以太坊是一个开源的有智能合约功能的公共区块链平台。区块链上的所有用户都可以看到基于区块链的智能合约。但是,这会导致包括安全漏洞在内的所有漏洞都可见。智能合约语言 Solidity 自身与合约设计都可能存在漏洞。如果智能合约开发者疏忽或者测试不充分,而造成智能合约的代码有漏洞的话,就非常容易被黑客利用并攻击。并且越是功能强大的智能合约,就越是逻辑复杂,也越容易出现逻辑上的漏洞。
以太坊的安全漏洞
如果说区块链也有 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 智能合约遭遇攻击,该合约筹集的公众款项不断被一个函数的递归调用转向它的子合约,涉及总额三百多万以太币。代码中通过 |
2 | Parity 多重签名钱包合约漏洞 | 使多重签名的智能合约无法使用,核心问题在于越权的函数调用。黑客间接调用了初始化钱包软件的库函数,让自己成为多个 Parity 钱包的新主人。黑客调用了一个叫做 initWallet() 的函数,它没有检查以防止攻击者在合同初始化后调用到 initMultiowned() ,这个函数使得这个合约的所有者被改为攻击者,相当于从 Unix 中获得了 root 权限。 |
3 | Parity 多重签名钱包提款漏洞 | 钱包的提款功能都失效,150 多个地址中超过 50 万个 ETH 被彻底冻结,漏洞使得黑客能通过库函数成为库的主人,然后调用自杀函数报废整个合约库。 |
4 | 太阳风暴 |
Solidity 是以太坊用于开发智能合约的类 JavaScript 语言,被发现有一个安全漏洞,当以太坊合约进行相互调用时,它们自身的程序控制和状态功能会丢失。因为它能切断以太坊智能合约间的沟通,就像太阳风暴能切断地球的通讯设备一样,可以影响整个以太坊。 |
5 | 以太坊编程语言 Solidity漏洞 | 影响了智能合约中一些地址以及数据类型,大多数受影响的合约将无法被撤回或更改。 |
6 | 智能合约 Fallback 函数 | 当调用某个智能合约时,如果指定的函数找不到,或者根本就没指定调用哪个函数(如发送以太币)时, fallback 函数就会被调用,黑客可以利用 fallback 函数做出很多危害系统的事情。 |
7 | 智能合约递归调用 |
用户取款的代码存有严重的递归调用漏洞,该用户可轻松地将你账户里的以太币全部提走。 |
8 | 调用深度限制 | 以太坊虚拟机 EVM 中一个智能合约可以通过 message call 调用其它智能合约,被调用的智能合约可以继续通过 message call 再调用其它合约,甚至是再调用回来(recursive)。黑客可以利用嵌套调用的深度被限定 1024 发动攻击。 |
9 | 以太坊浏览器 Mist | 这个漏洞来源于底层软件框架 Electron,使得加密数字货币私钥安全受影响。 |
10 | 区块节点漏洞 |
来自于以太坊区块链上 2283416 区块节点的漏洞,主要造成了包括 Geth 在内的所有基于 Go 语言编写的以太坊 1.4.11 版本客户端出现内存溢出错误,并阻止了进一步挖矿。 |
11 | 日食攻击 | 日食攻击是其他节点实施的网络层面攻击,其攻击手段是囤积和霸占受害者的点对点连接时隙,将该节点保留在一个隔离的网络中。这种类型的攻击旨在阻止最新的区块链信息进入到日食节点,从而隔离节点。 |
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 的消耗,如果有必须使用大量计算的地方,尽量将其放到链下去处理。
- 在智能合约中添加一个函数,执行一些自我检查,如“有没有以太泄漏?”。如果自检失败,智能合约会自动切换到某种“故障安全”模式,例如,禁用大部分功能,将控制交给固定和可信的第三方,或者将智能合约转换成简单的“把我的钱还给我”智能合约。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/46874.html