本文介绍了Solidity中的重入攻击,攻击原理是利用智能合约函数在执行过程中,通过外部调用恶意合约,递归调用原合约函数来耗尽资金。文章详细讲解了单函数重入攻击和跨函数重入攻击,并通过DAO、Lendf.me和Cream Finance等案例说明了重入攻击的危害及防范方法,例如CEI模式、重入锁、提取支付和Gas限制。
由 Brady Werkheiser 审核
发布于 2022 年 10 月 4 日,阅读时长 4 分钟
Solidity 中的 重入攻击 会重复地从智能合约中提取资金,并将它们转移到未经授权的合约,直到资金耗尽。当不良行为者发现可利用的智能合约时,攻击发生在区块链的执行周期中。重入攻击已经从 DAO 和区块链协议中清算了数百万美元。
以下文章解释了重入攻击的机制、两种类型的重入攻击,以及 Solidity 开发者 可以采取的预防措施,以保护智能合约免受以太坊和 Solana 区块链上的漏洞攻击。
当智能合约函数通过对有时由未知或可能具有敌意的行为者编写的合约进行外部调用来暂时放弃交易的控制流时,就会发生重入攻击。这允许后面的合约递归地调用回主要的 智能合约函数 以耗尽其资金。
以太坊区块链上智能合约的执行周期会检查余额、发送资金,然后更新余额。当智能合约处于第三方托管状态时,不良行为者可以再次调用以提取资金。该周期重复进行,直到所有资金都被有效耗尽。
重入攻击创建了一个递归过程,该过程在两个智能合约之间转移资金,即易受攻击的合约和恶意合约。 以下是重入攻击的步骤:
不良行为者调用易受攻击的合约“X”,以将资金转移到恶意合约“Y”。
合约 X 确定攻击者是否拥有必要的资金,然后继续将资金转移到合约 Y。
一旦合约 Y 收到资金,它将执行一个 回调 函数,该函数在余额更新之前回调到合约 X。
这个递归过程持续进行,直到所有资金都耗尽并转移。
下图说明了攻击场景:
重入攻击场景 | 图片来源:CryptoMarketPool
有两种类型的重入攻击:单函数重入攻击和跨函数重入攻击。
当易受攻击的函数与攻击者试图递归调用的函数是同一个函数时,就会发生单函数重入攻击。与跨函数重入攻击相比,单函数重入攻击更简单,更容易预防。
只有当易受攻击的函数与另一个对攻击者具有理想效果的函数共享状态时,跨函数重入攻击才是可行的。跨函数攻击更难检测,更难预防。
当一个合约中的状态在完全更新之前在另一个合约中被调用时,就会发生跨合约重入攻击。当多个合约手动共享同一个变量,并且有些合约不安全地更新共享变量时,通常会发生跨合约重入攻击。
以下著名的重入攻击进一步说明了不良行为者如何利用区块链协议中的漏洞:“DAO 黑客事件”、Lendf.me 和 Cream Finance。
以太坊 DAO 因大约 6000 万美元的以太币被黑客攻击。以太坊的 DAO 被设计为一个投资基金,网络成员可以直接投票决定投资决策。
DAO 筹集了大约 1.5 亿美元,但专家和社区参与者对存储资金的智能合约的安全性表示担忧。这些资金被锁定在一个智能合约中,由于源代码中的递归调用错误,该合约容易受到重入攻击。在开发团队解决问题之前,一名黑客执行了一次攻击并耗尽了合约。
2020 年 4 月,一名不良行为者使用重入攻击从 Lendf.me 协议(以太坊网络上用于借贷运营的去中心化金融协议)窃取了 2500 万美元。
该协议的开发者忽略了 ERC-777 代币包含一个回调函数,该函数在发送或接收资金时通知用户。黑客通过将恶意智能合约作为接收者并耗尽 Lendf.me 协议 99.5% 的资金来利用该漏洞。
2021 年 10 月,一名不良行为者通过对该协议的“闪电贷”功能进行重入攻击,窃取了价值超过 1.3 亿美元的 ERC-20 和 CREAM 流动性协议 (LP) 代币。该漏洞的根本原因是 AMP 错误地集成到 CREAM 金融协议中。
开发一个严格的区块链安全框架对于预防和减轻重入攻击造成的潜在损害至关重要。 以下防重入最佳实践将帮助开发者和更广泛的 web3 社区保护他们的资金:检查、效果和交互 (CEI)、重入保护、拉取付款和 gas 限制。
CEI 过程是预防重入的一种基本方法。“检查”指的是条件的真实性,“效果”指的是交互导致的状态修改,“交互”指的是函数或合约之间的交易。
对于开发者来说,将执行效果放在交互之前的潜在安全风险和漏洞是一个重要的考虑因素。
可以将重入保护或互斥锁创建为一个函数或 函数修饰符。在容易受到重入攻击的函数调用周围放置一个布尔锁。这意味着“锁定”的初始状态为假,但是,在易受攻击的函数执行开始之前立即将其设置为真,然后在终止后快速将其设置回假。
通过使用拉取付款方法,可以实现更安全的端到端交易。拉取付款过程要求使用中间托管来发送资金,并避免与潜在的敌对联系人直接联系。
通过经由中间托管发送资金,智能合约的资金将受到重入攻击的保护。如果托管为多个帐户管理资金,则该托管可能会受到重入的影响。应在适当的地方实施 CEI 模式和重入保护。
Gas 限制不是避免攻击者的最佳方法,因为 gas 成本取决于以太坊的操作码,这些操作码可能会发生变化。另一方面,智能合约代码是不可变的。
// 理解 _send_、_transfer_ 和 _call_ 函数之间的区别非常重要
理解 send、transfer 和 call 函数 之间的区别非常重要。Send 和 transfer 实际上是相同的,但是如果交易失败,transfer 将会恢复,而 send 不会。
与 send 和 transfer 不同,call 函数没有 gas 限制,并且会转发其 gas 以执行多合约交易。不幸的是,这也意味着重入攻击是可能的。
以太坊上智能合约的执行周期并非万无一失。不良行为者通过实施 重入攻击 来利用区块链,以从易受攻击的智能合约中转移和耗尽资金。采取预防措施将确保 Soldiity 开发者更安全的执行周期并保护他们的区块链协议。
要了解有关 Solidity 智能合约开发最佳实践的信息,请加入 Alchemy 的免费 7 周以太坊开发者训练营。最初是一个价值 3,000 美元的认证课程,Alchemy University 的训练营是 免费学习 Solidity 的首选之地。
如果开发者通常是开发新手,那么在开始以太坊训练营之前,Alchemy 的 3 周 JavaScript 速成课程 是一个很好的先决条件。
Supercharged | Alchemy | Substack
注册 Alchemy University 并开始免费学习 Solidity 开发 立即注册
📚 目录
分享:
\
\
学习 Solidity\
\
Solidity 中的 selfdestruct 是什么?\
\
它是什么、如何工作以及如何入门
\
\
学习 Solidity\
\
学习 Solidity 开发的 7 门最佳课程 (2025)\
\
探索学习 Solidity 开发的最佳免费和付费课程
\
\
学习 Solidity\
\
Solidity 数组是什么?\
\
你的 Solidity 数组入门指南——函数、声明和故障排除
Alchemy 将最强大的 web3 开发者产品和工具与资源、社区和传奇支持相结合。
- 原文链接: alchemy.com/overviews/re...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!