智能合约九大安全漏洞

智能合约部署在区块链上,例如以太坊或其他分布式账本基础设施,侦听来自预言机(Oracle)的加密安全数据源的事件和更新。这些合同通常控制大量高价值数据的流动,例如转移资金、提供服务和解锁受保护的内容,这使它们成为极具吸引力的攻击目标。

在设计和开发智能合约时,安全必须是重中之重。一旦智能合约部署到区块链上,就很难甚至无法修补,必须删除、重新创建和重新部署。此外,一旦智能合约上链,任何人都可以访问智能合约中的漏洞。

在流行的智能合约平台以太坊上部署用Solidity编写的智能合约时,开发团队需要特别注意以下九大安全漏洞(攻击媒介):

一、重入攻击

重入攻击媒介的存在是因为Solidity智能合约必须执行:每一行代码都必须在下一行代码开始之前执行。这意味着当合约对另一个合约进行外部调用时,调用合约的执行将暂停,直到调用返回。这使被调用的合约暂时控制接下来发生的事情,从而创造了无限循环的可能性。

例如,恶意合约可以递归回原始合约以提取资源,而无需等待第一次调用完成,因此在函数完成之前绝不能允许原始合约更新其余额。重入攻击有多种形式,包括单功能、跨功能、交叉收缩和只读重入攻击。漏洞利用列表在GitHub上维护。

修复建议:

当智能合约的代码逻辑有缺陷时,就会出现此漏洞。开发人员需要仔细设计外部调用,并始终检查和更新合约的状态,例如在满足发送资金的请求之前减少以太币余额。添加重入防护,可锁定协定来防止一次执行多个函数。使用各种审计工具,如Slither,Mythril和Securify,检查是否存在不同类型的重入漏洞。

二、预言机操纵

智能合约通过预言机访问和使用来自区块链外部的数据。这使他们能够与链下系统(如股票市场)进行交互。不正确的预言机数据可能会错误地触发智能合约的执行,即所谓的“预言机问题”。许多去中心化金融应用程序已被这种方法利用,攻击者最喜欢的是闪电贷款攻击。闪电贷款本质上是无抵押贷款,只要在同一笔交易中偿还贷款,就可以无限制借钱。攻击者使用这些贷款来扭曲资产价格以产生利润,同时仍然遵守区块链的规则。

修复建议:

使用去中心化的预言机,如Chainlink或Tellor,甚至多个预言机,是确保合约收到准确数据的最简单方法。此类预言机使攻击者干扰数据变得更加困难和昂贵。

三、gasgriefing攻击

要在以太坊区块链平台上执行交易或执行智能合约,用户必须支付gas交易费,后者是为了激励验证者(矿工)投入验证交易所需的资源。gas费用价格由交易时的供应、需求和网络容量决定。

当用户发送执行目标智能合约所需的gas量但不足以执行子调用时,就会发生gasgrief——对其他合约进行的调用。如果合约没有检查执行子调用所需的gas是否可用,则子调用将无法按预期执行。这可能会对应用程序的逻辑产生重大影响。

修复建议:

目前没有有效的技术来预防gasgriefing。开发人员所能做的就是对合约进行编码,设置要发送的gas量,而不是让用户来设置。然而,gas费用的上升可能意味着交易失败。

四、交易订单依赖攻击(抢先)

智能合约从待处理交易提交给网络的那一刻起就是公开可见的。这使区块的矿工能够选择具有最高gas费用的交易。例如,用户可以通过优先费–小费–以激励矿工将他们的交易优先于同一区块中的其他交易。然而,这也使攻击者能够观察机会,他们可以通过提交相同的合同来提前运行有利可图的合同,但gas费用更高,因为此类合同往往要求优先被处理。由于这些攻击必须在几分之一秒内实施,因此它们通常由机器人或矿工自己执行。

修复建议:

这些攻击很难避免。一种选择是只接受gas价格低于预定阈值的交易。或者使用提交和揭示方案,该方案涉及用户首先提交解决方案哈希而不是明文解决方案,以便潜在的领跑者无法查看解决方案,直到为时已晚。各种智能合约审计工具可以检测代码是否引入了前端漏洞。

五、强制馈送攻击

强制馈送攻击利用了这样一个事实,即开发人员无法阻止智能合约接收以太坊的原生加密货币以太币。这使得以太币转移到任何合约中变得容易–强制喂食它们–以改变它持有的以太币的余额,从而操纵任何仅依赖于内部会计预期余额的功能逻辑,例如如果余额增加超过一定水平,则支付奖励。

修复建议:

以这种方式阻止合约余额操纵是不可能的。合约的余额绝不应用作函数中的检查或保护,因为实际的以太币余额可能高于合约内部代码预期的余额。

六、时间戳依赖性

时间戳值由执行智能合约的节点生成。由于以太坊平台的分布式性质,几乎不可能保证每个节点上的时间正确同步。然后,节点可以操纵时间戳值,以针对依赖block.timestamp变量执行时间关键型操作的任何合约进行逻辑攻击。

修复建议:

为避免此漏洞,开发人员不应将block.timestamp函数用作控件或逻辑检查,或用作随机性源。

七、拒绝服务

与任何在线服务一样,智能合约容易受到DoS攻击。通过重载服务(如身份验证),攻击者可以阻止其他合约执行或生成意外的合约还原,例如,返回未使用的gas,并且所有状态都恢复到交易开始执行之前的状态。这可能导致拍卖结果或金融交易中使用的价值纵以利于攻击者。

修复建议:

使攻击者付出高昂的代价是阻止它们的最佳方式。时间锁定谜题和gas费只是增加攻击者成本的一些方法。确保仅调用受信任的合约还可以降低因DoS攻击导致严重问题的可能性。

八、整数下溢和溢出

当算术运算的结果超出固定大小的值范围时,会发生整数下溢和溢出:对于整数类型uint0,则为255到8。大于255的值溢出并重置为0,而小于0的值重置为255。这会导致合约的状态变量和逻辑发生意外更改,并触发无效操作。

修复建议:

从版本0.8.0开始,Solidity编译器不再允许可能导致整数下溢和溢出的代码。检查使用早期版本编译的任何合约以获取涉及算术运算的函数,或使用库(如SafeMath)来检查下溢和溢出问题。

九、信息和功能暴露

任何人都可以访问区块链。机密或敏感信息不应保存到区块链中,除非它被加密。智能合约中的变量和函数也可以被其他智能合约看到和访问,这使得它们有可能被误用或滥用。

修复建议:

开发人员应始终实施适当的访问控制,并使用最小特权原则,通过使用Solidity的变量和函数可见性修饰符来根据需要分配最低级别的可见性,而不是更多。

智能合约漏洞的预防

智能合约代码在部署后很难修补。开发团队从一开始就需要整合正确的安全性,严格测试其逻辑和代码执行,始终遵循智能合约安全最佳实践。除非开发团队中有专门的智能合约安全专家,能对每个功能进行单元测试来审核智能合约代码的逻辑缺陷和其他漏洞,否则请用智能合约的专业审计服务来识别安全问题。

前一篇2023年数据泄漏平均成本高达445万美元
后一篇SSH仍然是最热门的黑客攻击目标