从代码注入到资产流失:Bybit安全事件的前端攻防启示录

271 阅读6分钟

2025年2月21日,加密货币交易所Bybit遭遇了史上最大规模的数字资产盗窃事件,黑客通过篡改前端代码窃取价值14亿美元的以太坊(ETH)。令人非常意外的是,攻击并未利用智能合约漏洞,而是直击前端安全体系的薄弱环节。本文将从前端技术视角还原攻击链条,剖析漏洞成因,并探讨防御此类攻击的核心策略。

时间线

  • 2025年2月19日15:29 UTC:Safe{Wallet}的AWS S3存储桶中的JavaScript文件被替换为恶意代码。
  • 2025年2月21日14:13 UTC:Bybit执行冷钱包交易,触发恶意代码,导致资金被盗。

image.png

前端攻击流程

攻击的核心在于前端代码的篡改,尤其是Safe Wallet提供的用户界面(UI)。Safe Wallet是一个广泛使用的多重签名钱包工具,其前端通过JavaScript与后端智能合约交互。攻击者利用社会工程学或其他手段(如供应链攻击),入侵了Safe Wallet的AWS基础设施,并在前端文件中植入恶意代码。

具体攻击流程如下:

  1. 代码植入:黑客将恶意JavaScript代码注入 app.safe.global 的静态资源中。根据Sygnia的报告,该代码被设计为仅在特定条件下触发,例如当交易发起者为Bybit的多重签名地址时。这种有针对性的设计表明攻击者对Bybit的操作流程有深入了解。
  2. 用户界面欺骗:当Bybit的签名者(多签流程中的人类操作员)通过Safe Wallet的网页界面签署交易时,恶意代码悄然替换了交易参数。签名者看到的UI显示的是正常的目标地址(如热钱包地址),但实际签名的数据却是黑客指定的恶意地址。这种“掩码交易”(masked transaction)是前端攻击的典型手法。
  3. 交易执行:一旦签名者完成签名,篡改后的交易数据被提交至以太坊区块链。由于多重签名机制依赖于前端生成的签名,而非链上验证交易内容,黑客成功绕过了后端防护,完成了资金转移。

下面是一个简化的伪代码示例,代码来自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(去中心化应用)及类似系统的安全性。

  1. 实施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的浏览器。

  1. 启用内容安全策略 (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(跨站脚本攻击)和代码注入风险。

  1. 本地签名工具替代网页界面

依赖网页前端进行签名存在固有风险。建议开发离线签名工具(如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");

通过本地工具,签名者可直接审查交易细节,避免前端篡改风险。

  1. 多层次验证与用户教育

即使前端被篡改,多层次验证也能增加黑客难度。例如,在交易提交前,要求签名者通过独立设备(如手机应用)确认交易详情。此外,加强对签名者的安全培训,识别钓鱼攻击,是至关重要的非技术防护手段。

  1. 定期审计与基础设施加固
  • 前端代码审计:定期检查前端代码及依赖库,防止供应链攻击。
  • 云安全:对AWS S3等基础设施启用多因素认证(MFA)、访问日志监控,并限制API密钥权限。

小结

Bybit被盗事件暴露了前端安全在区块链生态中的薄弱环节,去中心化应用的前端仍是中心化风险点。攻击者通过篡改Safe Wallet的前端代码,成功绕过多重签名机制,完成了资金窃取。从技术角度看,静态资源的完整性保护、CSP的实施、本地签名工具的采用以及多层次验证,是应对此类攻击的有效手段。从非技术角度看,提升签名者的安全意识同样重要。