Euler Finance遭闪电贷攻击,损失1.97亿美金!漏洞分析附PoC
字数 1335 2025-08-11 08:36:00
Euler Finance 闪电贷攻击漏洞分析教学文档
1. 事件概述
- 时间: 2023年3月13日 UTC时间08:56:35
- 损失金额: 1.97亿美元
- 涉及代币: 6种不同代币
- 攻击类型: 闪电贷攻击
- 漏洞位置:
donateToReserves函数缺少流动性检查
2. 攻击流程详解
2.1 攻击准备阶段
-
闪电贷借款:
- 从Aave协议借入3000万DAI
- 部署两个合约: 借贷合约和清算合约
-
初始存款:
- 将2000万DAI存入Euler Protocol
- 获得1950万eDAI(抵押代币)
2.2 杠杆操作阶段
-
首次借款:
- 利用mint函数借出10倍杠杆:
- 借出1.956亿eDAI
- 借出2亿dDAI(债务代币)
- 利用mint函数借出10倍杠杆:
-
部分还款:
- 使用剩余的1000万DAI偿还部分债务
- 销毁1000万dDAI
- 再次借出1.956亿eDAI和2亿dDAI
2.3 漏洞利用阶段
-
捐赠攻击:
- 调用
donateToReserves函数捐赠10倍偿还资金(1亿eDAI) - 此操作使账户处于可清算状态
- 调用
-
清算操作:
- 调用liquidate函数进行清算
- 获得清算奖励:
- 3.1亿dDAI
- 2.5亿eDAI
2.4 获利退出阶段
- 资金提取:
- 通过withdraw函数提取3890万DAI
- 归还Aave闪电贷3000万DAI
- 最终获利: 887万DAI
3. 漏洞技术分析
3.1 关键函数对比
正常函数(mint):
function mint(...) {
// ...
checkLiquidity(account); // 关键流动性检查
// ...
}
漏洞函数(donateToReserves):
function donateToReserves(...) {
// 缺少checkLiquidity检查
// ...
}
3.2 漏洞原理
-
流动性检查缺失:
donateToReserves函数未调用checkLiquidity- 允许用户故意使自己处于可清算状态
-
清算机制滥用:
- 攻击者通过捐赠大量资金人为制造可清算状态
- 然后自己清算自己获取奖励
-
杠杆循环利用:
- 通过多次借款/还款放大资金规模
- 利用协议的高杠杆特性(10倍)
4. 漏洞修复建议
-
添加流动性检查:
- 在
donateToReserves函数中添加checkLiquidity调用
- 在
-
清算保护机制:
- 禁止用户清算自己的账户
- 设置清算最小时间间隔
-
杠杆限制:
- 设置单次操作的最大杠杆倍数
- 实施逐步增加的借款利率
-
捐赠限制:
- 设置捐赠金额上限
- 添加捐赠冷却时间
5. 安全开发实践
-
关键操作检查清单:
- 所有资金操作函数必须包含流动性检查
- 实现完整的权限控制和状态验证
-
借贷协议特殊注意事项:
- 资金偿还流程验证
- 实时流动性检测机制
- 债务清算安全边界
-
审计要点:
- 完整的状态机验证
- 所有外部调用函数的重入保护
- 全面的边界条件测试
6. 攻击复现(PoC)
参考Numen Cyber提供的PoC代码:
GitHub PoC链接
复现步骤:
- 设置测试环境(Fork主网状态)
- 部署攻击合约
- 执行闪电贷借款
- 按攻击流程执行各步骤
- 验证最终获利金额
7. 总结与启示
-
审计重要性:
- 合约上线前必须经过专业安全审计
- 特别关注状态转换和边界条件
-
协议设计原则:
- 最小权限原则
- 完备性检查原则
- 失败安全原则
-
监控与响应:
- 实时异常交易监控
- 紧急暂停机制
- 漏洞响应预案
-
行业建议:
- 建立安全开发标准
- 实施多层防御策略
- 定期安全培训更新