从cicd-goat了解供应链安全风险(上)

admin 2024年12月31日00:03:08评论10 views字数 2243阅读7分28秒阅读模式

写在前面

最近在公司做 CI/CD 安全专项,做了很多调研,检测防护工具、方法论等,也分析过一些供应链投毒的 case,但总感觉不够系统不成体系。所以希望通过 cicd-goat 靶场,对整个研发运维流程中的风险能有一个较为全面的认知,事实上通过对靶场通关的研究也收获了不少。

在cicd-goat 靶场中我看到了很多容器技术的影子。其实,云原生和 CI/CD 的联系一直比较紧密,二者都是颠覆原有传统开发模式的革命性技术。很多 CI/CD 基础设施都用 Kubernetes、Docker 等容器技术搭建,同时 CI/CD 又以自动化、敏捷开发的特性便捷、迅速的为云原生环境输送容器化应用。

CI/CD 技术及其衍生出的新系统的引入,也为整个开发的生命周期带来了新的风险。本次文章将借用 Github 很火的 CI/CD 研究项目 cicd-goat,来窥探 CI/CD 的安全风险,除了通关记录之外也会做适当的拓展,本系列文章会在每一关最后穿插 CI/CD OWASP-Top10 的安全风险,以帮助大家更好了解 CI/CD 安全

由于这次内容较长,本系列主要分上、中、下三篇文章推送,第一篇主要简单介绍 cicd-goat 环境搭建,以及 Easy 部分;第二篇主要介绍 Moderate 部分;第三篇主要介绍 hard 部分,这一部分的关卡比较复杂,我会在每一关最后附上攻击路径草图供大家分析参考

总之,通关的过程不是很顺利,有借鉴大佬的思路,也有自己的摸索,学到很多东西。这里将自己通关的过程和坑点记录一下,如果有不对的地方,欢迎各位大佬指正。

一、通关前的准备

1.1 cicd-goat 项目简介

项目由Cider Security 公司(2022 年被Palo Alto Networks 收购)的安全研究者们创建和维护,下面摘自cicd-goat 官方 Github[1] 的简介(机翻):

CI/CD Goat 项目允许工程师和安全从业者通过一组 11 个挑战来学习和实践 CI/CD 安全性,这些挑战针对真实的、全面的 CI/CD 环境进行。这些场景的难度级别各不相同,每个场景都侧重于一个主要攻击媒介。

这些挑战涵盖了十大 CI/CD 安全风险[2],包括流量控制机制不足、PPE(中毒管道执行)、依赖链滥用、PBAC(基于管道的访问控制)等。

下面是靶场 Web 系统的访问地址和初始账号密码(普通用户),管理员用户的账密[3]在这里。一般情况下除非测试或排错之外,用管理员账号是不符合规则的,建议不要轻易使用。

环境
地址
登录密码
入口
http://{YOUR_IP}:8000/challenges
alice:alice
jenkins
http://{YOUR_IP}:8080/
alice:alice
Gitea
http://{YOUR_IP}:3000/
thealice:thealice
Gitlab
http://{YOUR_IP}:4000/
alice:ali12345

下面是官方的靶场架构图:

从cicd-goat了解供应链安全风险(上)

靶场关卡总览:

从cicd-goat了解供应链安全风险(上)

1.2 心理建设

就整个通关过程而言,还是有不少坑点的,主要分为下面几点:

  • • 国内网络环境原因
    • • 需要自己解决镜像拉取问题;
    • • 环境里默认的 Dockerfile 或 CI 构建文件中的安装过程会失败(需要添加国内源);
    • • gitlab 容器 terrform 初始化很容易出错,需要慢慢排错。
  • • 题目本身的复杂度
    • • 官方给的solutions[4] 比较简略,有的甚至不能顺利通关,个别关卡需要参考别人的 wirtup,或自己摸索;
    • • 网上找的国内外 wirteup 文章很少有能把 hard 部分详细写出来的。

在开始之前,首先心里要有个预期,很顺利的完成通关几乎是不可能的,排错的时候心态不要崩。相信你最后一定会收获很多。

1.3 环境搭建

本人是在 linux 主机上搭建的,如果您的笔记本内存充足也可以选择在本地电脑上搭建,建议至少预留 8G 内存。

1.3.1 环境搭建过程

环境的构建命令还是比较简单的,docker-compose 一键启动容器,支持 Linux、mac、windows。

Linux & Mac

curl -o cicd-goat/docker-compose.yaml --create-dirs https://raw.githubusercontent.com/cider-security-research/cicd-goat/main/docker-compose.yamlcd cicd-goat && docker compose up -d

Windows

mkdir cicd-goat;cd cicd-goatcurl -o docker-compose.yaml https://raw.githubusercontent.com/cider-security-research/cicd-goat/main/docker-compose.yamlget-content docker-compose.yaml |%{$_-replace "bridge","nat"}docker compose up -d

1.3.2 环境搭建的坑点和问题

注:Easy 和 Moderate 部分的关卡是用不到 Gitlab 的,Gitlab 环境调试比较麻烦,如果安装失败可以先不管,先进行前面的关卡。

1.3.1 解决镜像拉取的问题

国内的网络环境拉取镜像会有问题,但是也有解决办法。可以使用 docker 全局代理,也可以用国外 VPS --> 阿里云镜像仓库 --> 本地 的方式转存,也可以打成 tar 包在本地 load,这里不多说。

有位大佬也分享过一种方式,可以参考这篇文章

1.3.2 解决Gitlab卡慢的问题

用官方默认的安装方式安装后,Gitlab 会很卡,每个页面会加载 7~10s 左右(64G 内存主机)。所以需要修改一下 Gitlab 配置,防止卡顿,方便后面的操作。

# 进入gitlab容器docker exec-it gitlab bash# 修改gitlab配置文件vi /etc/gitlab/gitlab.rb# 在gitlab.rb文件最后添加如下内容## 减少内存,且防止卡puma['worker_processes']=4puma['per_worker_max_memory_mb']=2048sidekiq['concurrency']=16postgresql['shared_buffers']="256MB"postgresql['max_worker_processes']=8# 刷新配置gitlab-ctl reconfigure# 重启gitlabgitlab-ctl restart

1.3.3 Gitlab 容器内部terraform初始化失败的问题

Gitlab 模块的靶场在启动容器的时候使用 terrafrom 做了初始化,包括预置 token、创建仓库、创建包等等。

terrafrom 在初始化的时候会从先 hashicorp 官网安装一些 provider,以方便和目标资源进行交互。这里也经常会因为网络环境问题报错,一次安装不成功是很正常的,耐心调错即可。

从cicd-goat了解供应链安全风险(上)

调错时可以一边对照日志,一边对照容器的初始化脚本[5]。网络环境问题可以选择配置代理或换国内 terraform 的镜像源解决。

1.3.4 Gitlab pipline构建过程中的报错

pipline 报错的原因主要在安装依赖时网络环境问题,比如在 apk install 或 pip install 等情况下过程会非常慢,timeout 报错导致 pipline 终止是很常见。建议先用管理员账号统一替换成国内源,然后再进行构建。

1.4 前置知识了解

在开始之前,你需要先了解一下 Jenkins、Gitlab、Gitea 这些系统是干啥的,主要充当什么角色,如果能再了解一些基本的配置和操作就更好。受限于篇幅原因,我们这里做一个简要介绍,不会很深入。

  • • Jenkins是一个开源的自动化服务器,主要用于持续集成(CI)和持续交付(CD)。它支持各种开发、构建、测试和部署流程的自动化操作,是现代软件开发生命周期中不可或缺的工具之一;
    • • 随着技术的不断发展,也催生出一些更适用于云原生场景的 CICD 系统,比如Tekton、Argo CD 等,同时 Gitlab 也有自己的 CICD 模块,但从笔者的见到的一些情况来看 Jenkins 的使用还是最广泛的;
    • • 从安全角度来讲,Jenkins 类的 CICD 系统是一个非常重要的风险点,向左连接着代码管理仓库,承接着编译、构建、打包自动化的任务,同时向右连接着制品仓库、运行时环境可以实现自动部署。可想而知,系统中会存放大量的敏感凭据以支撑这一系列的操作,而其中任何一个凭据的泄露或管理不善,都有可能导致整个研发流程被投毒,导致风险点大面积扩散。
    • • CI/CD 配置文件在持续集成/持续部署(CI/CD)中,配置文件用于定义自动化构建、测试和部署的流程。不同的 CI/CD 平台(如 Jenkins、GitHub Actions、GitLab CI、CircleCI 等)有不同的配置格式,但基本上都是描述性文件。通过 CI/CD 配置文件,我们可以访问存储在 CI/CD 系统中的敏感凭据,并且可以执行任意命令。CICD 的攻击场景中,有一个重要的点就是想方设法对 CICD 配置文件(比如 Jenkinsfile)进行投毒,这也被称为 PPE(Poisoned Pipeline Execution,投毒管道执行)。
  • • Gitea 是一个轻量级、开源的自托管 Git 服务,类似于 GitHub、GitLab 和 Bitbucket。但它不提供 CICD 之类的功能,可以理解为它就是一个纯代码仓库。比较适合适合个人开发者、小型团队以及中小型企业。
  • • Gitlab 是一个基于 Git 的开源 DevOps 平台,和 Github 比较像,提供从代码版本控制到持续集成/持续交付(CI/CD)和部署全流程解决方案。在这次的靶场中,hard 部分才会涉及此系统。

如果你了解的还不是很深入,不用担心,可以先开始靶场了,在体验过程中你会进一步加深理解。

二、复现过程(Easy部分)

2.1 White Rabbit

2.1.1 题目与提示

从cicd-goat了解供应链安全风险(上)

题目与提示:

我迟到了,我迟到了!没有时间说“你好,再见”了!在被抓住之前,利用你对 Wonderland/white-rabbit 存储库的访问权限窃取存储在 Jenkins 凭证存储中的 flag1 机密。

🔔尝试通过存储库触发管道。

🔔如何使用 Jenkinsfile 访问凭证?

2.1.2 分析过程

首先,登录Gitea http://{YOUR_IP}:3000/,访问私有仓库Wonderland/white-rabbit中的代码,我们发现Jenkinsfile文件是可以直接修改的,所以将文件内容修改为如下:

pipeline {    agent any    stages {        stage ('poc'){            steps {                withCredentials([string(credentialsId:'flag1', variable:'msg')]){                    sh '''                        echo $msg | base64                    '''            }         }     }     }}

注意⚠️:由于Jenkins的Masks Passwords[6]插件的这个功能,在你打印凭据信息时会把真实的凭据隐藏,所以需要把它进行base64编码后再输出。

上面的步骤可以通过 gitea 页面操作,也可以使用下面git命令完成:

git clone http://{YOUR_IP}:3000/Wonderland/white-rabbit.gitgit checkout -b gitflag2vim Jenkinsfilegit commit --"cat flag"git push -u origin gitflag2

Jenkins的凭据(cerdentials[7])一般存储在/var/jenkins_home/credentials.xml文件中和用户目录下,前者作用于全局,后者作用于特定用户:

从cicd-goat了解供应链安全风险(上)

接下来需要创建一个合并请求,以触发 pipline 的执行从而打印 flag, 这个需要在gitea页面上操作:

从cicd-goat了解供应链安全风险(上)

创建后,可以看到jenkinsfile文件修改的明细:

从cicd-goat了解供应链安全风险(上)

同时,合并请求已经触发了jenkins的pipeline(PR-2),可以在jenkins后台http://{YOUR_IP}:8080/ 看到poc这个stage已经执行了:

从cicd-goat了解供应链安全风险(上)

可以在输出log中看到flag的base64编码:

从cicd-goat了解供应链安全风险(上)

最后base64解密输出,提交flag。

从cicd-goat了解供应链安全风险(上)

2.1.3 风险点

⚠️D-PPE(直接管道投毒执行)

这一关主要体现的风险在于直接管道投毒执行(D-PPE),它是OWASP CI/CD 类前十大风险中管道投毒执行(PPE)[8]的一个子类。主要是指攻击者在获取某个 SCM (如 gitlab、gitea、github 等)的凭据后,有权限直接修改仓库中的 CI 配置文件(如 Jenkinsfile),从而利用“push”或“PR”事件触发管道执行 CI 配置文件中的恶意命令。

攻击者可以通过 CI 文件的投毒,来获取构建节点上的权限或者读取 pipline 中预置的敏感凭据信息。在这一关中读取的 flag,那么在真实场景可能是 SSH 密码、镜像仓库 token、生产集群 kubeconfig 等等,危害可见一斑。

2.2 Mad Hatter

从cicd-goat了解供应链安全风险(上)

2.2.1 题目与提示

题目与提示:

Jenkinsfile 受到保护?听起来像是一个非生日聚会。使用您对 Wonderland/mad-hatter 存储库的访问权限窃取 flag3 机密

🔔 Jenkinsfile 存储在哪里?在 Wonderland 组织中搜索 repo 名称,您可能会找到一些有用的 repo。

🔔 Jenkinsfile 运行哪些命令?

2.2.2 分析过程

(1)发现没有权限直接修改CI配置文件

在代码仓库中,我们发现mad-hatter仓库中并没有Jenkinsfile文件,而Jenkinsfile文件被单独存储在mad-hatter-pipeline 仓库中。在现实情况下可能会因为安全性,devops 工程师将CI配置文件和代码分开存储。

从cicd-goat了解供应链安全风险(上)

下面是mad-hatter-pipeline项目中的Jenkinsfile内容:

pipeline {    agent any    environment {        PROJECT ="yagmail"    }    stages {        stage ('Install_Requirements'){            steps {                sh """                    virtualenv venv                    pip3 install -r requirements.txt || true                """            }        }        stage ('Lint'){            steps {                sh "pylint ${PROJECT} || true"            }        }        stage ('Unit Tests'){            steps {                sh "pytest || true"            }        }        stage('make'){            steps {              withCredentials([usernamePassword(credentialsId:'flag3', usernameVariable:'USERNAME', passwordVariable:'FLAG')]){                sh 'make || true'            }        }   }   }    post {        always {            cleanWs()        }    }}

我们注意到第四个stage,也就是Jenkinsfile的make阶段,使用了凭证绑定[9]技术,也就是将凭证绑定到环境变量以供各种构建步骤使用。如果没有权限限制,我们其实可以直接打印出FLAG环境变量的内容来获取flag。

从cicd-goat了解供应链安全风险(上)

但是,我们发现没有权限直接修改Jenkinsfile文件

从cicd-goat了解供应链安全风险(上)

(2)投毒CI配置文件引用的Makefile

虽然无法直接修改Jenkinsfile文件,但是Jenkinsfile执行make操作的时候会引用Makefile,也就是说我们可以通过投毒Makefile 来间接投毒管道。

一定要注意,因为Makefile格式限制,命令前面是一个TAP键,不能用4个空格代替,也不能 copy 别人的粘贴过来。

从cicd-goat了解供应链安全风险(上)

否则就会出现下面的报错:

从cicd-goat了解供应链安全风险(上)

修改好Makefile并push到thealice-patch-3分支,然后创建合并请求。

从cicd-goat了解供应链安全风险(上)

当然,上述操作也可以通过git完成:

git clone http://{YOUR_IP}:3000/Wonderland/mad-hatter.git# 创建一个新分支并切换到该分支git checkout -b thealice-patch-3# 修改Makefile文件vim Makefile# 将变化区的文件先从工作区提交到暂存区,然后将暂存区中的变化提交到仓库区git commit --"get flag2"# 将本地分支thealice-path-3推送到远程仓库origin,并设置一个上游分支(下次就可以直接git push了)git push --set-upstream origin thealice-patch-3

(3)获取 flag3

随后到Jenkins中查看make的log输出:

从cicd-goat了解供应链安全风险(上)

解码下面的base64提交即可:

从cicd-goat了解供应链安全风险(上)

2.2.3 风险点

⚠️I-PPE(间接管道投毒执行

间接管道投毒执行(I-PPE)与直接管道投毒执行(D-PPE)不同的是,I-PPE 是在没有权限直接修改代码仓库中的 CI 配置文件的情况下,通过修改 CI 配置文件中引用(依赖)的文件,比如 Makefile、shell 脚本、第三方工具等,间接的方式达到管道投毒的目的。这一点其实比较好理解。

2.3 Duchess

从cicd-goat了解供应链安全风险(上)

2.3.1 题目与提示

如果每个人都管好自己的事,世界就会比现在更快地运转起来。这也适用于你的秘密吗?你可以访问 Wonderland/duchess 存储库,该存储库大量使用 Python。公爵夫人非常关心她的凭证的安全性,但肯定有一些 PyPi 令牌留在某个地方……你能找到它吗?

🔔 PyPi 令牌的前缀为“pypi-”。

🔔 过去可能犯过错误。

2.3.2 分析过程

从题目来看flag应该是泄露在duchess仓库中的某个地方,并且前缀为"pypi-"。

方法 1 翻找历史commit

因此可以先从仓库的commit记录中检索“token”或“pypi”等字眼,然后一个一个去翻找前缀为"pypi-"的flag。这一点在实战中很受用。

从cicd-goat了解供应链安全风险(上)

最终可以在“remove pypi token”的commit记录中找到flag,如下图:

从cicd-goat了解供应链安全风险(上)

但是,如果commit记录比较多的话,这样的方式比较低效。我们可以借助工具--gitleaks。

方法 2 第三方工具扫描

首先将Wonderland/duchess仓库clone到本地,应该是公开仓库,clone不需要输入密码:

 git clone http://{YOUR_IP}:3000/wonderland/duchess.git

然后利用gitleaks[10]检测仓库中的敏感凭据信息:

gitleaks 是一个 SAST 工具,用于检测和防止git repos 中的硬编码隐私,如密码、api 密钥和令牌;支持丰富的secret类型,可以自定义规则,不仅可以扫描最新的源代码,还能回溯整个git历史记录。

⚠️需要注意git不能是低版本,否则gitleaks会报错,应该升级到git 2.x版本

# 进入仓库cd/opt/duchess# gitleaks检测gitleaks detect -v

从cicd-goat了解供应链安全风险(上)

从检测的信息中可以查找出pipy的凭据信息:

从cicd-goat了解供应链安全风险(上)

但是secret显示的不够全,所以需要利用git show <commit-hash>获取历史信息,进一步获取到pypi token的完整信息。

git show 43f216c2268a94ff03e5400cd4ca7a11243821b0

从cicd-goat了解供应链安全风险(上)

最后提交pypi的完整token即可。

2.3.3 风险点

⚠️凭证管理不当

凭证管理不当[12]Insufficient credential hygiene的风险主要涉及攻击者能够通过流水线中存在的访问控制漏洞、不安全的凭据管理以及过于宽松的凭证,获取并使用分布在流水线中的各种密钥和令牌。

常见的风险有以下几个点:

  • • 代码中包含硬编码的凭据被推送的代码仓库中:这也是这一关体现的风险点。开发人员由于疏忽或缺乏安全意识将密钥硬编码在代码中,这是比较常见的问题,甚至很多 CVE 漏洞的底层原理也是硬编码。
  • • 在构建部部署过程中不安全的使用凭据:比如将明文密钥硬编码在 CI/CD 配置文件中;CI/CD 系统中的凭据没有设置合理的作用范围;凭据可以被未经审查的代码访问;凭据在管道中使用完之后没有及时清理等。
  • • 容器镜像层中的硬编码凭据:这个也是比较常见的现象,任何可以下载镜像的人都能访问凭据
  • • 打印到控制台输出的凭据:比如在 Jenkins 中的 console log 中打印出明文的凭据,或者在其他日志文件中记录明文凭据;
  • • 长期未轮替的凭据:这个和密码管理是一个道理,但 CI/CD 系统中存在大量的各种系统的凭据,研发或运维人员经常为了方便,凭据都设置较长的有效期。同时又遵循着“如果没有问题,就不要修复”的原则,导致凭证多年没有更换,攻击队(或黑客)可能拿着同一个凭据打好几年。

TIPS:修复代码中的硬编码问题,不是仅删除当前代码中的硬编码就够了,也需要删除 commit 历史记录中的敏感信息。如果打包了或者构建了镜像,也应该清理相关制品中的硬编码。

预告

下一篇将介绍Moderate 部分的通关记录,以及每一个关卡引申出来的安全风险,敬请期待!

引用链接

[1] CICD-Goat 官方 Github:https://github.com/cider-security-research/cicd-goat[2]十大 CI/CD 安全风险:https://owasp.org/www-project-top-10-ci-cd-security-risks/[3]管理员用户的账密:https://github.com/cider-security-research/cicd-goat/blob/main/break-glass.md[4]solutions:https://github.com/cider-security-research/cicd-goat/tree/main/solutions[5]初始化脚本:https://github.com/cider-security-research/cicd-goat/blob/main/gitlab/run.sh[6]Masks Passwords:https://plugins.jenkins.io/mask-passwords/[7]cerdentials:https://www.jenkins.io/zh/doc/book/using/using-credentials/[8]管道投毒执行(PPE):https://owasp.org/www-project-top-10-ci-cd-security-risks/CICD-SEC-04-Poisoned-Pipeline-Execution[9]凭证绑定:https://plugins.jenkins.io/credentials-binding/[10]gitleaks:https://github.com/gitleaks/gitleaks[11]secret 类型:https://github.com/gitleaks/gitleaks/tree/master/cmd/generate/config/rules[12]凭证管理不当: https://owasp.org/www-project-top-10-ci-cd-security-risks/CICD-SEC-06-Insufficient-Credential-Hygiene

原文始发于微信公众号(喵苗安全):从cicd-goat了解供应链安全风险(上)

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年12月31日00:03:08
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   从cicd-goat了解供应链安全风险(上)https://cn-sec.com/archives/3572991.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息