ugChain技术团队

以太坊智能合约编程的典型漏洞汇集

2018-05-19  本文已影响104人  Buffalo_Lv

PeckShield网站近期公布了一些以太坊智能合约漏洞分析,包括

 batchOverflow[1], proxyOverflow[2], transferFlaw[3],ownerAnyone[4], multiOverflow[5],

看了一下,感觉以太坊智能合约编程容易出问题的地方还是蛮多的,这些问题都是由于以太坊智能合约本身的特殊性决定的(控制资金流转,功能函数直接面向用户,合约部署后无法做升级修护等等)。

这里先记录一点整理,后续陆续记录、分析;

编程语言语法、语义要熟悉

估计有不少人,比如我,solidity编程就是稍微看了点例子,就直接动手编写代码的,这样就很可能会隐含了一些意想不到的错误,所以应该要尽量熟悉solidity语法。若没时间去抠语法细节,就要用非常简单的、没有歧义的语句来表达程序功能,未必要用编程语言本身提供的复杂的功能。不明确的、有点绕弯的功能,可以不用。


整数算术运算溢出

若不想使用SafeMath,涉及到两个无符号数相加或相乘的时候,可以先计算,然后判断其结果应该大于任何一个操作数

SUM = A + B

require(SUM >= A && SUM >= B)

MUL = A * B

require(MUL>= A && MUL >= B)

若涉及减法,可以这么写:

require(A >= B)

SUB = A - B

对于除法:

require(A >= B && B != 0)

DIV = A / B

类似的,还有乘方操作,都是按照这个思路加必要的判断语句就可以了。

合约地址与普通地址区分对待

涉及到汇款、转账操作时,一定要注意区分接收者是普通账户,还是合约账户,尽量不在一个合约里给另一个合约地址转账;

外部程序判断:

var code = web3.eth.getCode("account_address")

if(code === '0x') console.log('regular account')

else console.log('contract accout')

合约内部判断:

function isContract(address _addr) private returns (bool isContract) {

  uint32 size;

  assembly {

    size := extcodesize(_addr)

  }

  return (size > 0);

}


尽量不用递归调用,仔细考虑被调与主调关系

合约编程和一般的编程不一样,更注重安全可靠,尽量不要用递归。合约代码尽量是封闭的,既不调用未知的代码,也不被未知的代码调用(通过加某些特殊判断语句)。若做不到这一点,就需要慎重考虑如果别人的未知代码调用我的代码,可能发生什么,我的代码调用了别人的未知代码会发生什么。

合约用户归类,合约函数归类,某些函数不能让任何人都能调用

若某些函数的功能比较特殊,则可以设计为只有owner可以调用,或者是owner授权的用户才能调用,不可以让任意用户都可以发交易触发调用。比如针对proxyOverflow漏洞来说,那个代理函数其实应该由合约部署者授权调用的,然而却没有加限制,导致攻击者在一笔交易中构造出特殊的参数,并触发了函数运行,通过整数溢特性出制造了巨量的Token。

上一篇 下一篇

猜你喜欢

热点阅读