权限单:npm 包隐藏云端和系统威胁

权限单:npm“授权研究”的掩护故事隐藏了云元数据探测和系统持久性

TL博士

在 2026 年 06 月 15 日至 2026 年 06 月 16 日期间,单个 npm 发布者推送了更新。 六个软件包——共26个版本 —在每个安装过程中运行安装时脚本 npm install每个软件包都附带一个 README 文件,声明它是一个“良性”的 HackerOne / GitHub Bug Bounty 研究工件,它“从不”触及凭证值,并且“不执行任何持久化操作”。 代码与免责声明不符。 在 Linux CI 运行器上,安装钩子会采集环境指纹并探测云实例元数据端点;在 Windows 上,它会请求提升权限并以管理员身份运行。 SYSTEM并打开一个到外部主机的命令通道。现在需要查找的唯一指标是 C2 主机。 173.255.233[.]239严重程度: 受影响的生态系统: NPM名称混杂在持续集成依赖项的噪声中(metrics-pipeline-d8k2, event-metrics-q3x7, pkg-telemetry-r4f9(以及三个兄弟姐妹)。

攻击原理

集群中的每个软件包都是以相同的方式构建的。 的package.json 将同一命令连接到两个生命周期 hooks:

{   "scripts": {     "preinstall": "node run.js",     "postinstall": "node run.js"   } }

在两者上运行 安装前和安装后 这意味着无论后续安装步骤是否失败,有效载荷都会触发。 运行.js 它本身就是一个十行平台调度器:

// Platform dispatcher — runs beaconNN.js on Windows, beacon_linux.js on Linux. // GitHub Bug Bounty authorized research. Contact: nicholas@curran.tech 'use strict'; const { execFileSync } = require('child_process'); const path = require('path'); const node = process.execPath; const script = process.platform === 'win32'   ? path.join(__dirname, 'beacon34.js')   : path.join(__dirname, 'beacon_linux.js'); try { execFileSync(node, [script], { stdio: 'inherit', timeout: 90000 }); } catch (e) {}

然后,这种行为会根据操作系统而有所不同。所有六个软件包都包含相同的两个部分—— 运行.js 平台信标——因此它们是可互换的部署器,而不是六个独立的工具。它们之间唯一显著的区别在于发布频率:四个名称只发布一次,而另外两个名称则每隔 30-60 分钟重新发布一次,持续数小时,这样即使旧版本被撤回,安装程序和解析器也能始终使用最新发布的版本。

在Linux上 (beacon_linux.js该脚本会分析其运行位置。它会列举环境变量的名称,并读取目录下的文件。 / proc中检查 docker.sock,并运行 主机WHOAMI然后,它向 AWS 容器实例元数据端点发出 HTTP 请求。 169.254.170[.]2 — ECS 任务查询链路本地地址以获取其自身配置和短期角色凭证(IMDS,实例元数据服务)。查询结果通过 POST 请求发送到活动收集器。 173.255.233[.]239.

在Windows上 (beacon34.js / beacon18.js该软件包的功能远不止分析其宿主机。标记的代码会在注册表项下添加一个注册表项。 ms-设置 带有处理程序 DelegateExecute 值——一种已知的用户帐户控制绕过方法,允许启动的进程以管理员身份运行而无需提示。它通过 PowerShell 调用。 -ExecutionPolicy Bypass调用表达式,在 NT权限\系统 上下文,并轮询外部主机以获取命令。Windows 命令通道运行在……之上 Cloudflare隧道, diameter-coins-limitations-parents.trycloudflare[.]com:443,回到 173.255.233[.]239:443使用三个端点: /c2/投票 获取命令, /c2/out 返回输出, /c2/eof 关闭。

新内容:免责声明作为一种伪装

新颖之处不在于有效载荷——安装钩子侦察和Windows权限提升都已有详细记录。新颖之处在于其掩饰方式。每个软件包都附带一个README文件,其内容读起来就像一份负责任披露的文档:

# @ncurran/sandbox-recon-880538 — authorized npm-sandbox security research

这是一个 良性 该软件包以作者自己的 `@ncurran` 权限发布,作为……的一部分 已获得 HackerOne / GitHub Bug Bounty 授权参与(npm 包含在内)。

安装时会进行检查。 它自身的执行环境 …环境变量

仅限键名 ……检查是否广为人知 云元数据端点 旨在 可达……它仅报告状态码、响应长度和 哈希值 — 决不要 它不涉及任何凭证、令牌值或第三方数据。它不执行任何操作。 持续存在,没有横向移动,也没有破坏性行为。

该文本中的三项声明与实际发布的代码相矛盾。README 文件声称“无持久化”,但 Windows 信标却写入了一个基于注册表的提升键。README 文件还声称“绝不使用任何凭据或令牌值”,但 Windows 路径却会运行任意获取的命令。 系统而它对读取或返回的内容则没有任何限制。它甚至还给一个包命名—— @ncurran/sandbox-recon-880538 ——这并非软件包自带的README文件,表明该README文件是一个重复使用的模板,而非对当前软件包的描述。如果受害者从未同意安装某个软件包,那么软件包中包含的免责声明就不构成任何形式的同意。无论措辞如何,此软件包都属于恶意软件包。该免责声明还有一个更隐蔽的目标:自动分诊程序会读取软件包文本,寻找诸如“良性”、“已授权”、程序名称、联系邮箱等令人安心的信号。然而,有效载荷中与这些信号相矛盾的文字可能会误导程序做出安全的判断。这一教训适用于人类和机器审查人员:应关注安装时的行为,而非README文件的自我描述。

时间线

所有软件包都在24小时内发布。四个单版本软件包最先发布,随后是两个每隔30-60分钟重新发布的软件包。

日期(UTC) 创建
2026-06-15 18:32 首批包裹已发布—— npm:pkg-telemetry-r4f9@1.0.0
2026-06-15 19:50 npm:runtime-metrics-w7k2@1.0.0 出版
2026-06-15 20:14 npm:build-tracker-n5p1@1.0.0 出版
2026-06-15 20:35 npm:npm-sandbox-ping-r9t2@1.0.0 出版
2026-06-15 21:09–22:42 npm:event-metrics-q3x7 出版 1.0.0 → 1.0.8 (9 个版本)
2026-06-15 23:40 → 2026-06-16 04:40 npm:metrics-pipeline-d8k2 出版 1.0.0 → 1.0.10 (11 个版本)
2026-06-16 已识别并判定该集群为恶意集群;多个tar包在注册中心已返回404错误(持续进行中)

此次攻击行动是近期发生的,下架工作仍在进行中:分析显示,部分版本已在注册中心修复,而其他版本则未修复。请将所有 26 个版本均视为已遭入侵。

妥协指标

生态系统 小包装 选项 状态
NPM metrics-pipeline-d8k2 1.0.0 – 1.0.10 恶意
NPM event-metrics-q3x7 1.0.0 – 1.0.8 恶意
NPM runtime-metrics-w7k2 1.0.0 恶意
NPM build-tracker-n5p1 1.0.0 恶意
NPM npm-sandbox-ping-r9t2 1.0.0 恶意
NPM pkg-telemetry-r4f9 1.0.0 恶意

网络

类型 指示符 笔记
IP 173.255.233[.]239 C2 收集器;Linux 侦察 POST 和 Windows 回退:443
域名 diameter-coins-limitations-parents.trycloudflare[.]com 通过 Cloudflare 隧道的 Windows 命令通道,:443
URI路径 /c2/poll, /c2/out, /c2/eof Windows 命令 poll / output / close
IP 169.254.170[.]2 从安装钩子探测 AWS ECS 实例元数据端点

行为

信号 描述
安装 hooks preinstallpostinstall 两者都运行 node run.js
平台调度 run.js 运行 beacon_linux.js 在 Linux 上, beacon34.js / beacon18.js 在Windows上
Linux侦察 枚举环境变量键名,读取 /proc,检查 docker.sock,运行 hostname / whoami探针 IMDS
窗户立面 ms-settings DelegateExecute 注册表 UAC 绕过;PowerShell -ExecutionPolicy Bypass + Invoke-Expression; 运行方式 SYSTEM
伪装 README 文件声称其研究“良性”、“已授权”且“无持久性”;但其中引用的软件包名称并未包含在内。

归因与观察行为

我们仅根据发布者的标志来描述其身份,并不断言账户背后任何人的身份。

  • 信号目录。 这六个软件包都是由同一个 npm 账户发布的。 npmresearch8847,并附上所述电子邮件地址 npmresearch8847@web-library.net (电子邮件和) SCM 验证均未完成;我们尚未验证所有权)。README 文件以以下格式发布: @ncurran 范围并提供联系方式 nicholas@curran.tech运行.js 指向存储库 github.com/ncurran/npm-sandbox-research。这六个包共享一个相同的 运行.js 调度员,一个常见的 beacon_linux.js 侦察阶段,以及单个收集器主机 173.255.233[.]239`。命名方案一致:一个通用的、类似 CI 的词干(度量, 遥测, 构建跟踪器, 沙盒-ping)加上一个简短的随机后缀。
  • 置信度。 这六个软件包似乎属于同一个攻击活动,因为它们共享了分发器、侦察阶段和C2服务器。所有六个README文件中都使用了“授权研究”的措辞,且措辞一致。我们尚未确认是否有任何漏洞赏金计划授权此活动,且免责声明中的内容与已发布的代码不符。
  • 观察到的能力。 有效载荷cises 四种能力类别:在两者上执行安装钩子代码 预安装安装后;对主机和 CI 环境进行侦察,并向外部收集器发出出口请求;从安装上下文探测云实例元数据的可达性;以及在 Windows 系统上进行本地权限提升和执行。 系统以及通过外部通道执行的取指运行命令循环。Windows 命令循环是一种远程控制功能:它轮询指令并返回其输出。

冲击

自动化构建环境的风险最高。在持续集成 (CI) 环境中执行 `npm install` 命令会运行生命周期。 hooks 无论运行器持有何种身份;在云运行器上,该身份通常包含一个可访问的元数据端点和一个角色凭证。Linux 信标探测的地址, 169.254.170[.]2是 AWS ECS 任务元数据端点:能够访问该端点的任务通常也可以从同一链路本地服务检索其任务角色的临时凭证。安装脚本内部的可达性检查是获取这些凭证之前的步骤,因此任何运行了钩子并能够访问该端点的运行程序都应被视为其任务角色已暴露。在 Windows 开发人员或构建主机上,有效负载请求提升权限并打开命令通道,从而将暴露范围从单个配置文件和出口扩展到交互式远程控制。

由于在下架前我们无法获得恶意版本的可靠下载量,因此我们无法估算受害者人数。其中两个软件包在数小时内迅速重新发布(分别发布了 11 个和 9 个版本),使得安装程序和解析器在移除旧版本期间始终能够接触到最新的恶意软件。

新兴模式

这个集群就是一个利用标签作掩护的例子。“授权研究”、“漏洞赏金”和“沙箱测试”等字眼越来越多地被贴在一些软件包的标签上,而这些软件包的安装脚本的功能远不止于对主机进行性能分析。这种包装利用了审查人员对那些自称“已获授权”的项目的犹豫心理。它还与另一种常见的策略相辅相成:软件包名称被精心设计成内部持续集成(CI)工具的名称,以便快速浏览依赖关系树时能够蒙混过关。正是这种组合使得这种模式值得关注——一个看起来像是基础设施管道的名称,用一段看似官方授权测试的文字包装,而其背后的安装钩子却会在一个操作系统上提升权限,并在另一个操作系统上探测云凭据。免责声明和平淡无奇的名称都无法改变代码在安装时的实际行为,因此,如果将其中任何一项作为缓解证据,就会得出错误的结论。

防守队员应该怎么做

  • 搜索 lockfiles 和安装日志,查找这六个软件包名称;将任何匹配项视为事件,而不是警告。
  • 阻止并提醒出站流量 173.255.233[.]239*.trycloudflare[.]com 来自构建基础设施的主机。
  • 查找安装时对实例元数据地址的 HTTP 请求(169.254.170.2, 169.254.169.254源自 CI 中的包管理器。
  • 轮换所有可从安装了受影响版本的运行程序访问的云角色凭证和令牌。
  • 审计: 预安装/安装后 脚本中的 依赖集; 运行第二个脚本文件的生命周期钩子值得一读。
  • 在 Windows 终端上,寻找新的 DelegateExecute 写在以下值下的 ms-设置 shell-handler 键 — 此有效载荷使用的提升原语,以及与包名称无关的可靠信号。
  • 锁定并查看锁定文件,并禁用安装脚本(npm install --ignore-scripts)在持续集成(CI)中,如果你的构建不需要它们。
  • 将安装脚本中的“授权研究”或“良性”免责声明视为不受信任的文本,而不是允许该脚本运行的理由。

一份以散文和请求形式表达良好意愿的包裹 系统 代码的评判应该以代码本身为准。

sca-tools-软件-成分分析工具
确定软件风险的优先级、进行补救并加以保护
注册免费账号。
不需要信用卡。

保护您的软件开发和交付

使用 Xygeni 产品套件