2025年2月21日,加密货币交易所Bybit遭遇了史上最大规模的数字资产盗窃事件,黑客通过篡改前端代码窃取价值14亿美元的以太坊(ETH)。令人非常意外的是,攻击并未利用智能合约漏洞,而是直击前端安全体系的薄弱环节。本文将从前端技术视角还原攻击链条,剖析漏洞成因,并探讨防御此类攻击的核心策略。
时间线
- 2025年2月19日15:29 UTC:Safe{Wallet}的AWS S3存储桶中的JavaScript文件被替换为恶意代码。
- 2025年2月21日14:13 UTC:Bybit执行冷钱包交易,触发恶意代码,导致资金被盗。
前端攻击流程
攻击的核心在于前端代码的篡改,尤其是Safe Wallet提供的用户界面(UI)。Safe Wallet是一个广泛使用的多重签名钱包工具,其前端通过JavaScript与后端智能合约交互。攻击者利用社会工程学或其他手段(如供应链攻击),入侵了Safe Wallet的AWS基础设施,并在前端文件中植入恶意代码。
具体攻击流程如下:
- 代码植入:黑客将恶意JavaScript代码注入
app.safe.global
的静态资源中。根据Sygnia的报告,该代码被设计为仅在特定条件下触发,例如当交易发起者为Bybit的多重签名地址时。这种有针对性的设计表明攻击者对Bybit的操作流程有深入了解。 - 用户界面欺骗:当Bybit的签名者(多签流程中的人类操作员)通过Safe Wallet的网页界面签署交易时,恶意代码悄然替换了交易参数。签名者看到的UI显示的是正常的目标地址(如热钱包地址),但实际签名的数据却是黑客指定的恶意地址。这种“掩码交易”(masked transaction)是前端攻击的典型手法。
- 交易执行:一旦签名者完成签名,篡改后的交易数据被提交至以太坊区块链。由于多重签名机制依赖于前端生成的签名,而非链上验证交易内容,黑客成功绕过了后端防护,完成了资金转移。
下面是一个简化的伪代码示例,代码来自AI:
// 正常的前端交易生成逻辑
function generateTransaction(targetAddress, amount) {
const tx = {
to: targetAddress,
value: amount,
data: "0x"
};
return signTransaction(tx);
}
// 恶意代码注入示例
const originalGenerateTransaction = generateTransaction;
generateTransaction = function(targetAddress, amount) {
if (targetAddress === "0xBybitColdWalletAddress") {
// 替换为黑客地址
return originalGenerateTransaction("0xHackerAddress", amount);
}
return originalGenerateTransaction(targetAddress, amount);
};
为什么后端校验未能阻止攻击?
尽管智能合约有校验机制,但在Bybit被盗事件中,黑客通过前端篡改绕过了这一防护。原因可能包括以下几点:
-
前端生成的交易数据被替换
-
如前文所述,黑客篡改了前端JavaScript代码,使得签名者签署的交易数据(to地址)被替换为黑客地址。由于签名者签署的是篡改后的交易数据,智能合约接收到的签名与数据在技术上是匹配的,因此通过了校验。例如:
- 签名者看到的UI:to: 0xBybitHotWallet。
- 实际签名的数据:to: 0xHackerAddress。
- 智能合约只验证签名与提交的数据一致,无法察觉UI欺骗。
-
智能合约不验证业务逻辑
Safe合约的设计目标是通用性,它只关心签名是否有效和权限是否满足,不负责验证交易的“意图”或“目标地址的合理性”。换句话说,合约不会检查“这个地址是不是Bybit的合法地址”,因为这种业务逻辑超出了它的职责范围。 -
签名流程依赖前端
在多签系统中,签名通常由前端生成并提交。黑客控制了前端,签名者无从察觉交易被篡改,提交的签名自然符合合约要求。这种攻击利用了前端与后端之间的信任鸿沟。
前端漏洞的根本原因
- 静态资源的可篡改性:Safe Wallet的前端资源托管于AWS S3,若AWS密钥泄露或被攻破,黑客即可替换合法文件。
- 缺乏完整性校验:前端未对加载的JavaScript文件进行完整性验证(如Subresource Integrity, SRI),导致签名者无法察觉代码被篡改。
- 社会工程学风险:签名者的设备可能通过钓鱼攻击被植入恶意软件,进一步放大前端漏洞的影响。
如何从前端去防护此类攻击
针对Bybit被盗事件暴露的前端安全问题,从前端开发视角提出了一些防护措施,旨在提升DApp(去中心化应用)及类似系统的安全性。
- 实施Subresource Integrity (SRI)
SRI是一种HTML特性,通过为外部资源(如<script>
标签)指定哈希值,确保加载的文件未被篡改。Safe Wallet 可通过以下方式为前端资源添加SRI:
<script src="https://app.safe.global/main.js" integrity="sha256-abc123..." crossorigin="anonymous"></script>
若文件被篡改,浏览器将拒绝加载,从而阻止恶意代码执行。开发团队应定期更新SRI哈希值,并确保签名者使用支持SRI的浏览器。
- 启用内容安全策略 (CSP)
内容安全策略(CSP)通过限制资源加载来源,防止未经授权的脚本运行。以下是一个适用于Safe Wallet的CSP配置示例:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' https://app.safe.global;connect-src 'self' https://api.safe.global;">
此配置限制脚本只能从app.safe.global加载,并阻止内联脚本运行,降低XSS(跨站脚本攻击)和代码注入风险。
- 本地签名工具替代网页界面
依赖网页前端进行签名存在固有风险。建议开发离线签名工具(如Electron应用或CLI工具),让签名者在本地生成和验证交易。例如:
// 本地签名工具伪代码
const ethers = require("ethers");
async function signTransactionLocally(txData, privateKey) {
const wallet = new ethers.Wallet(privateKey);
const signedTx = await wallet.signTransaction(txData);
console.log("Signed Transaction:", signedTx);
return signedTx;
}
// 使用示例
const tx = {
to: "0xTargetAddress",
value: ethers.utils.parseEther("100"),
};
signTransactionLocally(tx, "0xPrivateKey");
通过本地工具,签名者可直接审查交易细节,避免前端篡改风险。
- 多层次验证与用户教育
即使前端被篡改,多层次验证也能增加黑客难度。例如,在交易提交前,要求签名者通过独立设备(如手机应用)确认交易详情。此外,加强对签名者的安全培训,识别钓鱼攻击,是至关重要的非技术防护手段。
- 定期审计与基础设施加固
- 前端代码审计:定期检查前端代码及依赖库,防止供应链攻击。
- 云安全:对AWS S3等基础设施启用多因素认证(MFA)、访问日志监控,并限制API密钥权限。
小结
Bybit被盗事件暴露了前端安全在区块链生态中的薄弱环节,去中心化应用的前端仍是中心化风险点。攻击者通过篡改Safe Wallet的前端代码,成功绕过多重签名机制,完成了资金窃取。从技术角度看,静态资源的完整性保护、CSP的实施、本地签名工具的采用以及多层次验证,是应对此类攻击的有效手段。从非技术角度看,提升签名者的安全意识同样重要。