这段时间听到很多黑客攻击事件,不免让人惴惴不安。虽然大多发生在一些新的项目,但金额都挺大,而且一般都是审计过的知名项目。所以,还是安全为上,自己多看多想,自己做判断,一些风险大的项目就不要参与了,特别是跨链桥!
重翻了下以太坊的安全问题,里面着重强调了重入攻击。以前也曾了解些,没有深入,现在刚好趁着空闲,来尝试下重入攻击。
重入攻击最早最知名的是DAO这个项目,事件发生后导致了ETC的分叉,后果还是很严重的。我查了下代码 ,想重现下,其实真是我想多了,漏洞早就修补好了!
发生场景
重入攻击发生在以太坊转帐的时候,msg.sender.call.value(_amount)();
这条代码有重入风险。以太坊有两种帐户类型:一是外部帐户(用户地址),另一个是合约帐户 。如果是外部帐户,代码可以正常执行。但如果是合约的话,这条代码就有问题了。msg.sender.call.value(_amount)();
会触发这个合约的fallback函数!如果fallback函数有恶意代码,那乐子就大啰!比如这样:
fallback() payable external {
ibank.withdraw();
}
这就相当于重复不停地取以太坊了!
复现了一下代码,这些代码早就不能用啰,是我想多了!如下所示:
msg.sender.call.value(_amount)(); //重入代码,早已修补!
找了下新的写法,msg.sender.call{value: 1 ether}(""); 新写法
,其实也是没有重入风险了。当然现在一般不用这么底层的写法了,推荐使用transfer
, 是这样的payable(msg.sender).transfer(1 ether);
。transfer
有2300gas的限制,所以不可能有重入风险了。