ERC中的重入
所有重入的本质都是不可控的外部调用
注意:0.8.0 版本以后或使用了 SafeMath 的合约,重入时不能选择状态变量更改为 -= 的模式,否则会因为下溢而 revert
1 |
|
比如以上模式就不能重入,只能提取自己真正拥有的代币
ERC20
原理
ERC20 中的重入也就是最基础的重入,发生在 ETH 和 ERC20 代币的交换过程中,使用 call 低级调用,并未遵守检查-生效-交互模式,攻击者可以通过重写 fallback 或者 receive 函数来进行重入
详情见以前的博客
复现
reentrancy-exp/contracts/erc20
运行命令
1 |
|
ERC223
原理
ERC223 相对于 ERC20,增加了 tokenReceived 函数,本意是防止意外发送的代币被合约接受(并卡在合约的余额中),但是增加了重入风险
黑客可以利用该函数调用原合约中的问题函数(如未遵守检查-生效-交互模式的函数),多次重入
复现
reentrancy-exp/contracts/erc223
运行命令
1 |
|
相关事件
CTF-Tokenbank
[capture the ether - Token-bank](https://sissice.github.io/2022/04/02/capture the ether wp/#Token-bank)
ERC777中的重入
原理
ERC777 引入了“钩子”的概念,以解决 ERC20 的一些缺陷。使用挂钩让合约知道它正在接收或发送资金并允许它采取行动。
增加了两个需要用户自己实现的函数:tokensToSend 和 tokensReceived
使用挂钩,接收联系人可以在收到令牌时执行操作,例如,如果向其发送了错误类型的令牌,则取消交易。所以 Tokenlon 似乎做出了正确的选择:所有 ERC20 的优点加上一些额外的很酷的功能。然而,正如他们沮丧地发现的那样,ERC777 钩子也为一些严重的攻击打开了大门!
如上所示,ERC777 挂钩允许合约在接收或发送资金时执行附加功能。然而,这个功能可能被滥用,允许恶意合约对毫无戒心的调用合约的问题函数,执行重入攻击。
可以重入的场景:
- 在余额更新之前在转账功能中向收件人(或攻击者控制的任何其他帐户)进行外部调用。
- 在更新余额之前或之后在transferFrom函数中对令牌花费者(或攻击者控制的任何其他帐户)进行外部调用。重要的是要注意所有的transferFrom函数总是以交易所作为接收者来调用,因此在不同的 ERC20 扩展中常见的对接收者的回调并不危险。
复现
reentrancy-exp/contracts/erc777
运行命令
1 |
|
相关事件
imBTC
2020 年 4 月 18 日 imBTC Uniswap 池被黑客攻击并耗尽了价值 30 万的代币
问题主要是在uniswap中ERC777会发生重入
攻击交易:0x32c83905db61047834f29385ff8ce8cb6f3d24f97e24e6101d8301619efee96e
Cream Finance
2021 年 8 月 30 日, Cream Finance 遭遇闪电贷攻击,攻击者利用漏洞共计获利5890ETH(约合1880万美元)。
由于 AMP 支持类似 ERC-777 的代币标准,而它的特性与某些协议不相兼容,此次 Cream.Finance 的重入攻击正是操纵了此漏洞。
这里在更新存储之前进行了转移贷款的操作
攻击交易:0xc90468d698700757f33543039c7cb10d4ca49d57b5417789e7656e73019de674