《我学区块链》—— 十、以太坊安全之 漏洞清单

十、以太坊安全之 漏洞清单

       遵循 ERC20 标准开发的 token 合约只能说完成了代币合约的基本功能,并且便于使用。但区块链甚至以太坊毕竟也是个新鲜事物,因此随着时间过去,以太坊和 Solidity 语言本身固有的缺陷,以及相关安全规范不足的问题逐渐暴露出来,再由于区块链技术的不可撤消性,这就要求我们在开发用于生产环境的智能合约时,还要较多考虑一些安全方面的问题。

       本节先简单罗列下以太坊自运行以来,由于漏洞已经爆出的一些重大安全事件。

以下内容转自 以太坊目前已知安全问题总结,如何打造安全的以太坊智能合约。

       智能合约语言 Solidity 自身与合约设计都可能存在漏洞。如果智能合约开发者疏忽或者测试不充分,而造成智能合约的代码有漏洞的话,就非常容易被黑客利用并攻击。 —— 众享比特

       以太坊Ethereum是一个开源的有智能合约功能的公共区块链平台。区块链上的所有用户都可以看到基于区块链的智能合约。但是,这会导致包括安全漏洞在内的所有漏洞都可见。智能合约语言 Solidity 自身与合约设计都可能存在漏洞。如果智能合约开发者疏忽或者测试不充分,而造成智能合约的代码有漏洞的话,就非常容易被黑客利用并攻击。并且越是功能强大的智能合约,就越是逻辑复杂,也越容易出现逻辑上的漏洞。

1、以太坊的安全漏洞

       如果说区块链也有 315,那么以太坊想必榜上有名。以太坊自运行以来多次爆出过由于漏洞造成的重大安全事件。

       2016 年 6 月 17 日,区块链出现了历史上沉重的一次攻击事件。由于以太坊的智能合约存在着重大缺陷,区块链业界最大的众筹项目 TheDAO(被攻击前拥有约 1 亿美元的资产)遭到攻击,导致 300 多万以太币资产被分离出 TheDAO 资产池。

       2017 年 7 月 21 日,智能合约编码公司 Parity 警告其 1.5 版本及之后的钱包软件存在漏洞,据 Etherscan.io 的数据确认,有价值 3000 万美元的 15 万以太币被盗。2017 年 11 月 8 日,Parity 钱包再出现重大 bug,多重签名漏洞被黑客利用,导致上亿美元资金被冻结。

       以太坊开源软件主要是由社区的极客共同编写的,目前已知存在 Solidity 语言漏洞、短地址漏洞、交易顺序依赖、时间戳依赖、可重入攻击等漏洞,在调用合约时漏洞可能被利用,而智能合约部署后难以更新的特性也让漏洞的影响更加广泛持久。

据有关调查统计,以太坊主要漏洞情况描述如下表:

序号 漏洞名称 漏洞描述
1 The DAO 漏洞 运行在以太坊公有链上的 TheDAO 智能合约遭遇攻击,该合约筹集的公众款项不断被一个函数的递归调用转向它的子合约,涉及总额三百多万以太币。代码中通过 addr.call.value() 的方式发送以太币,而不是 send(),这给黑客留下了空间。黑客只需要制造出一个 fallback 函数,在该函数里再次调用 splitDAO() 即可。
2 Parity 多重签名钱包合约漏洞 使多重签名的智能合约无法使用,核心问题在于越权的函数调用。黑客间接调用了初始化钱包软件的库函数,让自己成为多个 Parity 钱包的新主人。黑客调用了一个叫做 initWallet()的函数,它没有检查以防止攻击者在合同初始化后调用到 initMultiowned(),这个函数使得这个合约的所有者被改为攻击者,相当于从 Unix 中获得了 root 权限。
3 Parity多重签名钱包提款漏洞 钱包的提款功能都失效,150多个地址中超过50万个ETH被彻底冻结,漏洞使得黑客能通过库函数成为库的主人,然后调用自杀函数报废整个合约库。
4 太阳风暴 Solidity,以太坊用于开发智能合约的类java-script语言,被发现有一个安全漏洞,当以太坊合约进行相互调用时,它们自身的程序控制和状态功能会丢失。因为它能切断以太坊智能合约间的沟通,就像太阳风暴能切断地球的通讯设备一样,可以影响整个以太坊。
5 以太坊编程语言Solidity漏洞 影响了智能合约中一些地址以及数据类型,大多数受影响的合约将无法被撤回或更改。
6 智能合约Fallback函数 当调用某个智能合约时,如果指定的函数找不到,或者根本就没指定调用哪个函数(如发送以太币)时,fallback函数就会被调用,黑客可以利用fallback函数做出很多危害系统的事情。
7 智能合约递归调用(recursive) 用户取款的代码存有严重的递归调用漏洞,该用户可轻松地将你账户里的以太币全部提走。
8 调用深度限制(call depth) 以太坊虚拟机EVM中一个智能合约可以通过message call调用其它智能合约,被调用的智能合约可以继续通过message call再调用其它合约,甚至是再调用回来(recursive)。黑客可以利用嵌套调用的深度被限定1024发动攻击。
9 以太坊浏览器Mist 这个漏洞来源于底层软件框架Electron,使得加密数字货币私钥安全受影响。
10 区块节点漏洞 来自于以太坊区块链上2283416区块节点的漏洞,主要造成了包括Geth在内的所有基于Go语言编写的以太坊1.4.11版本客户端出现内存溢出错误,并阻止了进一步挖矿。
11 日食攻击(eclipse attack) 日食攻击是其他节点实施的网络层面攻击,其攻击手段是囤积和霸占受害者的点对点连接时隙(slot),将该节点保留在一个隔离的网络中。这种类型的攻击旨在阻止最新的区块链信息进入到日食节点,从而隔离节点。
12 以太坊短地址漏洞 由于EVM并没有严格校验地址的位数,并且还擅自自动补充消失的位数,使得合约多发送很多代币出来。
13 Geth客户端DoS攻击漏洞 大约75%的以太坊节点都在运行Geth,这个漏洞可能会使那些运行兼容拜占庭的版本的节点在硬分叉之后更加容易遭受DoS攻击。
14 浪子合约漏洞 交易资金因为漏洞返还给所有者、交易者过去发送给以太网的地址,以及特定地址。这种漏洞就像是空手套白狼,买家得到商品,而卖家无法得到加密货币。
15 自杀合约漏洞 智能合约的拥有者可以在以太坊发生故障时选择退回,类似于微信中的撤回选项。但是这个指令也可以被其他人执行,使得交易失败。
16 贪婪合约漏洞 这是指那些永远停留在以太坊的智能合约,上述的 Parity 漏洞正是一种贪婪合约,它会把智能合约所涉及的商品以及加密货币锁定在以太坊中,交易双方均无法得到,也不能取消。
17 遗嘱合约漏洞 在那些已完成或者被关闭的智能合约中,虽然他们的代码和全局变量被清楚了,但是其中一部分仍然在继续执行。遗嘱合约和贪婪合约一样,均是由以太坊的错误引起,目前并不能被黑客利用。
18 交易顺序依赖性 一笔交易被传播出去并被矿工认同包含在一个区块内需要一定的时间,如果一个攻击者在监听到网络中对应合约的交易,然后发出他自己的交易来改变当前的合约状态,例如对于悬赏合约,减少合约回报,则有一定几率使这两笔交易包含在同一个区块下面,并且排在另一个交易之前,完成攻击。而这个攻击者甚至可以自己直接参与挖矿,并提出更高的gasPrice来激励矿工包含这笔交易。
19 时间戳依赖性 有一部分智能合约使用区块的时间戳来作为某些操作的触发条件。通常来说都是使用矿工的本地时间作为时间戳,而这个时间大约能有900秒的范围波动,当其他节点接受一个新区块时,只需要验证时间戳是否晚于之前的区块并且与本地时间误差在900秒以内。一个矿工可以通过设置区块的时间戳来尽可能满足有利于他的条件,从中获利。
20 可重入性 当一个合约调用另一个合约的时候,当前执行进程就会停下来等待调用结束,这就导致了一个可以被利用的中间状态。 利用合约存在的中间状态,当一个合约还没有调用完成时发起另一个调用交易,即可完成攻击。
21 挖矿中心化 以太坊前3大矿商控制着超过50%的算力,存在联合作恶的风险。

       上述漏洞目前已经广泛存在以太坊网络中,2018年2月24日,新加坡和英国几位研究员指出,3.4万多份以太坊智能合约可能存在容易被攻击的漏洞,导致数百万美元以太币暴露在风险中,其中2365份属于著名项目。

       鉴于以太坊其运行时间还不到3年,如上漏洞可能只是其所有漏洞的冰山一角,为保证业务在区块链上安全可靠运行,保护数字资产的安全,采用以太坊做为区块链技术方案时必须对智能合约代码进行充分测试。在构造智能合约时,众享比特技术团队的安全建议如下:

  • 限制在智能合约中存储以太坊的数量。如果智能合约源代码、编译器或者平台有问题,这些资金可能丢失。
  • 尽可能保证智能合约中的功能小而模块化。源码质量一定要得到保证(比如限制局部变量的数量,函数的长度),程序注释尽量完整,以便方便日后的维护和增加代码的可读性。
  • 尽可能减少交易中gas的消耗,如果有必须使用大量计算的地方,尽量将其放到链下去处理。
  • 如果可能,合约逻辑应该避免依赖于合约余额的确切值,因为它可以被人为地操纵,比如攻击者将当前合约地址发送到其他合约的selfdestruct方法,则当前合约将不得不接受因此转移过来的 ether。
  • 在智能合约中添加一个函数,执行一些自我检查,如“有没有以太泄漏?”。如果自检失败,智能合约会自动切换到某种“故障安全”模式,例如,禁用大部分功能,将控制交给固定和可信的第三方,或者将智能合约转换成简单的“把我的钱还给我”智能合约。
  • 目前以太坊的 Solidity 问题的确挺多,类似的合约语言还有 Serpent,而 Synereo 的 Rholang 在安全方面会美好一些。


thead {font-weight: bold; }
.head1 {min-width: 28px; text-align: center;}
.head2 {min-width: 110px; text-align: center;}
.head3 {text-align: center;}
tbody tr:nth-child(2) {background:RGB(248, 248, 248);}
tbody tr td:first-child {text-align:center;}
tbody tr td:nth-child(2) {text-align:center;}

你可能感兴趣的:(《我学区块链》)