重入攻击: 加密货币领域的重入攻击是什么?重入攻击是一种智能合约漏洞利用:外部合约会在第一次函数调用尚未完成前,回调易受攻击的合约。在加密货币领域,这类攻击通常针对持有资金、记录余额、处理提现、计算奖励、管理金库份额或与其他合约交互的智能合约。核心问题在于,易受攻击的合约尚未完成内部状态更新,就将控制权交给了另一个合约。如果攻击者能在状态尚未完成更新时重新进入合约,就可能重复执行本应只能执行一次的操作。一种常重入攻击: 加密货币领域的重入攻击是什么?重入攻击是一种智能合约漏洞利用:外部合约会在第一次函数调用尚未完成前,回调易受攻击的合约。在加密货币领域,这类攻击通常针对持有资金、记录余额、处理提现、计算奖励、管理金库份额或与其他合约交互的智能合约。核心问题在于,易受攻击的合约尚未完成内部状态更新,就将控制权交给了另一个合约。如果攻击者能在状态尚未完成更新时重新进入合约,就可能重复执行本应只能执行一次的操作。一种常
加密货币领域的重入攻击是什么?
重入攻击是一种智能合约漏洞利用:外部合约会在第一次函数调用尚未完成前,回调易受攻击的合约。在加密货币领域,这类攻击通常针对持有资金、记录余额、处理提现、计算奖励、管理金库份额或与其他合约交互的智能合约。核心问题在于,易受攻击的合约尚未完成内部状态更新,就将控制权交给了另一个合约。如果攻击者能在状态尚未完成更新时重新进入合约,就可能重复执行本应只能执行一次的操作。一种常见情况是,提现函数先向用户发送加密资产,然后才扣减用户记录的余额。如果接收方是恶意合约,它可以利用回退函数或回调逻辑,在余额更新前再次调用提现函数。这可能让攻击者提取超出其应得数量的资产。OWASP 2026 年智能合约十大风险中的重入攻击页面将重入定义为:合约进行外部调用后,被调用方在合约状态完全更新前回调原合约的情况。
重入是最著名的智能合约漏洞之一,因为它直接攻击链上记账的信任模型。它在去中心化金融(DeFi)领域尤其危险,因为智能合约往往管理大型流动性池,并依赖其他合约进行兑换、抵押、奖励分发或获取价格数据。重入攻击的运作方式
当易受攻击的智能合约向另一个合约或地址进行外部调用时,重入攻击就可能开始。这种外部调用可能会发送原生加密货币、转移代币、调用钩子、请求回调、执行策略或与其他协议交互。易受攻击的合约发起调用时,会暂时给予接收合约执行自身代码的机会。如果接收合约由攻击者控制,攻击者就可以趁机回调易受攻击的合约。由于合约尚未更新余额、债务、份额、奖励指数或锁定标志,易受攻击的合约可能仍保留旧状态值。攻击者可以利用这些旧值重复提现、重复领取奖励、超额借款或操纵计算结果。攻击会持续下去,直至易受攻击的合约资金耗尽、交易 Gas 耗尽,或防护机制阻止重复调用。Solidity 关于外部调用的文档警告,与另一个合约交互会将控制权交给该合约;在第一次调用返回前,被调用合约可能回调原合约。
这一警告是防范重入的基础。任何外部调用都应被视为可能破坏合约假设的节点。简单的重入示例
假设某借贷合约会记录每个用户的存款余额。用户向合约存入 10 ETH。合约记录该用户的余额为 10 ETH。之后,用户调用提现函数,取回这 10 ETH。安全的合约会先将用户余额减至零,然后再发送 ETH。易受攻击的合约则会先发送 ETH,之后才更新余额。如果用户实际使用的是恶意合约,那么发送 ETH 时就会触发其接收函数。该接收函数可以立即再次调用提现函数,而易受攻击的合约仍认为用户余额为 10 ETH。同一笔提现可能在一笔交易中反复执行。因此,智能合约逻辑的执行顺序至关重要。在传统软件中,轻微的顺序错误可能只会导致普通的记账错误。但在持有加密资产的智能合约中,同样的顺序错误可能直接导致资产被盗。重入攻击的危险性
重入攻击很危险,因为智能合约往往控制着遭遇漏洞利用后难以追回的资产。公有区块链旨在执行有效交易并保留交易历史。如果恶意交易符合区块链规则,却利用了合约漏洞,通常很难撤销损失。Ethereum.org 智能合约安全指南说明,已部署的智能合约代码通常难以更改;由于区块链具有不可篡改性,被盗资产也难以追回。
因此,预防远比事后补救重要。重入漏洞可能导致流动性池、金库、跨链桥、质押系统、NFT 市场、奖励合约和借贷协议中的资产被耗尽。即使被盗金额之后追回,用户信任也可能受损。在加密货币领域,智能合约风险不仅是开发者的问题。它也可能同时演变为用户问题、流动性问题、治理问题和声誉问题。经典重入攻击
经典重入攻击是指攻击者重新进入发起外部调用的同一函数。最常见的例子是存在漏洞的提现函数。该函数会检查用户是否有余额,向用户发送资金,然后才更新余额。攻击者的合约接收资金后,会在余额扣减前再次调用同一提现函数。这样一来,同一笔记录余额就能被重复使用。经典重入攻击虽然容易理解,但仍然很危险,因为许多开发者依旧会过早执行外部调用逻辑。现代合约的记账逻辑往往比简单的存款和提现映射复杂,这也增加了风险。存在漏洞的函数可能涉及份额、债务仓位、奖励乘数、金库资产、流动性代币或费用记账。即使模式看起来与经典示例不同,核心问题仍可能存在。跨函数重入
跨函数重入是指攻击者重新进入同一合约中的另一个函数。这比经典重入更隐蔽,因为单独审查被攻击的函数时,它看起来可能没有问题。例如,某个函数启动提现流程并进行外部调用。在外部调用期间,攻击者可能调用另一个依赖相同余额、份额或权限状态的函数。如果第一个函数尚未完成状态更新,第二个函数可能读取到过时信息。攻击者因此可能在第一个操作完成前领取奖励、转移份额、借入资产或更改仓位。跨函数重入说明,开发者必须考虑整个合约的不变量,而不能只保护一个显而易见的提现函数。合约不变量是指每次有效操作前后都应保持成立的规则。如果外部调用能暂时破坏不变量,其他函数也可能成为攻击路径。跨合约重入
跨合约重入是指回调路径经过多个合约。在 DeFi 系统中,金库、策略、路由器、代币合约、预言机读取器、质押模块和奖励分发器彼此交互时,就可能发生这种情况。金库可能调用某个策略。该策略可能调用代币或另一个协议。被调用的合约可能触发回调,进而重新进入金库,或调用金库所依赖的相关合约。存在漏洞的状态可能不在发起首次外部调用的同一个合约中。Solidity 安全注意事项指出,重入不只由 Ether 转账引起,还必须考虑多合约场景。
这一点很重要,因为现代加密应用具有很强的可组合性。可组合性让协议能够相互连接并在彼此基础上构建,但也会增加出现意外回调的路径。只读重入
只读重入是指在状态转换尚未完成时,视图函数或读取函数返回了误导性信息。乍看之下,这似乎无害,因为视图函数不会直接修改状态。但是,其他合约可能使用视图函数计算价格、份额、抵押品价值、汇率或奖励金额。如果某个合约处于中间状态时发生回调,视图函数可能返回不应被信任的临时值。攻击者可能会在依赖该值的另一个合约中利用这一临时值。这可能造成类似预言机操纵的行为或记账错误,而无需通过普通提现函数直接掏空第一个合约。只读重入提醒我们,安全性不只取决于函数是否写入存储。还要考虑其他合约能否观察到未完成的状态,并据此作出金融决策。基于钩子的重入
基于钩子的重入是指代币标准或协议接口在转账或操作期间,主动调用接收方逻辑。某些代币和 NFT 标准包含接收方钩子,使合约在收到资产时能够作出响应。闪电贷系统也会使用回调,让借款方在同一笔交易中使用借入的流动性并完成偿还。这些钩子很有用,但也会带来回调机会。如果合约假定代币转账只是简单操作,不会执行外部代码,这种假设可能并不成立。根据代币标准和实现方式,转账可能触发接收方逻辑、操作员钩子或其他合约行为。开发者应检查每次外部代币交互,并将其视为潜在的重入点。对于支持多种代币、多个金库资产或多种外部集成的合约,这一点尤为重要。重入攻击的常见目标
提现函数是最常见的重入攻击目标,因为它们通常会将资金转出合约。金库的存款和提现函数也是常见目标,因为它们会更新份额余额和资产记账。借贷协议可能成为目标,因为它们会记录抵押品、债务、利息、强平阈值和借款余额。质押合约可能成为目标,因为它们要计算随时间累积的奖励,并可能在领取奖励时转移奖励代币。NFT 市场可能成为目标,因为购买和付款可能触发代币接收钩子或外部版税逻辑。跨链桥可能成为目标,因为它们要管理跨链消息、资产锁定和释放逻辑。治理执行合约可能成为目标,因为它们在执行提案时会调用外部合约。闪电贷接收方和提供方也可能成为目标,因为其设计依赖回调。任何在完成内部记账前就发送价值或调用不可信代码的智能合约,都应视为可能遭受重入攻击的目标。检查-生效-交互模式
检查-生效-交互模式(Checks-Effects-Interactions)是防范重入攻击最重要的方法之一。检查是指合约首先确认用户是否有权执行操作。生效是指合约先更新自身内部状态,再进行任何外部调用。交互是指合约完成检查和状态更新后才进行外部调用。对于提现函数,合约应先检查用户余额、扣减余额,然后再发送资金。这样,即使接收方尝试重新进入合约,合约中的余额也已经更新。Solidity 关于检查-生效-交互模式的文档将其描述为一种常见的重入攻击防护方法。
这种模式简单明了,但对于与不可信外部代码交互的合约而言并非可有可无。只要函数会更改状态并调用合约外部代码,开发者就应养成默认采用该模式的习惯。重入防护锁
重入防护锁是一种锁定机制,可防止受保护函数在首次调用完成前再次进入。在 Solidity 合约中,通常使用一个状态变量来标记函数正在执行。如果重入调用尝试进入同一受保护路径,防护锁就会拒绝该调用。OpenZeppelin Contracts 5.x 的 ReentrancyGuard 文档介绍,ReentrancyGuard 是一个提供 nonReentrant 修饰符、用于防止嵌套重入调用的模块。
重入防护锁很有用,因为它能为高风险函数增加一道明确的安全保障。不过,防护锁不能取代正确的记账逻辑。开发者仍应采用检查-生效-交互模式,并审查所有外部调用。OpenZeppelin 还指出,由于只有一个 nonReentrant 防护锁,被标记为 nonReentrant 的函数不能直接相互调用。一种常见的解决方法是将内部逻辑设为私有函数,并通过独立的外部入口调用,同时使用 nonReentrant 保护。瞬态存储与重入锁
瞬态存储是 EVM 的一项较新功能,可用于存放仅在一笔交易期间有效的临时值。它可用于重入锁,因为函数调用结束后,锁不一定需要保留在永久存储中。OpenZeppelin ReentrancyGuardTransient 文档介绍了一种使用瞬态存储实现的 ReentrancyGuard 版本,适用于支持 EIP-1153 的链。
Solidity 瞬态存储文档指出,使用瞬态存储实现会在调用帧结束时清除的重入锁是安全的。
这并不意味着所有合约都应自动使用瞬态存储。开发者必须确认目标链支持所需功能,并确保锁能正确清除。管理不当的锁可能破坏可组合性,或使合约难以用于复杂交易。最佳选择取决于目标区块链、编译器版本、库版本、升级模式和审计要求。为什么 transfer 和 send 并非全面防护手段
早期 Solidity 指南常将限制 Gas 的转账视为实用的重入缓解方法。现代指引更加谨慎,因为 Gas 成本和 EVM 行为可能随时间变化。Solidity 地址成员文档警告,send 和 transfer 已弃用,并建议使用其他方式防范重入。
这一点很重要,因为仅依赖 Gas 限额可能会带来虚假的安全感。合约应依靠正确的状态逻辑确保安全,而不是假设接收方没有足够的 Gas 执行危险操作。更稳妥的做法是在外部调用前更新状态,在适当情况下使用重入防护锁,检查返回值,并谨慎设计提现流程。开发者还应审查仍把 transfer 或 send 作为主要重入防护手段的旧代码。随着协议规则、Gas 成本和常见攻击技术的发展,加密货币安全实践也在不断变化。将付款提取作为防护措施
提取式付款模式允许收款方自行提取资金,而不是由合约在其他操作期间主动推送资金。这种做法可以降低风险,因为合约可以记录应付款项,再由收款方在单独步骤中领取。例如,市场可以记录卖家的所得,而不是在买家购买交易中直接向卖家发送资金。之后,卖家再调用提现函数领取资金。这种模式可以限制恶意收款方拒绝付款或在支付过程中尝试重入所造成的损害。OpenZeppelin 安全工具文档指出,PullPayment 模式有助于避免重入攻击。
提取式付款并非适用于所有设计,因为它可能增加用户操作步骤。不过,如果许多用户或合约需要从同一系统收款,这种模式会非常有用。紧急暂停控制
紧急暂停控制允许获授权账户或治理系统在发生事件时暂停敏感功能。如果发现可疑行为或潜在的重入漏洞利用,这有助于限制损失。暂停功能可能会暂时停止提现、存款、领取奖励、新增贷款或其他高风险操作,让团队进行调查。OpenZeppelin 将 Pausable 列为常见的紧急响应机制,可在等待整改期间暂停相关功能。暂停系统应谨慎设计,因为它会带来治理和中心化方面的取舍。如果暂停权限过大,用户可能担心审查或滥用。如果暂停权限过弱或响应太慢,则可能无法在攻击进行期间发挥作用。对于高价值加密协议,紧急响应计划应从一开始就纳入安全设计。开发者如何识别重入风险
开发者可以通过审查合约中的每次外部调用来识别重入风险。外部调用包括原生币转账、代币转账、低级调用、接口调用、闪电贷回调、NFT 接收方钩子以及对协议模块的调用。针对每次外部调用,开发者都应确认内部状态是否已完成更新。开发者还应确认外部调用期间能否调用其他函数,并读取过时状态。开发者应检查多个合约是否共享可能被回调破坏的假设。开发者应测试恶意接收方合约,确认其会尝试回调所有公开函数和外部函数。开发者应结合使用静态分析、模糊测试、单元测试、不变量测试和人工审查。Solidity SMTChecker 文档将重入属性列为可针对外部调用未知代码的行为进行分析的一类情况。
没有任何单一工具能够保证合约安全。将自动化工具与经验丰富的安全审查相结合,才能更有效地检测重入风险。用户如何理解重入风险
大多数用户无法在使用智能合约前对其进行完整审计。不过,用户仍可留意安全实践是否完善,以降低风险。协议应清晰说明审计情况、漏洞赏金计划、紧急控制、升级权限和风险披露。对于持有大量资产却缺少公开审查记录的新合约,用户应保持谨慎。如果协议提供异常高的收益,却未说明收益来源和智能合约风险,用户也应谨慎对待。即使用户界面设计精良、看起来很专业,也仍可能存在重入风险。界面良好并不能证明底层合约逻辑安全。用户不应向未经审计或仍处于实验阶段的合约存入超出自身承受能力的资产。用户还应了解,审计可以降低风险,但无法彻底消除风险。重入攻击与 DeFi 可组合性
DeFi 可组合性是指智能合约能够像金融积木一样相互连接。这是加密货币领域最强大的特性之一,因为它允许钱包、金库、借贷市场、兑换、衍生品、质押系统和治理工具相互交互。不过,可组合性也会增加重入风险,因为一笔交易可能经过多个合约。一个合约中看似安全的操作,可能会在另一个合约中触发复杂行为。回调可能到达第三个合约,并更改第一个合约所依赖的值。价格、份额价值或余额可能在临时状态下被读取,而该状态本不应被外部观察。因此,现代重入分析必须覆盖完整的交互路径。开发者不应把每个合约都当作独立系统来审查。开发者应检查合约与路由器、代币、金库、闪电贷和外部策略组合时的行为。重入攻击与闪电贷
闪电贷可以让重入攻击变得更具威胁性,因为攻击者能够在一笔交易中获得大量临时流动性。闪电贷本身并不是重入攻击。它可以用于合法的套利、再融资、强制平仓和提高资本效率的操作。但是,如果攻击者能在一笔交易中操纵存在漏洞的合约,闪电贷可能提供足够的资金,使攻击获利。闪电贷回调系统也需要谨慎设计,因为基于回调的系统会主动将控制权交给另一个合约。除非有充分理由,否则开发者应将每个回调都视为不可信的外部调用。开发者应尽可能在回调前更新状态,并在回调返回后验证最终还款、余额和不变量。集成闪电贷时,应使用恶意借款方合约进行测试,而不只是测试正常借款示例。重入攻击与可升级合约
使用重入防护机制时,可升级合约需要特别谨慎。可升级代理会将面向用户的存储与实现逻辑分开。如果重入防护锁使用存储,开发者必须确保存储布局正确,并且在升级后保持兼容。错误更改存储布局可能会破坏防护锁或损坏重要状态变量。构建可升级合约时,开发者应使用兼容可升级模式的库。开发者还应针对既有合约状态测试升级,而不只是测试全新部署。合约在第一个版本中可能安全,但后续升级若改变调用顺序或新增外部集成,就可能引入漏洞。升级审查应针对每个新增外部调用进行重入分析。如果协议持有大量资产,执行升级的治理或管理系统也应设置延迟、审查和紧急控制。预防重入攻击的最佳实践
在进行外部调用前更新内部状态。提现、领取奖励、转账、兑换和记账变更应采用检查-生效-交互模式。为高风险的外部入口函数应用重入防护锁。不要假设代币转账总是简单操作,因为一些代币标准和实现可能触发钩子或回调。不要只依靠 transfer 或 send 的 Gas 限制防范重入。如果直接付款会带来不必要的风险,可使用提取式付款模式。不仅要审查经典的同函数重入,还要检查跨函数和跨合约重入。使用恶意接收方合约进行测试,确认其会尝试在每次外部调用期间重入。通过不变量测试,确认复杂交互过程中总余额、份额、债务和储备仍然正确。对于高价值系统,应制定紧急暂停和事件响应计划。在部署持有用户资金的合约前,应进行独立安全审查。保持依赖项更新,并在升级主要版本前查看库的迁移说明。开发者常见错误
一种常见错误是在发送资金后才更新余额。另一种常见错误是只保护提现函数,却让相关函数暴露于跨函数重入风险之下。另一种常见错误是认为代币转账不会执行外部代码。另一种常见错误是在一个合约中使用重入防护锁,却忽视共享记账假设的相关合约调用。另一种常见错误是依赖旧有的 transfer 和 send 假设,而不是正确设计状态逻辑。另一种常见错误是在升级时新增外部集成,却没有重新检查完整调用路径。另一种常见错误是将视图函数视为无害,即使其他合约会在复杂交易期间依赖其返回值。另一种常见错误是忘记恶意合约可以刻意采取不同于普通用户的行为。安全测试应假设存在恶意行为,而不能只测试用户界面的正常用法。常见问题
重入攻击是什么意思?
重入攻击是指恶意合约在第一次函数调用完成、状态尚未安全更新前,回调存在漏洞的智能合约。重入攻击为何在加密货币领域很危险?
重入攻击可能让攻击者在一笔交易中掏空资金、重复领取奖励、操纵记账或破坏合约假设,因此十分危险。重入攻击只与 ETH 转账有关吗?
不是。Solidity 文档警告,重入并非只与 Ether 转账有关,因为任何外部合约调用都可能产生回调风险。最广为人知的重入防护方法是什么?
检查-生效-交互模式是最广为人知的防护方法之一,因为它会在外部调用前更新合约状态。什么是 ReentrancyGuard?
ReentrancyGuard 是一种智能合约工具,提供 nonReentrant 修饰符,以防止受保护函数发生嵌套调用。ReentrancyGuard 能防止所有重入漏洞吗?
不能。ReentrancyGuard 有助于保护特定入口函数,但开发者仍需确保记账正确、调用顺序安全,并审查跨合约交互。什么是跨函数重入?
跨函数重入是指第一个函数尚未执行完成时,攻击者重新进入同一合约中的另一个函数。什么是只读重入?
只读重入是指操作尚未完成时,视图函数返回误导性的临时状态值,而另一个合约依赖该值。代币转账会导致重入吗?
会。一些代币标准和代币实现可能触发钩子或回调,因此应将代币转账视为潜在的外部调用进行审查。用户是否应该因为重入风险而避开所有智能合约?
不必。用户无需避开所有智能合约,但应优先选择具备完善审计、清晰文档、主动监控和负责任风险控制的协议。结论
重入攻击是一种利用外部调用期间未完成状态的智能合约漏洞利用方式。攻击者会在第一次调用完成前重新进入存在漏洞的合约,并利用过时的记账信息获取超出允许范围的价值。经典示例是重复提现,但现代重入攻击还可能涉及跨函数调用、跨合约流程、只读状态、代币钩子、闪电贷回调和 DeFi 可组合性。最重要的经验是,应将每次外部调用都视为可能把控制权交给不可信代码。开发者可以通过采用检查-生效-交互模式、使用重入防护锁、避免不安全的付款模式、测试恶意回调并审查完整合约交互路径来降低重入风险。用户可以选择重视智能合约安全的协议,并避免向未经审计且持有大量资产的系统存入资金,从而降低风险敞口。重入仍是加密货币安全领域的重要概念,因为一次小小的逻辑顺序错误就可能演变为严重的金融漏洞利用。了解重入有助于开发者构建更安全的合约,也能帮助用户理解智能合约审计、安全模式和风险控制为何重要。您可能也喜欢
反恐融资(CTF)
反恐怖主义融资(CTF)是指旨在发现、预防和打击恐怖主义活动资金支持的法律、法规和活动。这包括监控和监管资金流动、在金融机构内部实施合规计划,以及执行旨在遏制恐怖主义融资的国际制裁和法规。 反恐融资在各领域的重要性 反恐融资在包括银行业、科技和国际贸易在内的各个领域都至关重要。在金融领域,强而有力的反恐融资措施可确保银行和其他金融机构不会被恐怖组织利用为其活动提供资金。这不仅有助于维护金融体系的完
2025/12/23 18:42
框架
在专业情境中,「框架」指的是一套结构化的指南、工具或实践,旨在支援专案、应用程式或系统的开发和实施。它提供了一种标准化的方法来解决复杂问题或实现特定目标,通常包含可根据具体需求进行调整和扩展的预先建置元件。 框架的关键特征 框架在软体开发、专案管理和数位行销等各个领域都至关重要。例如,在软体开发中,Angular、React 和 Django 等框架提供了开发人员用来高效建立高品质应用程式的程式库
2025/12/23 18:42
波动性爆发
「波动性爆发」是指金融市场、资产或指数的波动性突然显著增加,通常由不可预见的事件或市场情绪变化所驱动。这种突如其来的增加会导致价格大幅波动和交易量激增,从而影响投资者和交易者的风险和机会。 了解波动性爆发 波动性是衡量特定证券或市场指数收益分散程度的统计指标,显示资产价格在特定期间内的波动幅度。当这种波动超出正常水平时,就会发生波动性爆发,这通常是对意外新闻或经济事件的反应。这些事件可能包括地缘政
2025/12/23 18:42
热门
目前热门备受市场关注的加密货币
最高成交量
按交易量计算交易量最大的加密货币

