Medusa - 智能合约 Fuzzing 工具在 Truebit Protocol 案例中如何应用?
摘要:案例背景 20260109,ETH 链上的 Truebit Protocol 遭受了黑客攻击,损失约 2600 万美元。漏洞原因是计算购买 TRU 代币所需要的 ETH 数量的计算公式设计存在缺陷,购买大量 TRU 代币时会因为 0.6.1
案例背景
20260109,ETH 链上的 Truebit Protocol 遭受了黑客攻击,损失约 2600 万美元。漏洞原因是计算购买 TRU 代币所需要的 ETH 数量的计算公式设计存在缺陷,购买大量 TRU 代币时会因为 0.6.10 版本没有防溢出机制而发生上溢出得到 0 值,使得攻击者可以以 0 ETH 购买大量的 TRU 代币,最后抛售完成获利。
前置内容-完整攻击分析:https://www.cnblogs.com/ACaiGarden/p/19465686
TX:https://app.blocksec.com/explorer/tx/eth/0xcd4755645595094a8ab984d0db7e3b4aabde72a5c87c4f176a030629c47fb014
Trace 分析
黑客调用 buyTRU() 函数以零成本购入大量的 TRU 代币
然后调用 sellTRU() 函数卖出所有 TRU 代币完成获利
随后攻击者利用漏洞以零或极低成本的价格购买 TRU 代币后出售的流程重复多次。
Medusa 配置
首先参考《Medusa - 智能合约 Fuzzing 工具介绍与案例讲解》中的内容对 Medusa 进行初始化与配置。
Fuzz 函数挑选与实现
Fuzz 函数挑选
在编写 fuzz 函数之前,首先要挑选需要对哪些函数进行 fuzz,可以按照以下的条件进行筛选:
public 或 external 的函数
非 view 和 prue 的函数
没有权限访问控制的函数
非一次性调用的函数(如 initialize)
其中满足以上条件的函数有
- `0xa0296215(uint256)`(购买/铸造路径:依赖 `msg.value` 与定价计算,容易出现边界值/除零/舍入问题)
- `0xc471b10b(uint256)`(赎回/燃烧路径:依赖 `allowance`、`transferFrom`、对外部合约调用与 ETH 转账,容易出现重入/资金守恒/状态不一致问题)
- `0xdb5c0f79()`(`payable` 增加储备:fuzz `msg.value` 与多次调用组合)
Fuzz 函数实现
在 TRUVulnerabilityFuzz 合约中,实现了对 0xa0296215(buyTRU(uint256 amount)) 和 0xc471b10b(sellTRU(uint256 amount)) 两个未开源函数的 fuzz,以及一个检查函数 property_checkBalance()
0xa0296215(buyTRU(uint256 amount):需要调用 getPurchasePrice 函数(反编译的时候提供了函数名)计算对应的 msg.value ,伴随函数调用传入。
0xc471b10b(sellTRU(uint256 amount)) :直接提供卖出的 TRU 代币数量,需要实现 receive 函数接收返回的 ETH 代币。但是在 fuzz 过程中 Medusa 会尝试往 receive 函数中转账,所以要添加权限控制。
property 函数则检查了合约的余额(初始值为 1e28)经过 sequence 操作后是否增加,如果增加则判断发现了获利的途径。
