智能合约漏洞攻击及注意事项

地铁上正好赶上,迅雷链总工程师在微信开发群 直播智能合约,受益匪浅,回家赶紧趁着热乎总结一下。

迅雷链的开发平台底层兼容以太坊的EVM虚拟机,所以开发用的智能合约语言仍然是solidity,这个语言是c++、python和javascript的衍生物,存储用的c++地址,用的python的语法,js的函数类型操作。。

迅雷链整体借鉴(copy)的以太坊,唯一的优势可能是百万级的并发处理(我猜是减少了超级节点数。。。结果查了下是用的多链框架,以太坊是一条公路的话,迅雷链copy过来后并行地修了(copy)四条公路,不同车牌号上不同的路,真凶残)。。。还有第一年的gas消耗费用他们买单

其中介绍的智能合约开发过程中的安全注意事项很不错,如下:

1.设置函数可视性和合理的modifier(修饰器) 权限

有对外江湖的函数通常设置为public或external,内部函数设置为private或internal,另外一般使用相应的modifier限制函数操作的角色权限,这些都可以有效减少安全问题。

2.send调用可能失败,需要检测send结果后再确定是否进行下面的状态改变。

.send(uint256) returns(bool)

通常的操作逻辑可能会使,向某个账户发送一笔交易,然后改变合约内的某些数据状态。但是如果未对send函数调用的结果做检测,可能会出现send失败,但是后续状态依然被改变的结果,导致状态不一致。

举个栗子,(不一定安全的栗子):

3.循环可能导致gas被消耗完而引起合约执行失败

循环变量可能依赖外部输入,如果循环的次数过多,将会导致gas消耗递增,直至超过gasLimit,从而使得合约执行失败,回滚状态值,但是对应的gas却已经消耗不能退回。

4.调用栈深度

EVM调用堆栈限制最深1024层,从资源交易占用角度看这是必须的。同时也意味着,如果嵌套调用的数量达到1024,合约执行将会失败。攻击者可以递归调用一个合约1023次,然后再调用合约函数,造成失败一些send之类的失败,如上述第一条。

5.溢出漏洞。。。这个漏洞一行代码没防溢出,蒸发64亿。。。刺激

溢出,就是一个数字增加到它的最大值以上。Solidity可以处理多达256位的数字(高达2²⁵⁶-1),所以递增1会得0。最佳实践是通过zeppelin-solidity提供的safeMath来处理数值计算。

上面是openzeppelin实现的safeMath的乘法运算。如果乘法运算溢出,则c/a的结果不会等于b。以此保证运算的正确性。

6.可重入攻击(DAO)

在使用call来发送value时,检测外部条件顺序的不合理或调用者设置call或send对应fallback恶意转账,都可能导致状态不一致和金额的损失。

避免DAO攻击最佳实践就是使用transfer来实现转账,并使用require检测结果。

7. selfdestruct 的执行参数如果是合约地址,将不会执行合约的fallback

如果一个合约A的selfdestrcut(sender)的sender是一个合约地址B,B合约将不会使用fallback来接收A的selfdestruct带来的转账。由此可能产生绕过合约逻辑的风险。

8. 短地址攻击

短地址攻击是针对基于ERC20类型的token transfer时的问题。在调用transfer(address addr, uint amount)时,实际发送交易的是abi编码后的16进制代码,其中每个参数长度是固定的,如果长度不足会自动补0。

漏洞即源于此,如果addr的最后是以0结尾的,而攻击者少输入最后的0,amount编码高位补0,导致amount编译值比实际输入值大。从而实现转移超出实际应该transfer的数量的token。实践中,需要在transfer方法检查长度来限制此类问题。

合约的安全实践需要持续的关注和更新,并做好合约的审计和升级,必要情况下可设置一些紧急停止或转移合约功能的方法,以备不时之需。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180516G1XSLF00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

同媒体快讯

扫码关注云+社区

领取腾讯云代金券