← 返回预习计划
Module 05

Module 05: Blockchain & Smart Contract Security

漏洞分类、经典攻击案例复盘、Slither/Mythril 工具与 Ethernaut CTF

上一模块思考题参考

Q: 闪电贷在一笔交易内完成借款和还款——攻击者如何利用这个特性操纵 AMM 的价格,进而从借贷协议中获利? 典型步骤:1)借入大量代币 A;2)在 AMM 中大量卖出 A,将 A 的价格砸低;3)在以该 AMM 为价格源的借贷协议中,用极低价格的 A 作为抵押品借出其他资产,或触发他人仓位的不公平清算;4)在 AMM 中买回 A(价格已恢复),归还闪电贷,净赚差价。整个过程在一笔交易内完成,零资本投入。

Q: 预言机将链外价格数据喂到链上,但喂价更新有延迟。攻击者如何利用这个时间差? 攻击者可以在链外价格已经剧烈变动但链上喂价尚未更新时,利用过时价格进行套利——例如以旧的高价抵押品价值借出超额资金。Chainlink 的多节点聚合降低了单点操纵风险,但对延迟问题无法完全消除,特别是在极端行情和网络拥堵同时发生时。

Q: DeFi 可组合性意味着一个协议的漏洞可能影响所有依赖它的协议。从安全角度看,这种”乐高积木”架构的系统性风险如何评估? 每个协议的风险不是独立的,而是沿着调用链传导。评估需要考虑依赖图的深度和广度:一个底层协议(如稳定币或预言机)出问题,上层所有协议都受影响。审计单个合约不够,还需要审计合约间的交互逻辑和边界条件。

为什么安全是区块链的头等大事

区块链有两个特性让安全问题格外致命:

  1. 不可变性——合约部署后无法修改。传统软件发现 bug 可以热修复,智能合约的 bug 是永久的。
  2. 经济激励——合约直接管理资金。一个漏洞可能意味着数亿美元被瞬间转走,攻击者有充分动机去找漏洞。

2016 年 The DAO 被盗 6000 万美元,2022 年 Wormhole 被盗 3.2 亿美元。这些不是假设场景,是已经发生的事实。


常见智能合约漏洞

重入攻击(Reentrancy)

攻击者在合约完成状态更新前,通过回调函数反复调用取款函数,多次提取资金。

The DAO 事件就是这个漏洞。核心问题:先转账,后更新余额。

有漏洞的代码:

// 危险:先转账后更新状态
function withdraw() external {
    uint256 amount = balances[msg.sender];
    (bool success, ) = msg.sender.call{value: amount}("");
    require(success);
    balances[msg.sender] = 0; // 攻击者在这行执行前就重新进入了 withdraw()
}

修复后的代码:

// 安全:Checks-Effects-Interactions 模式
function withdraw() external {
    uint256 amount = balances[msg.sender];
    balances[msg.sender] = 0;  // 先更新状态
    (bool success, ) = msg.sender.call{value: amount}("");
    require(success);
}

关键区别:把 balances[msg.sender] = 0 移到转账之前。即使攻击者重入,余额已经是 0,无法重复提取。

整数溢出(Integer Overflow)

Solidity 0.8 之前,uint256 溢出不会报错。255 + 1uint8 中变成 0,攻击者可以利用这一点绕过余额检查。

2018 年 BEC 代币事件中,攻击者利用溢出凭空创造了天量代币。

Solidity 0.8+ 内置了溢出检查,运算溢出会自动 revert。旧版本需要使用 OpenZeppelin 的 SafeMath 库。

访问控制缺陷

关键函数缺少权限检查。2017 年 Parity 多签钱包事件中,initWallet() 函数没有限制调用者,任何人都可以将自己设为钱包所有者,然后转走资金。

常见错误:忘记加 onlyOwner 修饰符、将管理函数设为 public 却无权限校验。

前端运行(Front-running)

以太坊的交易在 mempool 中公开可见。攻击者看到一笔大额 DEX 交易后,可以提交更高 gas 的同方向交易抢先执行,等受害者交易推高价格后获利。

这不是合约漏洞,而是协议层面的结构性问题。缓解方案包括 commit-reveal 机制和 Flashbots 等私有交易通道。

闪电贷攻击

闪电贷允许在一笔交易内借入任意金额(无需抵押),只要同一交易内还清。攻击者利用这一特性:

  1. 借入大量代币
  2. 用巨额资金操纵 DEX 上的价格
  3. 目标协议根据被操纵的价格执行操作(如清算、兑换)
  4. 攻击者获利,归还贷款

根本原因:协议依赖单一 DEX 作为价格预言机。防御方案是使用 Chainlink 等去中心化预言机,或 TWAP(时间加权平均价格)。


安全开发实践

Checks-Effects-Interactions 模式:先检查条件(require),再更新状态(effects),最后进行外部调用(interactions)。这是防止重入攻击的基本模式。

Pull over Push 支付:不主动向用户转账(push),让用户自己来取(pull)。避免因接收方合约恶意回退导致整个批量支付失败。

重入锁(ReentrancyGuard):OpenZeppelin 提供的 nonReentrant 修饰符,函数执行期间锁定状态,阻止重入。在 CEI 模式之上多一层保险。

使用 OpenZeppelin 库:经过审计的标准实现——ERC20、ERC721、AccessControl、Pausable 等。不要自己造轮子,除非你有充分理由。

最小权限原则:每个角色只拥有必要的权限。使用细粒度的角色控制(AccessControl)而非单一 owner


审计工具

工具类型说明
Slither静态分析Trail of Bits 开发。扫描 Solidity 源码,检测 70+ 种已知漏洞模式。速度快,适合集成到 CI/CD
Mythril符号执行ConsenSys 开发。通过符号执行探索所有可能的执行路径,能发现更深层的逻辑漏洞。分析时间较长
Echidna模糊测试基于属性的模糊测试工具。你定义不变量(如”总供应量不变”),Echidna 自动生成大量随机输入尝试打破它

三者互补:Slither 做快速扫描,Mythril 做深度分析,Echidna 做边界测试。


审计流程

专业审计通常包含三个层次:

  1. 人工审查——审计员逐行阅读代码,理解业务逻辑,检查权限模型和资金流向。这一步最耗时,也最有价值,因为工具无法理解业务意图。
  2. 自动化扫描——用 Slither、Mythril 等工具跑一遍,捕捉人工可能遗漏的已知模式。
  3. 形式化验证——用数学方法证明合约满足特定性质。成本最高,通常只用于核心金融协议。

审计报告会按严重程度分级:Critical(可直接窃取资金)、High(可造成资金损失)、Medium(可能造成异常行为)、Low(代码质量问题)、Informational(建议改进)。

注意:审计不是银弹。审计通过不代表没有漏洞,只代表在审计范围和时间内没有发现漏洞。


经典案例分析

The DAO(2016 年 6 月)

  • 发生了什么:攻击者利用重入漏洞从 The DAO 合约中反复提取 ETH,总计约 360 万 ETH(当时约 6000 万美元)
  • 根本原因splitDAO() 函数在转账后才更新余额
  • 后果:以太坊社区投票硬分叉,回滚攻击交易。反对者继续运行原链,即 Ethereum Classic(ETC)
  • 教训:催生了 Checks-Effects-Interactions 模式,让整个行业认识到智能合约安全的重要性

Poly Network(2021 年 8 月)

  • 发生了什么:攻击者利用跨链桥的访问控制漏洞,修改了 keeper 地址,窃取 6.1 亿美元
  • 根本原因:跨链消息验证逻辑存在缺陷,攻击者可以伪造跨链调用修改关键权限
  • 后果:攻击者最终归还全部资金(自称”白帽”),但暴露了跨链桥的系统性风险
  • 教训:跨链桥是安全最薄弱的环节之一,权限管理必须极其严格

Wormhole(2022 年 2 月)

  • 发生了什么:攻击者绕过 Solana 端的签名验证,伪造消息凭空铸造了 12 万 wETH(约 3.2 亿美元)
  • 根本原因:使用了已弃用的 verify_signatures 函数,攻击者可以伪造验证通过的结果
  • 后果:Jump Crypto(Wormhole 背后公司)自掏腰包补上了 3.2 亿美元的缺口
  • 教训:不要使用已弃用的函数;跨链桥必须对签名验证进行多层校验

推荐资源

资源类型说明
Damn Vulnerable DeFi实战练习一系列 DeFi 安全挑战,从闪电贷到治理攻击,边做边学
SWC Registry漏洞库智能合约弱点分类,每种漏洞有编号、描述、示例代码和修复建议
OpenZeppelin Docs开发文档安全合约库的官方文档,包含最佳实践和安全指南
ConsenSys Security Best Practices最佳实践以太坊智能合约安全开发的系统性指南
EthernautCTFOpenZeppelin 的安全 CTF 挑战,通过游戏化方式学习合约漏洞利用

思考题

  1. Slither 等静态分析工具能检测已知漏洞模式,但无法理解业务逻辑。机器学习模型是否有可能通过学习大量合约代码和已知漏洞,发现静态规则遗漏的新型漏洞?这种方法的局限在哪里?
  2. 链上交易数据完全公开——能否通过分析历史攻击交易的特征(调用模式、gas 用量、资金流向),训练模型实时检测正在发生的攻击?这种检测系统面临的最大挑战是什么?
  3. 安全审计依赖人工审查业务逻辑,但审计员的时间和能力有限。NLP 模型能否帮助审计员更快地理解合约意图、标注可疑代码段?这会如何改变审计流程?

下一步

完成安全基础后,进入 Module 06 学习共识机制。