Mika Ayenson, PhD

CI/CD 管道滥用:无人关注的问题

我们如何构建了一个开源的即插即用 CI 模板,该模板使用信号提取和 LLM 推理来捕捉 GitHub Actions、GitLab CI 和 Azure DevOps 管道中的 CI/CD 滥用行为。

阅读时间:9 分钟Detection Engineering, Enablement, Tools

前言

在 2025 和 2026 年,我们看到整个行业都出现了一种模式。攻击者不再直接攻击生产服务器,而是开始攻击部署到生产服务器上的自动化系统。开发人员凭据被破坏,工作流文件被修改,CI/CD 环境中的所有秘密突然都流向了攻击者控制的端点。我们看到这种情况在涉及大型开源项目《财富》 500 公司关键基础设施工具的事件中不断上演。

攻击链非常简单:

开发人员凭证被盗 → 工作流文件被修改 → 获取 CI 秘密 → 向云端和生产端横向移动

今天,我们开源了cicd-abuse-detector,它是一个即插即用的 CI 模板,使用基于 regex 的信号提取和 LLM 分析来检测 CI/CD 管道中的可疑更改。它可在 GitHub Actions、GitLab CI 和 Azure DevOps 上运行,并围绕公开安全研究中记录的真实世界攻击技术而设计。

关键要点

  • CI/CD 环境是高价值目标,因为单个受损工作流可同时外泄云凭证、包注册表令牌、代码签名密钥、部署密钥和 OIDC 令牌
  • 该工具可从差异中提取 50 多种 regex 和元数据信号,然后将它们与完整差异一起传递给 Claude 进行结构化威胁分析。无 Python,除 bash 和 Claude Code CLI 外无其他依赖项
  • 针对Nord StreamGato-X 等攻击性工具包以及ArtiPACKEDHackerBot-Claw等真实事件测试了检测模式
  • 该项目附带 19 以特定事件为蓝本的恶意差异和四个良性差异示例,以及验证每个信号的自动测试套件。

为什么 CI/CD 管道是首要目标

如果你花时间查看 GitHub Actions 或 GitLab CI 配置,你可能会注意到这些文件中集中了多少信任。典型的部署工作流程可以同时访问 AWS 凭据、npm 发布令牌、Docker Hub 密码和具有写入权限的 GitHub 令牌。攻击面不是带有 CVE 的服务器,而是 YAML 文件。

大规模采集凭证

攻击者利用窃取的开发人员凭证修改工作流程,外泄 CI 环境中的机密。9 月份的GhostAction 活动 2025 就大规模地证明了这一点,它损害了 817 资源库中的 327 GitHub 用户。有 3,325 项机密通过注入的工作流文件被窃取,这些文件将凭证 POST 到攻击者端点。

Shai-Hulud npm 蠕虫走得更远。这种自传播攻击通过 gh auth 令牌获取 GitHub 个人访问令牌,运行TruffleHog进行秘密侦查,并使用受损令牌将恶意代码悄悄注入同一开发人员拥有的其他软件包。仅第一波就发布了 46 000 多个恶意程序包。

利用特权触发器

pull_request_target 触发器是 GitHub Actions 中最危险的功能之一。与普通的 pull_request 触发器不同的是,它在基础版本库的上下文中运行工作流,并能访问机密,但它可以从不受信任的分叉中执行代码。Orca"Pull Request Nightmare"研究针对谷歌、微软和英伟达维护的软件源演示了这一点。

2026 年 2 月,一个名为HackerBot-Claw 的自动活动系统地扫描了公共资源库,以查找这种错误配置。它使用了五种不同的利用技术,包括中毒 Goinit() 函数、分支名称命令注入、基于文件名的注入、直接脚本注入,以及针对基于克劳德的代码审查员的人工智能提示注入。在最严重的案例中,Aqua Security 公司的 Trivy 存储库遭到全面破坏,导致下游供应链攻击,近 7000 台机器上的 33000 个机密被泄露。根据记录,这种供应链攻击是通过被盗的代币实现的,这些代币在最初被盗几周后仍然有效。

分类法的其他部分

除了凭证获取和触发器利用,该威胁模型还涵盖了公开研究中经常出现的另外四类威胁:

  • 权限升级,增加 "全部写入 "或 "id-令牌:写入 "权限,可扩大任何入侵的爆炸半径
  • 针对运行程序,将作业重定向到通常可通过网络访问内部基础设施的自托管运行程序,或指定攻击者控制的容器映像
  • 通过可变操作引用(使用 @main 代替 SHA 引脚版本)、远程脚本执行 (curl |bash)、锁文件注册表交换和依赖中毒操纵供应链
  • 通过提交时间戳篡改进行防御规避,使恶意文件看起来更旧、更可信。KL4R10N 在与朝鲜有关的活动中 记录了 这种技术,其中追溯的提交引用了在声称日期并不存在的基础设施

每项技术都与特定的MITRE ATT&CK 技术相对应:T1552(不安全凭证)、T1195(供应链破坏)、T1070.006(Timestomp)和T1059(命令和脚本解释器)。

探测器如何工作

我们希望模板无需 Python、自定义运行时或复杂的依赖关系即可运行。在默认的 ubuntu-latest 运行程序上,一切都在标准的 shell 工具中运行,唯一安装的工具是通过 npm 安装的Claude Code CLI,它可以处理身份验证、重试和模型路由。

第 1 阶段:过滤和扩散

当拉动请求被打开(或推送到受保护的分支上)时,工作流会在 CI/CD 相关路径的三个层级中识别已更改的文件。第一层涵盖工作流定义、管道配置和 Makefile 等核心 CI 文件。第二部分涉及构建和发布工件,如 Dockerfiles、包清单、锁定文件以及签名或部署脚本。第三层获取开发环境配置,如 .vscode/tasks.json 和 .devcontainer文件

每个文件单独进行差异化处理,上限为 10,000 个字符。我们是按文件而不是全局来做这项工作的,因为合并 diff 上的单个上限是一个旁路向量。攻击者可以用大量良性 Dockerfile 编辑来填充恶意工作流更改,从而使漏洞利用超过字符限制。

第 2 阶段:信号提取

在 LLM 看到任何内容之前,50 多种 regex 模式会扫描每个差异,查找已知的危险模式。这些信号是咨询性的。他们从不对分析结果进行把关,但会向法律硕士提供一份预先筛选过的威胁摘要。举几个例子:

信号图案它能捕捉到什么
secrets_context${{.*secrets.工作流程中的直接密文插值
pull_request_targetpull_request_target赋予公关代码秘密的危险触发器
checkout_refref:.*github.event.pull_request.head.(sha|ref)在特权环境下签出不受信任的 PR 代码
double_base64base64.*|.*base64双重编码以规避日志屏蔽(北溪技术)
ld_preloadLD_PRELOAD通过环境变量注入执行任意代码
vscode_auto_taskrunOn.*folderOpen打开文件夹时执行的 VS 代码任务(传染性访谈)

信号列表基于真实的对抗工具,包括Nord StreamGato-X,并针对 19 以特定事件为模型的恶意示例差异进行了测试。

该检测器在 GitHub Actions、GitLab CI 和 Azure DevOps 上的运行方式完全相同。下面是在每个平台上发射的探测器:

第 3 阶段:LLM 分析

信号摘要、完整差异、作者简介和提交元数据被捆绑在一起,并通过 Claude Code CLI 发送给 Claude。分析提示通过几个方面对模型进行引导:

  1. 差异理解和每个文件的风险评估
  2. 结合上下文进行信号解读(仅有信号并不代表判决)
  3. 追溯提交的时间分析
  4. 使用账户年龄、缴款历史和组织成员资格进行作者信任评估
  5. 根据包含 60 多个条目的信号组合表进行严重性校准
  6. 假阳性识别(例如,下载已知工具的 cURL 并非外泄行为)
  7. 具体、可操作的建议 ("将 actions/setup-node@main 引到特定的 SHA" ,而不是"仔细审查")

输出结果是一个结构化的 JSON 判决,其中包含严重程度、可信度、推理、证据和建议,所有这些都根据JSON 模式进行了验证。

第 4 阶段:警报和闸门

根据判定的严重性,工作流程会发布步骤摘要、创建问题、发送 Slack 通知,如果严重性达到配置的阈值,还可选择不进行 PR 检查。

Slack 和 GitHub Issues 中的警报解决了即时通知的问题,但它们无法提供可查询的历史记录。探测器产生的每一个判决(例如良性、可疑或恶意),可以选择以结构化文档的形式发送到 Elasticsearch 的日志-cicd.abuse-default 中。数据流。该工作流将判决书与 CI/CD 元数据(平台、存储库、角色、事件类型、运行 URL)一起传送到跨越所有三个支持平台的单一索引中。

这就是跨平台关联变得实用的原因。来自同一行为者的 GitHub 行动警报和 GitLab CI 警报会出现在同一数据流中,可通过单个 ES|QL 语句进行查询:

FROM logs-cicd.abuse-* 
WHERE verdict.verdict IN ("malicious", "suspicious") AND @timestamp > NOW() - 7 days 
EVAL platform = cicd.platform, repo = cicd.repository, actor = cicd.actor, severity = verdict.severity
KEEP @timestamp, platform, repo, actor, severity
SORT @timestamp DESC

模式包括 cicd.platform、cicd.repository、在此基础上,我们可以使用 cicd.actor,以及完整的判决对象(判决、严重程度、可信度、摘要、原因、证据),从而直接建立检测规则。一小时内打击多个 repos 的协调活动、跨平台标记的惯犯或需要事件响应页面的关键发现激增,都可以被关联起来。

针对真实攻击进行验证

为了验证覆盖范围,我们将检测模式与攻击工具的实际源代码、已发表的研究成果和公开的事后分析进行了比较。

北溪管道:逐字匹配有效载荷

Nord Stream 是 Synacktiv 的开源 CI/CD 秘密提取工具,支持 GitHub、GitLab 和 Azure DevOps。我们调出 YAML 生成器源代码 (nordstream/yaml/github.py) 并将其输出模板与示例差异进行比较。

  • GitHub payload 模板使用env -0 | awk -v RS='0' '/^secret_/ {print $0}' | base64 -w0 | base64 -w0 。我们的nord-stream-pipeline-exfil.diff 逐字包含这一行,而我们的double_base64env_null_dumpenv_secret_grep 信号都会发射。
  • OIDC Azure 模板使用azure/login@v1 ,权限为id-token: write ,然后是 az 账户get-access-token | base64 -w0 | base64 -w0 。我们的差分捕捉到了这一精确流量,并触发cloud_auth_actionid_token_write
  • Azure DevOps 管道技术(用于暴露 SPN 凭据的addSpnToEnvironment 、用于安全文件窃取的DownloadSecureFile 、通过ssh.js 修改 SSH 任务源补丁)都存在于nord-stream-azure-devops.diff 中,并通过特定平台信号进行检测。

ArtiPACKED:人工制品竞赛条件

来自 Palo Alto Unit 42 的ArtiPACKED研究表明,将整个检出目录作为工件上传会泄露包含GITHUB_TOKEN.git/config 文件。由于 v4 工具应用程序编程接口允许在运行过程中下载,攻击者可以在任务完成前提取并使用令牌。

我们的artifact-token-leak.diff 正是以这种模式为模型,使用upload-artifactpath: . (整个工作区)。upload_artifact 信号会捕捉到它,LLM 会评估上传范围是否包括.git 目录。

GITHUB_ENV 注入:LD_PRELOAD 至 RCE

Legit Security 对 Google Firebase 和 Apache 的 研究 表明,向$GITHUB_ENV 写入不受信任的输入,允许攻击者设置任意环境变量(如LD_PRELOADNODE_OPTIONS ),从而在特权工作流中实现代码执行。

我们的github-env-injection.diff 用三种不同的有效载荷重现了这一技术,包括指向恶意共享对象的LD_PRELOAD 、带有所需注入的NODE_OPTIONS 和 $GITHUB_PATH 操作。github_env_writeld_preloadgithub_path_write 信号均按预期触发。

传染性访谈:IDE 配置作为初始访问

朝鲜发起的 "传染性面试 "活动通过伪造工作面试,向开发人员分发带有.vscode/tasks.json 文件的存储库,这些文件会在文件夹打开时自动执行。呈现方式是隐藏的(reveal: never,echo: false ),有效载荷使用curl |node 进行静默执行。

我们的ide-config-poisoning.diff 捕获了完整的攻击链,包括自动执行触发器 (runOn: folderOpen)、隐藏的演示、curl | node 有效载荷、隐藏.vscode 目录的files.exclude 条目,以及带有 base64 编码 URL 的木马化安装后钩子和用于执行代码的eval() 。六个信号同时接收。

防御建议

除了部署检测器外,我们还根据所研究的攻击模式采取了一些加固措施:

  • 将所有操作固定到 SHA,而不是标签或分支。SHA 销值引用可防止追溯标签修改攻击,如tj-actions (CVE-2025-30066)。
  • 将秘密范围扩大到单个步骤,而不是使用作业级环境变量。每个步骤只能访问其实际需要的机密。
  • 尽可能使用寿命短、短暂的令牌,以减少攻击面
  • 除非绝对必要,否则避免使用pull_request_target 。如果必须使用,切勿在同一工作流程中检出 PR head 代码。对于同时需要机密和 PR 上下文的操作,请使用单独的workflow_run-triggered workflow
  • 为每个工作流设置明确的权限,因为默认令牌权限过于宽泛。在工作流程级别设置permissions: {} ,并为每个任务添加特定权限。
  • 在结账时启用persist-credentials: false ,因为 actions/checkout 的默认行为会将GITHUB_TOKEN 保存在.git 目录中。如果您上传了人工制品,此标记也会随之上传。

总结

CI/CD 管道已成为供应链漏洞的主要攻击面。使现代软件交付成为可能的自动化,正是攻击者用来获取凭证、毒化软件包和转移到云基础设施的工具。传统的代码审查并不能很好地捕捉到这些模式,因为它们很微妙、特定于平台,而且被设计成合法的 DevOps 变更。

通过将基于 regex 的信号提取与 LLM 推理相结合,我们可以在拉取请求阶段就发现这些模式,然后再将其应用到生产中。如果您想深入了解细节或根据自己的环境进行调整,该 repo 包括完整的威胁模型、测试套件和示例差异。

要开始使用,请查看cicd-abuse-detector repo以获取设置说明、完整的威胁模型和示例差异。我们一直对新的攻击模式和检测理念感兴趣。在我们的社区 Slack 上与我们聊天,在我们的讨论论坛上提问。

通过 MITRE ATT&CK 滥用 CI/CD

我们使用MITRE ATT&CK 框架来映射对手针对 CI/CD 管道使用的战术、技术和程序。

战术

战术CI/CD 相关性
凭证访问(TA0006)从 CI 环境中获取机密
执行(TA0002)在管道运行程序中运行命令
持久性(TA0003)计划触发器、基于 cron 的工作流程
防御回避 (TA0005)提交时间戳篡改、日志掩码规避
初始访问 (TA0001)开发人员证书受损,PAT 网络钓鱼
横向移动(TA0008)利用收获的云凭据进行透视

技术

技术CI/CD 应用
T1552:无担保凭证在 CI 环境变量、工件和运行内存中暴露的秘密
T1195.002:破坏软件供应链中毒的操作、依赖关系和锁定文件
T1059:命令和脚本解释器curl
T1070.006:计时器回溯提交日期以逃避审查
T1098:账户操纵通过全部写入权限升级,id-令牌:写入
T1078:有效账户被盗的开发人员 PAT 用于修改工作流程

参考资料

上述研究参考了以下内容:

关于 Elastic 安全实验室

Elastic Security Labs 是 Elastic Security 的威胁情报分支,致力于在威胁形势中创造积极变化。 Elastic Security Labs 提供有关新兴威胁的公开研究,并分析对手的战略、运营和战术目标,然后将该研究与 Elastic Security 的内置检测和响应功能相结合。

在 Twitter 上关注 Elastic Security Labs @elasticseclabs ,并在www.elastic.co/security-labs/查看我们的研究。

分享这篇文章