返回首页

Git 中的恶意合并:合并提交中的恶意软件

文章描述了通过 Git 中的恶意合并进行的攻击:将混淆代码注入合并提交。负载使用区块链进行 C2。介绍了一个 Go 检测器,用于自动化仓库扫描。

恶意合并:代码中潜伏 3.5 个月
Advertisement 728x90

邪恶合并:隐藏在Git合并提交中的恶意代码

在一个项目的vite.config.js文件中发现了恶意、混淆的代码。它并非通过拉取请求(PR)引入,而是在冲突解决期间直接出现在合并提交中。GitHub的PR视图仅显示功能分支的差异,忽略了合并提交本身所做的更改。使用git log分析发现,一个合并提交的父提交相同,但文件内容被篡改。

父提交的MD5哈希值匹配:

  • 父提交1:aa82acb0c335430d8300b6cb306dc824(干净)
  • 父提交2:aa82acb0c335430d8300b6cb306dc824(干净)
  • 合并提交:2a54754defae4d13aab39f256738dbbf(已修改)

在三方合并中,当父文件相同时,Git应产生不变的结果。任何差异都表明在合并过程中进行了手动编辑。

Google AdInline article slot

注入与混淆机制

恶意负载被注入到不同模块的两个文件中。贡献者在PR中点击合并按钮时添加了负载。该代码在npm run devnpm run build期间执行了3.5个月。

混淆技术包括:

  • 使用数字种子打乱字符串(如requiremoduleconstructor)进行重构。
  • 使用Function而非eval以绕过静态分析。
  • 使用字符替换表的自定义解码器。

负载不包含URL或IP地址。相反,它:

Google AdInline article slot
  • 查询TRON钱包的最新交易。
  • 提取BSC交易哈希。
  • 向BSC节点发起JSON-RPC eth_getTransactionByHash调用。
  • 从交易的input字段中XOR解码代码。

如果TRON不可用,则使用Aptos作为备用方案。执行使用child_process.spawn,设置detached: truestdio: 'ignore',并有一个30秒计时器以对抗监视模式检测。

未被发现的原因

  • GitHub不在PR中显示合并提交的差异。
  • git log不显示更改;需要使用git diff <parent1>..<merge>
  • 代码通过空格被移动到第200列之后。
  • SAST工具因缺乏签名而失败:没有eval、URL或base64。

这种技术被称为邪恶合并——一种引入父提交中均不存在的更改的合并(gitglossary(7))。Git维护者在2013年描述过它,但检测工具很少。

邪恶合并检测器:自动化扫描工具

一个用Go编写的检测器通过比较预期的三方合并结果(通过共同祖先)与实际合并提交来工作。差异表明手动编辑。

Google AdInline article slot

用法:

evilmerge scan /path/to/repo

选项:

  • --format=sarif用于GitHub代码扫描。
  • 严重级别:手动冲突解决与无冲突编辑。

集成:

  • GitHub Action:

```yaml

- uses: fimskiy/Evil-merge-detector@v1

with:

fail-on: warning

```

  • GitHub应用:PR检查和历史回顾扫描。
  • GitLab、Bitbucket和自托管设置(预接收钩子)的模板。

缓解措施与工作流漏洞

通过贡献者访问进行攻击:合法提交后,在合并期间注入。PR本身保持干净。

建议:

  • 使用线性历史(压缩/变基)。
  • 在服务器上实现预接收钩子。
  • 在GitHub上:启用“关闭过时审查”以在PR分支更改时要求重新审查。

GitHub确认这是有意设计,未来可能限制。当前措施侧重于预防而非检测。

关键要点

  • 邪恶合并是合并提交中手动编辑的官方术语。
  • 负载使用区块链(TRON/BSC/Aptos)进行命令与控制,无需URL/IP。
  • 基于Go的检测器扫描历史并集成到CI/CD中。
  • 在有CI和代码审查的项目中,3.5个月未被发现。
  • GitHub暂无更改合并工作流的计划。

— Editorial Team

Advertisement 728x90

继续阅读