cicd-goat靶场解题记录Part1
在软件工程领域,CI/CD是持续集成、持续交付(或部署)的总称。CI/CD通过标准化的方式、自动化的手段,减少软件构建、测试、打包、部署过程中的人为干预,极大提高代码发布速度。
cicd-goat是一个专门配置的存在漏洞的CI/CD测试环境,覆盖由OWASP发布的CI/CD领域Top10的安全风险。这两者的作者都是由Cider Security公司,现已被Palo Alto Networks收购。
cicd-goat
cicd-goat的架构图如下:
靶场解题环境部署在CTFd平台,CI/CD环境分两类:
- 绝大多数环境采用Gitea进行代码版本管理,Jenkins进行CICD
- 难度为难的Gryphon采用Gitlab、Gitlab runner进行CICD
cicd-goat项目本身也是一个CI/CD环境,里面运用了一些我前面不熟悉的技术(例如使用Terraform对S3对象存储进行权限控制)。
通过对其自身环境的理解,也可以有助于理解CI/CD概念本身及其安全性,类似于HackTheBox博客文章It is Okay to Use Writeups里提到的“拿到root之后,花时间去理解环境是怎么运行的”。我打算后面再补充一篇分析cicd-goat运行环境文章。
参考项目README文档中的说明,下载docker-compose文件之后直接运行即可。
mkdir cicd-goat; cd cicd-goat |
解题记录
Part1中包含简单、中等两个难度题目的解题过程记录。
Easy
White Rabbit
在CI/CD环境中,关键点是找到我们(或者攻击者)能控制的内容如何能影响到Pipeline的运行。
在Jenkins的wonderland-white-rabbit项目扫描多分支Pipeline记录中,我们可以看到对Pull Requests有检查,这说明我们可能可以通过提交包含恶意内容的Pull Request,来窃取flag1
。
Jenkinsfile的说明文档中,有关于如何处理秘密信息和秘密文件的说明,比较简单的实现是声明环境变量,并在后续步骤中使用环境变量。
在Gitea修改Jenkinsfile文件,并提交Pull Request后,Jenkins重新扫描会识别到Pull Request、并运行PR的Jenkinsfile中定义的流程。
而在执行单元的日志中,可以看到环境变量的base64输出,解码之后即可看到明文的flag1
。
Mad Hatter
在Jenkins的wonderland-mad-hatter项目扫描多分支Pipeline记录中,并没有对PR的检查,而且Gitea里的mad-hatter项目中并没有Jenkinsfile文件,那么管道流是如何实现的呢?
进一步在Gitea项目中浏览,发现了一个mad-hatter-pipeline项目,只包含一个Jenkinsfile文件。其文件内容中包含flag3
凭证的处理:
stage('make'){ |
make
命令根据makefile
文件内容,进行自动化编译处理,恰巧在Gitea的mad-hatter-pipeline项目中有Makefile文件。
我修改Makefile
文件后发现管道流一直没执行,几番尝试后发现新建分支可以触发管道流。
(注:我回过头看最前面截图时发现,扫描日志中一开始就有Checking branches...
的输出,只不过最开始忽略了。🤦♂️)
随后在Build History中查看make编译过程的日志,即可得到flag。
Duchess
这一个题目需求在Git项目中需要到泄露的Pypi Token,我直接在文件中找了很久、也尝试去使用JWT解码代码中的测试字符串,都没通过。
最后在Git的提交历史中搜索到删除token的提交,查看详情即可看到泄露的Pypi Token。
这种泄露账号密码、API token的场景还挺常见。
- 首先不推荐将私有项目放在公有云仓库上;
- 其次如果放了敏感信息,最好的解决办法是删仓库,如果仓库被fork了,可以提交DMCA申请Github删;
- 如果不想删仓库的话,使用git-filter-repo等类似项目处理时要注意,有些文件存在Github上,可能通过这些文件拿到泄露的信息。可以参考这里
Medium
Caterpillar
这是很经典的一个题目,攻击者对Gitea上caterpillar项目拥有只读权限、可以提交PR,在Jenkins上caterpillar有生产环境和测试环境两种,生产环境对main分支持续集成,包含flag2
,而测试环境则对PR进行集成、但不包含flag2
。漏洞点在于测试环境环境变量中包含GITEA_TOKEN,攻击者可以使用这个TOKEN更新main分支代码。
首先fork代码、修改Jenkins文件,并提交PR:
在测试环境中拿到GITEA_TOKEN:
使用Gitea的API进行仓库内文件更新,需要注意的是filepath
参数不需要、也不能以/
开头,body
参数中其他无关内容建议删除、只保留content
和sha
即可:
随后即可在Jenkins上生产环境的日志中查看到flag2信息:
Cheshire Cat
Cheshire Cat需求用户将Jenkins构建任务运行在Jenkins Controller节点上。
Jenkins官方文档中对Pipeline语法的agent部分进行了说明,手册里并没写很详细,实际上我是在Github上搜索现有Jenkinsfile文件才知道如何去配置。
更新项目Jenkinsfile文件,使用agent {label 'built-in'}
指定Pipeline运行在控制节点上,同时删去无关代码、避免报错:
待管道流运行后,即可拿到flag5
:
Twiddledum
这是一个NodeJS环境的环境,实际执行的项目是twiddledum,但是这个项目引用了twiddledee,而后者我们能控制。
直接运行Jenkins中wonderland-twiddledum项目,在日志中可以看到运行twiddledee中index.js的记录:
此时修改twiddledee项目、植入需要测试的代码,并重新发包。
清理环境之后再次运行时,可以看到日志中出现了我们植入内容的记录:
实际测试时需要删除掉原有tags,添加新版本的release文件:
清理环境之后再次运行时,即可得到flag6
:
Dodo
Dodo使用Terraform进行S3对象存储的权限配置,并使用checkov对权限进行自动化检测。当代码仓库是任意人可读、并且通过权限校验时,给出flag7。
在checkov的文档中,给出了抑制/跳过检查的方法:
resource "aws_s3_bucket" "foo-bucket" { |
参照文档修改main.tf
文件:
再次运行Jenkins任务即可拿到flag7(注:如果运行过程中出现报错,需要多运行几次):