欢迎订阅专栏:10分钟智能合约:进阶实战
闪电贷是 DeFi 领域最具颠覆性的创新之一,它允许用户在无需抵押的情况下借入巨额资金,但必须在同一笔交易内归还。这种特性使其成为套利和清算的有效工具,但也因其巨大的杠杆效应,成为众多黑客攻击的首选武器。
在 Damn Vulnerable DeFi (DVD) 的挑战中,多个题目都围绕闪电贷展开,是学习其安全风险的绝佳实战案例。
🎯 为什么闪电贷是攻击利器?
闪电贷的核心优势——无抵押、瞬时、高杠杆——也构成了其安全威胁的根源。攻击者可以在一笔交易中借入巨额资金,对市场或协议进行操纵,而无需承担任何资本风险。常见的攻击模式包括:
- 价格操纵:通过闪电贷借入大量资金,在DEX上进行大额兑换,人为拉高或拉低某个代币的价格,从而在其他依赖该价格数据的协议中获利。
- 闪电贷 + 重入攻击:将闪电贷与重入攻击结合,在闪电贷的回调函数中反复调用协议的漏洞函数,窃取超出借贷额度的资金。
🧩 Damn Vulnerable DeFi 闪电贷实战解析
DVD 中有多个挑战精准地模拟了真实的闪电贷漏洞,下面我们通过三个典型挑战来深入分析。
1. Truster: 被滥用的任意外部调用
- 挑战目标:你一无所有,需要从一个持有 100 万 DVT 代币的池子中,通过单笔交易拯救所有资金。
- 漏洞核心:
flashLoan()函数中存在一个target.functionCall(data)语句,允许在闪电贷过程中执行任意外部调用。 - 攻击手法:
- 调用
flashLoan,借款金额设为0。 - 构造
data,让池子代表攻击者调用approve函数,授权攻击者合约转移池子中的所有 DVT 代币。 - 由于借款金额为 0,闪电贷的余额检查通过。
- 利用刚刚获得的授权,通过
transferFrom将池子中的所有 DVT 代币转走。
- 调用
- 核心教训:闪电贷合约不应提供执行任意外部调用的能力。应遵循标准回调模式,限制借款人的操作。
2. Side Entrance: 被混淆的存款与还款
- 挑战目标:初始有 1 ETH,需要从一个包含 1000 ETH 的池子中拯救所有 ETH。
- 漏洞核心:
flashLoan()函数仅检查合约在闪电贷前后的 ETH 余额是否一致。它没有区分“偿还贷款”和“进行存款”,这两者都会增加合约的 ETH 余额。 - 攻击手法:
- 调用
flashLoan,借出池子里的所有 ETH。 - 在
execute()回调函数中,将借来的 ETH 作为存款(deposit)重新存入池子。 - 此时,池子的 ETH 余额已恢复,闪电贷的余额检查通过。
- 但池子的会计系统认为攻击者有一笔存款。攻击者调用
withdraw,将池子里的所有 ETH(包括自己的存款)取走。
- 调用
- 核心教训:闪电贷合约应使用
transferFrom主动从借款人那里拉取资金,而不是被动等待借款人推送资金。这可以清晰地区分还款和存款操作。
3. Unstoppable: 破坏内部会计的DoS攻击
- 挑战目标:初始有 10 个 DVT 代币,需要让一个持有 100 万 DVT 并提供免费闪电贷的金库停止服务。
- 漏洞核心:
flashLoan()函数在执行前会检查convertToShares(totalSupply) != balanceBefore。该检查用于确保金库的总资产价值与总份额价值是1:1锚定的。 - 攻击手法:
- 作为普通用户,直接调用 DVT 代币的
transfer函数,向金库合约地址捐赠 1 个 DVT 代币。 - 该操作会直接增加金库的底层资产余额(
balanceBefore),但不会增加其总供应量(totalSupply)。 - 这种不平衡破坏了 1:1 的锚定关系,导致金库的
flashLoan函数永远在检查处失败,从而拒绝服务。
- 作为普通用户,直接调用 DVT 代币的
- 核心教训:协议应统一状态更新入口,避免外部操作绕过内部记账逻辑。任何能改变合约状态的途径都应被考虑在内。
🛡️ 如何防御闪电贷攻击?
-
对开发者而言:
- 严格限制外部调用:避免在闪电贷流程中提供执行任意调用的后门。
- 区分操作语义:明确区分存款、还款、提款等操作,确保会计逻辑清晰。
- 使用拉取模式:闪电贷结束后,使用
transferFrom从借款人处拉取资金,而非等待其主动归还。 - 采用时间加权平均价格:使用 TWAP 等机制,避免依赖可被瞬时操纵的现货价格。
- 进行全面的安全审计:专业的审计是发现潜在逻辑漏洞的关键。
-
对普通用户而言:
- 设置滑点保护:在 DEX 交易时设置合理的滑点容忍度,避免因价格操纵导致意外损失。
- 谨慎授权:定期检查并撤销不必要的合约授权,减少资产风险敞口。
💎 总结
闪电贷本身是一个中性的金融工具,其风险源于不严谨的合约实现。DVD 的这几个挑战精准地揭示了闪电贷攻击的几种典型模式:
- Truster 展示了权限管理失败的风险。
- Side Entrance 暴露了会计逻辑混淆的后果。
- Unstoppable 则强调了状态一致性的重要性。
这些实战案例提醒我们,在 DeFi 开发中,必须对每一行代码、每一个外部调用和每一种状态变化都保持极度的警惕。