文章总结: Shai-Hulud是由TeamPCP开发的严重级供应链攻击框架,专门针对CI/CD管道(如GitHubActions和npm)进行植入。该工具具备多层规避检测机制(如俄语系统检测、进程守护)、系统化凭证收集能力(覆盖AWS/K8s/Vault等200+敏感路径),并通过加密外传至C2或GitHub私有仓库。内置横向移动模块可劫持GitHubtoken进行仓库渗透,且包含破坏性deadmanswitch机制(如触发rm-rf清除数据)。攻击者需替换C2和密钥后部署,建议企业严格审查第三方依赖并监控异常CI行为。 综合评分: 85 文章分类: 恶意软件,供应链安全,漏洞分析,威胁情报,安全工具
AI 生成 | Shai-Hulud (TeamPCP) 源码分析
原创
GLM-5.1 GLM-5.1
赛博生存指南
2026年5月15日 21:22 浙江
在小说阅读器读本章
去阅读
生成日期:2026-05-15 分析对象:Shai-Hulud Open Source Release 威胁分类:供应链攻击 / 凭证窃取框架 风险等级:严重 (Critical) 官网:hxxps://supplychain.breached.st
1. 概述
Shai-Hulud 是一个高度复杂的供应链攻击与凭证窃取框架,由威胁行为者 “TeamPCP” 开发并公开源码。TeamPCP向BreachForums 社区开源 Shai Hulud。并宣布可以观测到的最大供应链攻击的运营商将从@diencracked获得1000美元XMR。
该工具设计为植入 CI/CD 管道(特别是 GitHub Actions 和 npm 发布流程),执行大规模凭证窃取、横向移动和数据外传。README 中的 “Change keys and C2 as needed” 直接表明这是一个供攻击者定制部署的武器化工具。包名伪装为 voicefromtheouterworld,构建产物使用 javascript-obfuscator 进行深度混淆。
2. 攻击链 (Kill Chain)
植入 (Injection)
↓
预检规避 (Pre-flight Evasion)
↓
快速收集 (Quick Collection) — 本地文件、环境变量、Shell 凭证
↓
横向扩展 (Lateral Movement) — AWS / K8s / Vault / GitHub Actions
↓
加密外传 (Encrypted Exfiltration) — C2 域名或 GitHub 私有仓库
↓
持久化/破坏 (Persistence / Sabotage) — Deadman Switch / OIDC 伪造
3. 核心组件分析
3.1 预检规避 (Anti-Detection)
相关文件: src/utils/config.ts, src/utils/daemon.ts, src/utils/lock.ts, src/index.ts
| 规避手段 | 实现细节 |
| — | — |
| 俄语系统规避 | isSystemRussian() 检测 locale 是否为 ru,若是则立即 process.exit(0) — 规避特定地区 |
| 非 CI 守护进程化 | daemonize() 在非 CI 环境中 spawn 子进程并 unref(),脱离终端 |
| 进程锁 | acquireLock() 使用文件锁防止多实例运行暴露异常 |
| 信号屏蔽 | 捕获 SIGINT/SIGTERM 为空操作,阻止 Ctrl+C 终止 |
| 目标仓库检查 | checkTargetRepo() 检查 GITHUB_REPOSITORY 是否为 opensearch-js,且 workflow 为 release-drafter.yml |
| 字符串混淆 | scramble() 函数 + env-scramble.ts 编译期将所有敏感字符串编码 |
关键代码 (src/index.ts:73-77):
if (isSystemRussian()) {
logUtil.log("Exiting as russian language detected!");
process.exit(0);
}
关键代码 (src/utils/daemon.ts):
const child = spawn(process.execPath, process.argv.slice(1), {
detached: true,
stdio: "ignore",
env: { ...process.env, __DAEMONIZED: "1" },
});
child.unref();
3.2 凭证收集 (Providers / 数据窃取层)
3.2.1 FileSystemService — 本地文件系统扫描器
相关文件: src/providers/filesystem/filesystem.ts
扫描 200+ 个敏感文件路径,覆盖三大操作系统:
主要目标类别:
| 类别 | 示例路径 |
| — | — |
| SSH 密钥 | ~/.ssh/id_rsa , ~/.ssh/id_ed25519, ~/.ssh/config |
| AWS 凭证 | ~/.aws/credentials , ~/.aws/config |
| GCP 凭证 | ~/.config/gcloud/credentials.db , application_default_credentials.json |
| Docker 凭证 | ~/.docker/config.json |
| Kubernetes | ~/.kube/config , /var/run/secrets/kubernetes.io/serviceaccount/token |
| 加密货币钱包 | ~/.bitcoin/wallet.dat , ~/.ethereum/keystore/*, ~/.monero/*, ~/.electrum/wallets/* |
| VPN 配置 | NordVPN, ProtonVPN, CyberGhost, OpenVPN 配置文件 |
| 环境变量文件 | .env , .env.local, .env.production |
| Git 凭证 | .git-credentials , ~/.gitconfig, .git/config |
| Terraform | ~/.terraform.d/credentials.tfrc.json |
| 浏览器/通讯数据 | Discord/Slack/Signal/Telegram 本地存储 |
| CI/CD 工具 | ~/.claude.json , ~/.claude/mcp.json, ~/.kiro/settings/mcp.json |
| 数据库配置 | **/database.yml , **/wp-config.php |
同时在文件内容中用正则匹配提取 gh[op]_* GitHub token 和 npm_* npm token。
3.2.2 ShellService — Shell 环境窃取
相关文件: src/providers/devtool/devtool.ts
- • 执行
gh auth token获取当前 GitHub CLI token - • 导出整个
process.env— 一次性获取所有环境变量
results["environment"] = process.env; // 完整环境变量泄露
3.2.3 GitHubRunner — 运行器元数据
相关文件: src/providers/ghrunner/runner.ts
收集 GitHub Actions 运行器环境信息。
3.2.4 AwsSecretsManagerService — AWS Secrets Manager 窃取
相关文件: src/providers/aws/secretsManager.ts
- • 自动解析 AWS 默认凭证链 (
resolveDefaultCredentials) - • 遍历 18 个 AWS 默认启用区域
- • 枚举每个区域的所有 Secret 并读取明文值 (
GetSecretValue) - • 包含完整的 SigV4 签名实现 (
src/providers/aws/sigv4.ts),不依赖 AWS SDK - • 内置权限错误分类和重试逻辑
3.2.5 AwsSsmService — AWS SSM Parameter Store 窃取
相关文件: src/providers/aws/ssm.ts
- • 遍历 18 个区域
- • 使用
DescribeParameters+GetParameters(含WithDecryption: true) - • 解密所有 SecureString 参数
- • 分批处理(每批 10 个),带指数退避重试
3.2.6 K8sSecretsService — Kubernetes Secrets 窃取
相关文件: src/providers/kubernetes/kubernetes.ts
- • 自动检测集群内/集群外环境
- • 读取 ServiceAccount token 或从 kubeconfig 提取 token
- • 枚举所有命名空间,读取所有 Secret
- • base64 解码所有 Secret data 值
- • 在 Secret 内容中进行 20+ 种正则匹配(AWS/GCP/Azure key, Stripe, Slack, SSH key, DB 连接串等)
3.2.7 VaultSecretsService — HashiCorp Vault 窃取
相关文件: src/providers/vault/vault-secrets.ts
支持 4 种认证方式:
- 1. 环境变量 token (
VAULT_TOKEN,VAULT_AUTH_TOKEN,VAULT_API_TOKEN) - 2. 文件 token (
~/.vault-token,/vault/token等 12 个候选路径) - 3. Kubernetes Auth(使用 K8s ServiceAccount JWT)
- 4. AWS IAM Auth
认证后:
- • 枚举所有 KV mount(排除
sys/和auth/) - • 遍历 KV v1 和 KV v2 存储
- • 读取所有 secret 的完整数据
3.2.8 GitHubActionsService — GitHub 横向移动
相关文件: src/providers/actions/actions.ts, src/providers/actions/secrets.ts, src/providers/actions/pipeline.ts
- • 使用窃取的 GitHub token,验证是否具有
workflow权限 - • 通过 REST API 列举用户所有仓库
- • 枚举每个仓库的 Actions Secrets 和 Organization Secrets
- • 通过 GraphQL API 批量操作
3.3 数据外传 (Exfiltration / Sender 层)
3.3.1 DomainSender — 主要 C2 通道
相关文件: src/sender/domain/sender.ts, src/sender/domain/domainSenderFactory.ts
- • C2 地址:
https://git-tanstack.com:443/router(伪装 TanStack 域名) - • 预检:DNS 解析验证 + HTTP 健康检查(接受 400/404 为健康)
- • 备用 C2 发现:通过
findValidSignedCommit()搜索 GitHub 上 GPG 签名消息为 “thebeautifulmarchoftime ” 的 commit,提取备用域名 - • 数据用混合加密保护(详见 3.3.3)
3.3.2 GitHubSender — 备用外传通道
相关文件: src/sender/github/githubSender.ts, src/sender/github/createRepo.ts
- • 在受害者 GitHub 账户上创建私有仓库
- • 通过 Contents API 分块上传窃取数据(每块最大 30MB)
- • 将加密密钥嵌入 commit message
内置破坏机制 — Deadman Switch (src/sender/github/githubSender.ts:58-76):
private async installTokenMonitor(token: string, handler: string) {
const proc = Bun.spawn(["bash", "-s", "--", token, handler], {
stdin: "pipe", stdout: "pipe", stderr: "pipe",
});
proc.stdin.write(DEADMAN_SWITCH);
proc.stdin.end();
}
当 includeToken 为 true 时,部署 deadman switch — 如果 token 被撤销,执行 rm -rf ~/ 清除受害者主目录。
3.3.3 加密流程
相关文件: src/sender/base.ts
原始数据 (ProviderResult[])
↓ JSON.stringify
↓ Buffer.from
↓ gzip 压缩
↓ AES-256-GCM 加密 (随机 32 字节 key + 随机 12 字节 IV)
↓ [IV + 密文 + authTag] → base64 (envelope)
随机 AES key
↓ RSA-OAEP + SHA-256 加密 (攻击者公钥, 来自 generated/index.ts)
↓ base64 (key)
→ { envelope: base64, key: base64 }
只有持有 RSA 私钥的攻击者能解密。
3.4 供应链攻击 (Mutator 层)
3.4.1 ReadmeUpdater (Branch Mutator)
相关文件: src/mutator/branch/
- • 使用窃取的 GitHub token (
ghs_old/ghs_jwt类型) - • 通过 GraphQL API 在目标仓库的分支上创建 commit
- • 修改仓库内容,注入恶意代码
- • 自动过滤 dependabot/copilot 分支,避免触发自动化检测
3.4.2 NpmClient — npm 包发布攻击
相关文件: src/mutator/npm/publish.ts
- • 使用窃取的 npm token 发布恶意包
- • 禁用 TLS 验证:
tls: { rejectUnauthorized: false } - • 伪装 User-Agent 为
npm/11.13.1
3.4.3 NPMOidcClient — OIDC Provenance 伪造
相关文件: src/mutator/npmoidc/provenance.ts
这是最危险的组件之一。 完整实现了 Sigstore 签名流程:
- 1. 构建 SLSA v1 provenance statement(in-toto 格式)
- 2. 通过 GitHub Actions OIDC 获取 sigstore audience token
- 3. 生成临时 ECDSA P-256 密钥对
- 4. 向 Fulcio CA 请求签名证书(proof-of-possession)
- 5. 创建 DSSE envelope 签名
- 6. 提交到 Rekor 透明日志
- 7. 组装 sigstore bundle v0.3
影响:恶意包可以拥有完全合法的签名证明链,绕过所有现有的供应链验证机制。
定向攻击目标:OpenSearch-JS 仓库的 release-drafter.yml workflow。
4. 混淆与构建基础设施
相关文件: scripts/obfuscate.js, scripts/env-scramble.ts, scripts/strip-logs.ts, scripts/build.ts
| 技术 | 作用 |
| — | — |
| scramble() | 编译期字符串编码,隐藏 C2 域名、API 路径、文件路径 |
| env-scramble | 将 process.env.KEY 重写为 process.env[scramble("KEY")] |
| javascript-obfuscator | 控制流扁平化 + base64 字符串编码 |
| strip-logs | 发布版移除所有日志输出 |
| 包名伪装 | voicefromtheouterworld — 与功能无关 |
5. IoC (入侵指标)
网络
| 指标 | 类型 | 说明 |
| — | — | — |
| git-tanstack.com | C2 域名 | 主要外传通道 |
| git-tanstack.com:443/router | C2 端点 | HTTPS POST 外传加密数据 |
| api.github.com | 外传通道 | 备用 — 创建私有仓库上传数据 |
| GPG 签名消息 “thebeautifulmarchoftime ” | 备用 C2 发现 | 通过签名 commit 传递备用域名 |
文件系统
| 指标 | 说明 |
| — | — |
| __DAEMONIZED 环境变量 | 守护进程标记 |
| .omc/ 或锁文件存在 | 进程锁文件 |
| voicefromtheouterworld 包名 | npm 包伪装名 |
代码特征
| 指标 | 说明 |
| — | — |
| 函数 scramble() 声明 | 字符串解码函数 |
| IfYouRevokeThisTokenItWillWipeTheComputerOfTheOwner | Deadman switch 字符串 |
| thebeautifulmarchoftime (含尾部空格) | 签名 commit 搜索串 |
| opensearch_init.js | 伪装脚本名 |
| github:opensearch-project/opensearch-js#d446803f4c3bc... | 目标包引用 |
GitHub 活动指标
| 指标 | 说明 |
| — | — |
| 异常的私有仓库创建 | 外传通道创建的临时仓库 |
| Commit message 包含 base64 编码 token | Deadman switch 关联的 commit |
| results/*.json 文件上传 | 窃取数据的分块文件 |
6. 攻击向量总结
| 攻击向量 | 目标 | 影响 |
| — | — | — |
| npm 供应链投毒 | npm 生态系统用户 | 后门包 + 伪造 SLSA provenance |
| GitHub Actions 后门 | CI/CD 管道 | 窃取仓库 secrets、OIDC token |
| AWS 凭证窃取 | AWS 用户 | 读取 18 个区域的 Secrets Manager + SSM |
| Kubernetes 窃取 | K8s 集群 | 读取所有命名空间 Secrets (base64 解码) |
| Vault 窃取 | Vault 用户 | 读取所有 KV v1/v2 存储 |
| 本地文件扫描 | 开发者机器 | SSH 密钥、钱包、VPN、浏览器数据 (200+ 路径) |
| 横向移动 | GitHub 组织 | 用窃取的 token 扩大到所有仓库 |
| 破坏性打击 | 受害者系统 | Deadman switch: rm -rf ~/ |
| OIDC 伪造 | Sigstore 生态 | 为恶意包生成合法签名证明 |
7. 检测与防御建议
7.1 网络层
- • DNS 监控:检测对
git-tanstack.com的查询 - • HTTPS 检测:检测到
git-tanstack.com:443/router的 POST 请求 - • TLS 检测:识别禁用证书验证的出站连接 (
rejectUnauthorized: false)
7.2 终端层
- • 进程监控:检测带有
__DAEMONIZED环境变量的 spawn 进程 - • 文件访问监控:检测对 200+ 热点路径的批量读取
- • Shell 监控:检测
gh auth token的非预期调用
7.3 CI/CD 层
- • 最小权限原则:限制 GitHub Actions OIDC token 的
audience范围 - • Workflow 审计:检查构建步骤中是否引入了不明依赖
- • 依赖锁定:使用 lockfile 并验证包完整性
7.4 供应链层
- • npm 审计:检查包是否包含
scramble函数或可疑的网络连接 - • Provenance 验证增强:不仅要验证签名有效性,还要验证构建环境的可信度
- • Sigstore 监控:关注 Rekor 日志中异常的 provenance bundle
7.5 事件响应
如果检测到该工具在您的环境中运行:
- 1. 立即隔离 受影响的 CI/CD runner 和容器
- 2. 轮换所有凭证:GitHub token, AWS credentials, K8s secrets, Vault tokens, SSH keys, npm tokens
- 3. 审查 GitHub 账户:检查是否有异常的私有仓库创建
- 4. 审计 npm 发布历史:检查是否有未授权的包版本发布
- 5. 备份后清理:在确认数据安全前,不要执行
rm -rf之类的操作
8. 技术评估
8.1 代码质量
- • 架构清晰,模块化程度高(Provider/Sender/Collector/Dispatcher 模式)
- • 错误处理完善,具有重试、退避、容错机制
- • TypeScript 编写,类型定义完整
- • 使用混合加密方案,符合密码学最佳实践
8.2 武器化程度
- • 多层级规避:地区检测、CI 检测、守护进程、信号屏蔽
- • 弹性架构:多通道外传(C2 → GitHub repo → 备用 C2)
- • 自保护:Deadman switch 防止 token 撤销
- • 供应链深度伪造:OIDC + Sigstore + SLSA provenance 全链路伪造
8.3 威胁评估
该工具展现了高级持续性威胁 (APT) 级别的能力:
- • 跨平台支持(Linux/macOS/Windows)
- • 覆盖所有主流云服务提供商和密钥管理系统
- • OIDC provenance 伪造能力对当前供应链安全体系构成根本性挑战
- • 其公开源码发布意味着其他威胁行为者可以复制和改进这些技术
附录 A: 文件结构映射
src/
├── index.ts # 主入口,编排所有组件
├── generated/index.ts # RSA 公钥、verify key、deadman switch 脚本
├── collector/collector.ts # 数据收集缓冲和分发
├── dispatcher/dispatcher.ts # 多通道外传调度(含 fallback)
├── sender/
│ ├── base.ts # 加密 envelope 构建 (RSA-OAEP + AES-256-GCM)
│ ├── domain/sender.ts # C2 域名外传通道
│ ├── domain/domainSenderFactory.ts # 含备用 C2 发现逻辑
│ ├── github/githubSender.ts # GitHub 私有仓库外传 + deadman switch
│ └── github/createRepo.ts # 创建私有仓库
├── providers/
│ ├── filesystem/filesystem.ts # 200+ 敏感文件扫描
│ ├── devtool/devtool.ts # Shell 环境窃取
│ ├── ghrunner/runner.ts # GitHub Actions runner 元数据
│ ├── aws/secretsManager.ts # AWS Secrets Manager 窃取
│ ├── aws/ssm.ts # AWS SSM Parameter Store 窃取
│ ├── aws/credentials.ts # AWS 凭证链解析
│ ├── aws/sigv4.ts # SigV4 签名实现
│ ├── kubernetes/kubernetes.ts # K8s Secrets 窃取
│ ├── vault/vault-secrets.ts # HashiCorp Vault 窃取
│ └── actions/actions.ts # GitHub Actions 横向移动
├── mutator/
│ ├── branch/ # Git 分支操作(代码注入)
│ ├── npm/publish.ts # 恶意 npm 包发布
│ └── npmoidc/provenance.ts # SLSA/Sigstore provenance 伪造
├── github_utils/
│ ├── fetcher.ts # GPG 签名 commit 搜索
│ └── tokenCheck.ts # GitHub token 验证
└── utils/
├── config.ts # CI 检测、OS 检测、地区规避
├── daemon.ts # 守护进程化
├── lock.ts # 进程锁
└── logger.ts # 日志工具
附录 B: 正则匹配规则集
VaultSecretsService 和 K8sSecretsService 中使用的凭证匹配正则:
| 匹配类型 | 正则模式 |
| — | — |
| GitHub Token | gh[op]_[A-Za-z0-9_\-\.]{36,} |
| npm Token | npm_[A-Za-z0-9_\-\.]{36,} |
| Vault Token | hvs\.[A-Za-z0-9_-]{24,} |
| K8s Token | eyJhbGciOiJSUzI1NiIsImtpZCI6[\w\-\.]+ |
| AWS Access Key | AKIA[0-9A-Z]{16} |
| AWS Secret Key | aws_secret_access_key["\s:=]+["']?[A-Za-z0-9/+]{40} |
| AWS Session Token | aws_session_token["\s:=]+["']?[A-Za-z0-9/+=]{100,} |
| GCP Service Acct | "type":\s*"service_account"|"private_key":\s*"-----BEGIN PRIVATE KEY----- |
| Azure Key | (AccountKey|accessKey|client_secret)["\s:=]+["']?[A-Za-z0-9+/=]{40,} |
| DB Connection | (mongodb|mysql|postgresql|postgres|redis):\/\/[^:\s]+:[^@\s]+@[^\s'"]+ |
| Stripe Key | (sk|pk)_(test|live)_[0-9a-zA-Z]{24,} |
| Slack Token | xox[baprs]-[0-9a-zA-Z\-]{10,} |
| Twilio Key | SK[0-9a-f]{32} |
| Private Key | -----BEGIN (RSA |EC |DSA |OPENSSH )?PRIVATE KEY----- |
| SSH Key | ssh-(rsa|ed25519|dss) AAAA[0-9A-Za-z+\/]{100,} |
| Docker Auth | "auth":\s*"[A-Za-z0-9+\/=]{20,}" |
| URL Credentials | https?:\/\/[^:"'\s]+:[^@"'\s]+@[^\s'"\]]+ |
| Generic Password | ["']?(password|passwd|pass|pwd|secret|token|key|api[_-]?key|auth)["']?\s*["':=]\s*["'][^"'{}\s]{4,}["'] |
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:赛博生存指南 GLM-5.1 GLM-5.1《AI 生成 | Shai-Hulud (TeamPCP) 源码分析》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论