重入破绽置信大家都有所耳闻,那么什么是重入破绽呢?
家喻户晓,以太坊的转账不仅能够在钱包地址之间进行,合约与钱包地址之间、合约与合约之间也能够,而合约在接管到转账的时候会触发 fallback 函数执行相应的逻辑,这是一种暗藏的内部调用。攻击者就会利用这一点,在合约的 fallback 函数中写入歹意逻辑从新进入到被攻打的合约外部,让被攻打的合约执行非预期的内部调用,从而达到获取不正当利益的目标。
破绽示例
上面咱们来看一个比拟典型的有重入破绽的代码:
破绽剖析
下面的代码就是个一般的充提币的合约,那么怎么对其发动重入攻打呢?咱们来看这个合约的 withdraw 函数,这个函数中的转账操作有一个内部调用“msg.sender.call{value: bal}”,所以咱们就能够认为这个合约是可能有重入破绽的,让咱们来进一步剖析看看:
在 withdraw 函数中是先执行内部调用进行转账后才将账户余额清零的,那么就能够在转账内部调用的时候结构一个歹意的逻辑合约在合约执行 balance[msg.sender]= 0 之前始终循环调用 withdraw 函数始终提币从而将合约账户清空。
攻打合约
上面咱们看看攻击者编写的攻打合约中的攻打手法是否与咱们的破绽剖析雷同:
咱们看到 EtherStore 合约是一个充提合约,咱们能够在其中充值和提现。攻击者先调用合约中的攻打函数先向 EtherStore 中充值 1ether,在 EtherStore 中他的账户余额就为 1ether, 那么他就能够提现这些余额。紧接着,withdraw 函数发动提现,当 EtherStore 向攻打合约转账实现时,攻打合约就会调用 fallback 函数,再次申请提现余额,如此循环就能将 EtherStore 中的余额提现到有余 1ether,才完结这个循环。
攻打函数调用流程图:
修复倡议
看了下面的攻打手法置信大家对重入破绽都会有一个本人的认知了,然而咱们的应该怎么防止重入破绽进攻重入攻打呢?以下是我给大家的倡议:1. 写代码时须要遵循先判断,后写入变量在进行内部调用的编码标准(Checks-Effects-Interactions)。2. 退出防重入锁。上面是一个防重入锁的代码示例:
3. 记住所有波及到内部合约调用的代码地位都是不平安的。
那么智能合约中的重入攻打就解说完了,如果想理解更多的区块链常识,或是有什么疑难,能够到区块链交换社区 CHAINPIP 来,一起学习和交换。
社区地址:https://www.chainpip.com/