区块链 智能合约安全 重入攻击(re-entrancy attack)DAO incident

博客介绍了区块链合约资金泄露的情况,如转给非指定收款人或超额转账。以DAO合约攻击为例,攻击者利用重入攻击盗取6000万美元。当收款人是合约时,可回调withdraw()多次提款,而收款人是用户则无法回调,执行正常结束。

泄露资金的合约

合约有多种导致资金泄露的方式。例如,合约可能将资金转给非指定的收款人;或者将超额资金转给合法收款人等。

以下展示了对DAO合约的攻击,该攻击者借此盗取了6000万美元。大家可以观察到,该合约有一个状态变量shares。将状态变量视为可由任何函数访问的全局变量。

  • shares维护用户地址和相应份额之间的映射。
  • 股东可以调用withdraw()来提取他们的份额。
contract UnsafeContract1{

    // Mapping of address and share

    mapping(address => uint) shares;


    // Withdraw a share

    function withdraw() public {

        if (msg.sender.call.value(shares[msg.sender])())

            shares[msg.sender] = 0;

    }

}

如果用户在链外调用withdraw(),那么UnsafeContract1将以良性方式运行。

在这种情况下,合约发送一条消息将份额通过msg.sender.call.value()转给用户,然后通过更新下一行中的shares将份额设置为0。

攻击发生的情况是,收款人是一个合约而非用户。当合约调用方调用withdraw()时,被调用者执行msg.sender.call.value()并将执行控制权传递给调用者即合约,在这种情况下可以回调到withdraw()。

 

请注意,在withdraw()中,只有在if(msg.sender.call.value())终止后,调用方的shares才会更新为0。当恶意合约回调withdraw()时,它实际上是通过强制它停留在if()指令,来防止程序指针更新shares。这允许恶意合约多次提款,直到其燃料费被消耗殆尽。

如果收款人是用户而非合约,那么他将无法回调合约,因此执行将按预期结束。

这种攻击也被称为重入攻击(re-entrancy attack)。



作者:Zilliqa爱好者中文社区
链接:https://www.jianshu.com/p/5379e44280f5
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

软件工程小施同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值