ETH应用层、数据层、共识层、互联网层都有什么智能合约漏洞?
原文标题:《关于去中心化金融(DeFi)区块链智能合约漏洞的探索》
撰文:Abba Garba,WeBlock CTO
翻译:HAO
区块链是一种新的分布式系统体系,它用 点对点 对等互联网通信,区块存储,分布式算法共识和加密算法来预防篡改。从本质上讲,区块链可以看作是由所有互联网节点一同维护的分布式数据库。与传统的分布式数据库相比,区块链因为具备完整的数据备份,开放透明的互联网,没办法篡改,完整的信息可追溯性和弱信赖模,因此更合适对去中心化信赖有明确需要的应用场景。尤其是典的区块链应用场景包含数字支付,商品可追溯性,版权保护,Supply chain财务等。在区块链系统中,智能合约在推行DApps部署和扩展应用的功能方面发挥着极其要紧有哪些用途。区块链系统与传统应用程序相比,在区块链系统构造上运行的智能合约具备开放性和透明性,实行性,不可篡改且不依靠第三方的特征,可以满足各种DApps场景的需要,包含近年来进步飞速的去中心化金融(DeFi)项目。
截至 2022 年 1 月 15 日,去中心化金融(DeFi)以超越 45 亿USD的资本成为了成功的金融范例,它借助基于区块链的智能合约来确保其完整性和安全性,。去中心化金融是一个新的进步范围,用于交换,借出或借用代币。一般,这类指令由智能合约(而不是单个中心化的法人或个人)调节和 / 或由多方,去中心化治理机制(比如 DAO)控制的「收益」或收入流。去中心化金融(DeFi)—在现有区块链平台之上渐渐兴起。这个新范围的组成部分包含那些与贷款,资产买卖和衍生品市场有关的部分。作为去中心化的应用,智能合约管理着很多的数字资产,从而也使其容易遭到各种攻击。
本文将从三个维度具体讲解了智能合约安全性问题:第一,因为ETH体系结构每一层的漏洞致使的智能合约安全性。第二,也会探讨 DeFi 和智能合约最近出现的各种攻击。最后还将探讨现有些可行性工具与来其他的有效实践怎么样最大限度地降低此类攻击。
ETH构造不同层的智能合约漏洞 ETH构造概述
在探讨智能合约漏洞之前,大家先容易概述下有关ETH智能合约构造。
区块链互联网能部署并自动实行编程脚本任务。这类程序称为智能合约,用于概念在买卖期间调用的自概念功能和规则。基于智能合约的区块链技术已被应用到各种行业中,比如金融,Supply chain管理,医疗保健能源和政府服务。只有特定的区块链平台支持智能合约:ETH是第一个支持智能合约的。其他区块链平台(比如 柚子币,Lisk,BTC和 Hyperledger Fabric)兼容于部署和实行智能合约。一种称为 Solidity 的脚本类语言用于在ETH平台中开发智能合约。在这一部分中,大家介绍了ETH平台上智能合约推行的有关安全漏洞。智能合约可以持有和管理相应的功能 Credit (地址){可能价值数千USD的很多数字货币。因此,对手不断尝试操纵智能合约的实行以支持其活动。本质上,智能合约在分布式和无权限互联网上运行,该互联网继承了很多漏洞。在传统的系统中,可以重新开发或修补这一小部分的中心化应用程序。
相反,在去中心化的区块链互联网中,除非采取极端手段,不然没办法在实时互联网中修改或升级已部署的智能合约。智能合约的千篇一律特点是其安全方面的优势也是劣势。因为这种不变性,黑客没办法为我们的利益进行更改或修改合约。但,部署后开发职员也没办法修改智能合约应用程序。他们可以取消或终止合约并创建新的智能合约,然后第三部署它。因此,出于安全性考虑,在部署智能合约之前,应付智能合约进行大范围的测试。大家重点介绍了ETH智能合约构造的基本构建模块,如图 1 所示,其中包含ETH的构造。
图 1: 用于运行ETH区块链的环境是通过一个 Web 用户界面与ETH体系结构服务的四层进行交互,应用层,用于存储区块链数据的数据库,用于支持共识协议的加密机制与用于互联网层的 Internet 服务 [20]
应用层:ETH推广客户端在 EVM 中实行智能合约,其中智能合约与ETH竞价推广账户有关联。ETH支持两类型的竞价推广账户:外部拥有竞价推广账户(EOA)和合约竞价推广账户。 EOA 用于将用户资金存放在 Wei 中,Wei 是 以太币er 的最小子面额,价值 10-18 以太币er。 EOA 与公钥有关联并由公钥解决;通过显示相应私钥的所有权来验证对 EOA 的访问。相反,合约帐户与一段可实行的字节码(即智能合约)有关联,它概念了一些让人有兴趣的业务逻辑。智能合约是 DApp 的基石。 DApp 一般将用户界面作为其前端,并将一些智能合约作为其后端。一些 DApp 会发行我们的称为代币的数字货币,用于初始代币发行(ICO)和交易平台。基于ETH的代币是一种特殊的智能合约(比如 ERC-20)[20]。智能合约在 EVM 中实行,这类 EVM 是用基于堆栈的体系结构的准图灵完整机器。术语「quasi」是指实行受买卖提供的 gas 限制。在ETH应用层中,发生各种漏洞,致使很多攻击,如应用层中的图所示。
数据层:包括区块链数据结构。买卖是 EOA (称为发件人)与另一个 EOA 或合约帐户(称为收件人)之间的交互。买卖由以下方法指定:
nonce,它是用于跟踪发送方已发起的买卖总数的计数器;收件人,该收件人指定了买卖的目的 EOA 或合约帐户;价值,即从发件人向收款人转移的金额(单位:Wei)(假如适用);输入,是与买卖目的相对应的字节码或数据;gasPrice 和 gasLimit,分别指定发送方想向包括买卖的区块的获胜矿工支付的单价和最大天然气量;(v,r,s),它是发送者的椭圆曲线数字签名算法(ECDSA)签名。实行买卖会更新所涉及帐户的状况,从而更新区块链。共识层:确保区块链的状况一致。在写作本文时,ETH大约需要 12-14 秒来创建一个区块,这意味着多个矿工可以同时创建有效的区块,并且可能有很多区块。ETH用 GHOST 共识协议的变体来选择「最重」分支作为主链,其中「heaviest」分支是根植于所讨论的分叉的子树,并且具备最高的累积区块困难程度,同时注意到陈旧区块不在主链上。但注意,ETH用权益证明(PoS)替代其目前用的工作量证明(PoW)。
互联网层:管理节点或推广客户端的ETHP2P(点对点)互联网,以使节点一直可以从某些活动节点获得区块链的更新状况。ETH互联网是一个结构化的 点对点 互联网,其中每一个节点(即推广客户端)存储整个区块链的副本。为了进行节点发现和路由,每一个节点维护一个动态路由表,其中包括 160 个存储桶,每一个存储桶最多包括 16 个其他节点的 ID,IP 地址,UDP / TCP 端口条目。ETH用 RLPx 协议发现目的推广客户端,并用ETH有线协议来促进推广客户端之间ETH区块链信息(比如买卖,区块)的交换。
ETH区块链环境:运行在如下四层的环境中:用户与ETH区块链进行交互的 Web 界面 ; ETH顾客的数据库,用于存储区块链数据 ; 出于安全目的的加密机制;与支持ETH节点之间的区块链通信的网络基础设施。大家将ETH区块链构造与环境区别开来,由于针对ETH区块链的攻击可能来自环境,并且这类攻击可能在环境中得到更好的解决,而不是由ETH解决。
ETH智能合约漏洞
重点介绍了ETH体系每一层的智能合约漏洞,如图 2 所示。
图 2:ETH各层漏洞的分类
ETH应用层
重入性:此漏洞刚开始是从 DAO 攻击中发现的 [1],当外部被调用方合约在用方合约完成之前(即某种意义上是循环调用)在调用方合约中回调函数时,会发生此漏洞。这使攻击者可以绕开适合的有效性检查,直到调用者合约被耗尽ETH或买卖用完为止。
委托呼叫注入:第一从对 Parity 钱包的攻击中发现了此漏洞 [2]。为了促进代码重用,EVM 提供了一个操作码委托调用,用于将被调用方合约的字节码插入到调用方合约的字节码中。结果恶意的被调用方合约可以直接修改(或操纵)调用方合约的状况变量。此漏洞是因为被调用方合约可以更新调用方合约的状况变量而致使的。声明旨在通过委托调用作为库共享的无状况合约,可完全防此漏洞。
冻结以太:初次从对 Parity 钱包的攻击中发现了此漏洞 [3]。该漏洞产生因为用户没办法将钱存入其合约帐户,而没办法从这类帐户中支出资金,从而有效冻结了他们的资金。
升级合约:引入合约升级的思想是为了缓解智能合约一旦部署后就没办法修改的问题,即便将来发现它们存在漏洞。为了允许合约升级,有两种办法:(i)将合约分为加盟合约和逻辑合约,以使开发职员可以升级后者而不是前者; (ii)用注册管理机构合约来保存更新后的合约。这类办法虽然有效,但却引入了一个新的漏洞:当合约开发者变得恶意时,更新的合约可能是恶意的。此漏洞(即,不安全的联系人更新)仍然是一个未解决的问题。
具备意料之外还原的 DoS:发生这样的情况是什么原因,因为主叫方合约遇见外部呼叫失败而致使事务被还原,或者被叫方合约故意实行还原操作以中断主叫方合约的实行。此漏洞是由实行被调用方合约还原的调用方合约引起的。通过使接收者调用买卖来「提取」发件人为接收者预留的资金,可以预防此漏洞,从而有效地预防了发件人的买卖被还原。
整数上溢和下溢:初次从针对 BEC 代币的攻击中发现了此漏洞 [4]。当运算的结果超出了 Solidity 数据类的范围时,就会发生这样的情况,比如致使对攻击者的余额或其他状况变量进行未经授权的操纵。该漏洞是由 Solidity 源码未在数字输入上实行正确的验证引起的,并且 Solidity 编译器和 EVM 均未提供整数上溢 / 下溢测试。可以通过用 SafeMath 库来预防此漏洞处置这类问题。
操纵余额:当合约的控制流决策依靠于此值时,会发生此漏洞。平衡或解决(balance)平衡,攻击者可以借助它使自己成为唯一可以获得资金的人。可以通过不用任何条件声明中的合约余额来预防此漏洞 [5]。通过 tx.origin 进行身份验证:tx.origin 是 Solidity 中的全局变量,它指的是发起有问题买卖的原始 EOA。当合约用 tx.origin 进行授权时会发生此漏洞,这或许会遭到互联网钓鱼攻击的害处。通过用 msg.sender 而不是 tx.origin 进行身份验证,可以预防此漏洞,由于 msg.sender 返回致使该消息的帐户。
错误的可见性:错误地指定功能的可见性,从而允许未经授权的访问。
无保护的自杀:合约的所有者(或受委托的第三方)可以用自杀或自毁办法销毁合约。 取消合约时,将删除其关联的字节码和存储。 该漏洞是由合约强制实行的身份验证不足引起的。 可以通过强制实行比如多原因身份验证来缓解此漏洞,这意味着自杀操作需要得到多方的批准。
将ETH泄漏到任意地址:当任意调用方都可以提取合约的资金时,该漏洞就不会发生,该调用方不是合约的所有者,更不是向合约存入资金的投资者。 此漏洞是由调用者调用将ETH发送到任意地址的功能时没办法检查呼叫者的身份引起的。 通过对发送资金的功能进行适合的身份验证,可以预防此漏洞。
机密性失效:在区块链中,因为区块链的公共性质(即买卖细节是大家都知道的),限制变量或函数的可见性并不可以确保变量或函数是机密的。 预防此漏洞的一种可能解决方法是用加密技术,比如定时承诺 [6]。
签名信息不足:当数字签名对多个买卖有效时,就会发生此漏洞,当一个发件人(比如 Alice)通过加盟合约向多个收件人汇款(而不是发起多个买卖)时,或许会发生此漏洞。 此漏洞刚开始是在针对智能合约的重播攻击中借助的。通过在每条消息中合并适合的信息(比如现时值和时间戳)可以预防此漏洞。
具备不受限制的操作的 DoS:此漏洞第一从 Govern Mental 合约中察看到 [7]。
未经检查的呼叫返回值:此漏洞也称为处置错误的异常。它有两个变体,称为 gas-less 发送和 unchecked 发送。当不检查低级调用的返回值时会出现这样的情况,即便函数调用抛出错误 [8],实行也会会继续。
未初始化的存储指针:回顾下,在 Solidity 中,合约状况变量一直从插槽 0 开始连续放置在存储中。对于复合局部变量(比如,struct,array 或 mapping),将引用分配给未占用的对象存储中的插槽以指向状况变量。
错误的架构函数名字:此漏洞刚开始是从 Rubixi 合约 [9] 中察看到的,该架构函数的名字不正确,它使其他人都可以成为合约的所有者。在 Solidity 0.4.22 版之前,声明与合约名字相同的函数被视为合约架构函数,该函数仅在创建合约时实行。
类转换:此漏洞最早在 [10] 中发现。以 Solidity 语言撰写的合约可以通过直接引用被调用方合约的实例来调用另一个合约。
过时的编译器版本:当合约用过时的编译器时会发生,其中包括错误,因此使已编译的合约易受攻击。通过用最新的编译器可以预防此漏洞。
简短地址:此漏洞最早在 [11] 中达成,并进行了广泛讨论。
ETH丢失给孤立地址:ETH失去到孤立发生在汇款时,ETH仅检查接收者地址的长度低于 160 位,而不检查接收者地址的有效性。 假如将钱发送到一个没有的孤立地址,则ETH会自动注册该地址,而不是终止买卖。 因为该地址未与任何 EOA 或合约帐户有关联,因此无人可以提取已转移的资金,这事实上是丢失的。 此漏洞是由 EVM 不可以孤立保护引起的。 在写作本文时,只能通过手工确保收件人地址的正确性来预防此漏洞。
调用堆栈深度限制:此漏洞是由 EVM 的实行模不足引起的,并且已被 EIP-150 的硬分叉所消除,该硬叉重新概念了外部调用的耗油量规则,使其不可能达到 1,024 in 调用堆栈深度。
低估操作码:第一从两次 DoS 攻击中发现了此漏洞 [12] [13]。
买卖顺序依靠(又名前端运行):这是指并发性问题,即区块链的即将来临的状况取决于买卖的实行顺序,但由矿工决定。
时间依靠关系:当合约在实行重要操作(比如汇款)时将 block.timestamp 用作触发条件的一部分或作为可由恶意矿工操纵的随机性出处时,会发生此漏洞。该漏洞是由ETH引起的,它只须求时间戳大于其母块的时间戳并且在目前时钟的 900 秒以内。
产生随机性:比如,很多赌博和彩票合约都是随机选择中奖者,一般的做法是依据一些初始私有种子(比如 block.number,block.timestamp,block。难易度或 blockhash)生成伪随机数。但,这类种子由矿工完全控制,这意味着恶意矿工可以操纵这类变量使自己成为赢家。此漏洞是由可操纵的 entropy 源引起的。
数据层漏洞
难以分辨的链:当ETH分为 以太币 和 ETC 两条链 [13] 时,第一从跨链重放攻击中察看到此漏洞。回想一下,ETH用 ECDSA 签署买卖。在进行 EIP-155 [7] 硬分叉之前,每笔买卖都包括六个字段(即,随机数,收件人,值,输入,gasPrice 和 gasLimit)。但,数字签名不是特定于链的,由于那时甚至还不了解特定于链的信息。结果,为一个链创建的事务可被另一链重用。通过将 chainID 合并到字段中,已消除去此漏洞。
State Trie 中的「空帐户」:此漏洞第一从参考文献 [12] [13] 中报告的 DoS 攻击中发现的。
共识层的漏洞
可外包的难点:回想ETH使用了名为 以太币ash 的 PoW 难点,该难点旨在抵御 ASIC,并可以限制并行计算的用法(因为事实上,矿工的大多数工作将是读取数据集。 通过有限的内存带宽)。 但,狡猾的矿工仍然可以将搜索难点解决方法的任务划分为多个较小的任务,然后将其外包。 该漏洞是由 以太币ash 导致的,它仅使拼图形解析决策略在原图像搜索中部分顺序,而不是依靠顺序 PoW。
概率最后性:此漏洞是由ETH区块链偏爱可用性而非一致性的设计引起的,这是依据 CAP 定理 [14] 选择的。
带有块填充的 DoS:初次从 Fomo3D 合约中察看到此漏洞 [15]。该漏洞仅致使攻击者的买卖包括在新挖矿的区块中,而其他买卖则被矿工放弃一段时间。当攻击者提供更高的 gasPrice 以勉励矿工选择攻击者的买卖时,或许会发生这样的情况。此漏洞是由贪婪的挖矿勉励机制引起的。在写作本文时,尚无解决方法来预防此漏洞。
诚实的挖矿设想:此漏洞是由共识协议引起的,由于它与勉励不兼容,请参见 [16]。在写作本文时,此漏洞仍然是一个未解决的问题。
出块奖励:它是指出块奖励机制,用于应付因为迅速生成块而致使的陈旧区块增加。但,这种机制有一个不良反应,即允许自私的矿工将陈旧的区块变成出块并获得奖励,从而有效地勉励了自私的挖矿和双重支出。
验证者的困境:此漏洞最早在参考文献 [17] 中报道,指的是当验证新买卖需要不费吹灰之力的计算时,无论矿工是不是选择验证买卖,都将遭到攻击。假如矿工验证了计算量大的买卖,那样他们将花费很多时间,并在下一个区块的角逐中为攻击者提供优势;假如矿工未经验证同意买卖,则区块链可能包括不正确的买卖。此漏洞是由ETH中验证资源需要买卖的高昂本钱引起的。可以通过限制验证块中所有事务所需的计算量来缓解此漏洞 [17]。但,尚不了解怎么样消除此漏洞。
互联网层的漏洞
无限节点的创建:此漏洞是针对 G以太币 推广客户端 1.8 之前的版本。在ETH互联网中,每一个节点都由唯一的 ID 标识,该 ID 是 64 字节的 ECDSA 公钥。攻击者可以在一台计算机上创建无限数目的节点(即具备相同的 IP 地址),然后用这类节点垄断某些受害者节点的传入和传出连接,从而有效地将受害者与互联网中的其他对等节点隔离开来。此漏洞是由对节点生成过程的弱限制引起的。通过用 IP 地址和公钥的组合作为节点 ID,可以消除此漏洞。格斯(G以太币)开发职员尚未使用这种对策,他们觉得这对推广客户端的可用性有负面影响。
不受限制的传入连接:此漏洞在版本 1.8 [18] 之前的 G以太币 推广客户端中。 每一个节点在任何时间点可以具备总数为 maxpeers 的连接(默认值为 25),并且可以与其他节点发起多达 1 (1 + maxpeers)/2⌋个出站 TCP 连接。 但,其他节点启动的传入 TCP 连接的数目没上限。 通过为 maxpeers 打造与没出站连接的受害节点的很多传入连接,攻击者有机会使受害者暗然失色。 在 G以太币 v1.8 中,通过对到节点的传入 TCP 连接的数目推行上限,默认值为⌊maxpeers/3⌋= 8,消除去此漏洞。
公共对等体选择:在 G以太币 推广客户端 1.8 之前的版本中测试到此漏洞 [18]。
对等体选择:该漏洞指的是 G以太币 推广客户端在从其路由表中选择节点以打造出站连接时,一直获得随机选择的桶的头部。因为每一个存储桶中的节点都是按活动排序的,因此攻击者可以通过按期向 G以太币 推广客户端发送消息来使其节点一直坐落于其他节点之前。通过在路由表中所有节点的集合中随机选择统一的节点,而不是仅从每一个存储桶的头中随机选择节点,在 G以太币 v1.9 中已消除去此漏洞。
独立块同步:它允许攻击者对ETH 点对点 互联网进行分区,而不会垄断受害者推广客户端的连接。回想一下,每一个块标题都包括一个困难程度字段,该字段记录了该块的挖矿困难程度。区块链的总困难程度用 totalDifficulty 表示,是直到目前区块的困难程度之和。
RPC API 暴露:此漏洞刚开始是通过对 G以太币 和 Parity 推广客户端的攻击发现的 [19]。
引用:
[1] https://www.coindesk.com/understanding-dao-hack-journalists
[2]https://www.freecodecamp.org/news/a-hacker-stole-31m-of-以太币er-how-it-happened-and-what-it-means-for-以太币ereum-9e5dc29e33ce/
[3]https://medium.com/blockcat/on-the-parity-multi-sig-wallet-attack-83fb5e7f4b8c
[4]https://nvd.nist.gov/vuln/detail/CVE-2022-10299
[5]https://medium.com/loom-network/how-to-secure-your-smart-contracts-6-SOLidity-vulnerabilities-and-how-to-avoid-them-part-2-730db0aa4834
[6] https://eprint.iacr.org/2022/1007.pdf
[7]https://www.reddit.com/r/以太币ereum/comments/4ghzhv/governmentals_1100_以太币_jackpot_payout_is_stuck/
[8]https://github.com/KadenZipfel/smart-contract-attack-vectors/blob/master/vulnerabilities/unchecked-call-return-value.md
[9]https://medium.com/hackernoon/hackpedia-16-SOLidity-hacks-vulnerabilities-their-fixes-and-real-world-examples-f3210eba5148
[10]https://medium.com/golem-project/how-to-find-10m-by-just-reading-blockchain-6ae9d39fcd95
[11]https://medium.com/loom-network/how-to-secure-your-smart-contracts-6-SOLidity-vulnerabilities-and-how-to-avoid-them-part-2-730db0aa4834
[12]https://blog.以太币ereum.org/2022/09/22/transaction-spam-attack-next-steps/
[13]https://blog.comae.io/the-280m-以太币ereums-bug-f28e5de43513?gi=3b0603be9186
[14] https://dl.acm.org/doi/10.1145/3149.214121
[15]https://medium.com/coinmonks/how-the-winner-got-fomo3d-prize-a-detailed-explanation-b30a69b7813f
[16] https://dl.acm.org/doi/10.1145/3212998
[17] https://dl.acm.org/doi/10.1145/2810103.2813659
[18]https://ljk.imag.fr/membres/Jean-Guillaume.Dumas/Enseignements/ProjetsCrypto/以太币ereum/236.pdf
[19]https://mp.weixin.qq.com/s/ia9nBhmqVEXiiQdFrjzmyg
[20] https://dl.acm.org/doi/fullHtml/10.1145/3391195