事件概述
2026年7月18日至19日,安全研究人员发现了一起针对RubyGems生态系统的协调供应链攻击,被命名为SleeperGem。攻击者通过劫持休眠多年的RubyGems维护者账户,发布了三个恶意gem包,专门设计用于在开发者机器上安装持久化后门,同时主动避开CI/CD流水线环境。
该攻击由StepSecurity和Aikido Security独立发现并报告。受影响的包包括冒充微软官方Git Credential Manager的git_credential_manager、休眠近六年的Dendreo,以及fastlane插件fastlane-plugin-run_tests_firebase_testlab——后者历史下载量超过57.4万次。
技术细节
恶意包清单
| 包名 | 恶意版本 | 特征 |
|---|---|---|
| git_credential_manager | 2.8.0 – 2.8.3 | 冒充微软官方工具,2.8.2起import-time触发 |
| Dendreo | 1.1.3, 1.1.4 | 休眠自2020年,无对应GitHub提交 |
| fastlane-plugin-run_tests_firebase_testlab | 0.3.2 | 无对应GitHub标签,上游标签止于v0.3.1 |
CI环境规避机制
SleeperGem最显著的特征是其主动规避CI/CD环境的策略。恶意代码在触发前会检查约30个CI平台环境变量,包括GitHub Actions、GitLab CI、CircleCI、Travis、Jenkins、Vercel等。一旦检测到任何CI标记,代码立即退出,不执行任何恶意行为。
这种设计的战术意图很明确:
- CI runner:生命周期短、日志密集、通常作业完成后即销毁——不利于持久化,且高概率被发现
- 开发者笔记本:长期在线、持有SSH密钥和云凭证、可直接访问私有仓库、缺乏同等级的安全监控
这意味着”我们在CI中扫描依赖”的传统安全模型对此攻击完全失效。
攻击流程与持久化
在确认运行在开发者机器上后,恶意gem执行以下操作:
- 下载第二阶段:通过Ruby内置HTTP客户端(禁用TLS证书验证)从攻击者控制的Forgejo主机下载shell脚本和原生二进制文件
- User-Agent伪装:将HTTP请求的User-Agent设为”Git”,混入正常Git流量
- 安装守护进程:在
~/.local/share/gcm/目录下释放原生守护进程 - 建立持久化:通过systemd用户服务和cron任务确保跨重启存活
- 权限提升:在具备passwordless sudo的系统上,创建setuid root shell(伪装为
/usr/local/sbin/ping6)
影响评估
SleeperGem的攻击模式揭示了软件供应链安全的新威胁维度:
- 休眠账户武器化:长期不活跃的维护者账户被重新激活并用于分发恶意代码,registry层面缺乏有效监控
- CI盲区利用:专门针对大多数企业安全 instrumented 的CI环境之外的开发者工作站
- 广泛暴露面:fastlane插件的57万+历史下载量意味着潜在影响范围覆盖大量移动开发团队
- 多账户入侵:受影响的包分属不同维护者账户,表明攻击者至少入侵了两个独立账户
修复建议
紧急处置(如曾安装受影响版本)
StepSecurity明确指出:仅卸载gem不足以清除威胁。如确认安装过受影响版本,应执行以下清理:
- 立即轮换所有凭据:SSH密钥、云访问密钥、Kubernetes凭据、GitHub/GitLab令牌
- 删除目录:
rm -rf ~/.local/share/gcm/ - 检查并删除所有site-packages中的
mmcompat.pth文件 - 清理cron任务:
crontab -l,删除指向恶意二进制文件的条目 - 检查systemd用户服务:
systemctl --user list-units,删除可疑服务 - 检查shell配置文件(
~/.bashrc、~/.zshrc),删除可疑代码块 - 检查是否存在
/usr/local/sbin/ping6setuid文件 - 将被影响的开发者机器视为完全失陷,必要时重新镜像
供应链安全加固
- 对PyPI/RubyGems/npm发布凭证实施定期轮换和MFA保护
- 将依赖包版本与源码仓库的发布标签和提交记录交叉验证
- 在CI和开发者机器上均部署依赖安全扫描(SCA)工具
- 对长期休眠的维护者账户设置重新激活的额外审核机制
- 使用私有registry或缓存代理,增加恶意包发布的检测窗口