Dos***
dos***也叫做拒绝服务***,通过使程序操作无效完成***的目的。
下面的一段合约是2016年KotET(“纷争时代”)合约,其遭受了dos***。本小节将揭开此合约被***的秘密。
源代码
在下面KotET合约代码中,模拟了争夺皇位的功能。只有出价最高的人才能够夺得桂冠。 合约中的bid方法正是最核心的竞价合约。只有当msg.value即附带的以太币大于当前最大的出价人,就会首先将从前的最高价格转移给从前的出价人。完成之后,新的价格和资金会替换掉旧的资金。
1 |
pragma solidity ^0.4.23; |
***合约
下面是******的合约。***手法为:首先部署POC合约。假设为0x3456
将Auction合约的地址传递给setInstance,构建auInstance接口实例。从而能够在外部调用合约。执行attack方法,附带以太坊,例如100wei。假设还没有进行过拍卖,那么当前的最高出价地址为当前合约,最高价格为100wei。假设有另外一个人想争夺皇位,其出价了200wei 调用了Auction合约的bid方法。虽然其价格最高,但是这笔操作不能成功。原因就在于currentLeader.send(highestBid)转账,如果是合约地址,会调用合约中自定义的回调函数,而在当前案例中的回调函数,revert()意味着操作回滚,不成功。因此始终没有办法将钱还给合约,此合约将霸占王位。
1 |
pragma solidity ^0.4.23; |
解决办法
让用户自己去取钱,而不是自动的转移资金到失败者的账户中。
1 |
pragma solidity ^0.4.23; |
dos***案例2
dos***的第二个例子是,谨慎的使用循环。
如下,refundAll方法为动态数组refundAddresses中每一个账户转移资金。由于refundAddresses长度不确定。一旦超过了以太坊gaslimit的限制,就会导致这笔操作不能够成功。
对可以被外部用户人为操纵的数据结构进行批量操作,建议使用取回模式而不是发送模式,每个投资者可以使用withdrawFunds取回自己应得的代币。
如果实在必须通过遍历一个变长数组来进行转账,最好估计完成它们大概需要多少个区块以及多少笔交易。
下面合约的第二个错误在于,一旦某一个账户转账不成功,就会导致所以交易回滚,全部失败。
1 |
address[] private refundAddresses; |
参考资料
本文链接: https://dreamerjonson.com/2018/11/24/solidity-51-dos-attrack/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY 4.0 CN协议 许可协议。转载请注明出处!