热门搜索:和平精英 原神 街篮2 

您的位置:首页 > > 教程攻略 > web3.0 >重入攻击是什么?一文解读智能合约中的重入攻击

重入攻击是什么?一文解读智能合约中的重入攻击

来源:互联网 更新时间:2026-08-26 21:20

重入攻击:智能合约中最经典的漏洞之一

智能合约的可重入性,是安全领域老生常谈的话题,但也是至今仍在不断“翻车”的雷区。简单来说,攻击者利用合约在执行期间状态不一致的间隙,反复进入合约并执行恶意代码,直到把资金抽干。这种手法听起来简单,实际杀伤力却极大——从2016年的DAO事件到近年DeFi协议频频失守,无一不印证了这一点。

下面,我们就从头到尾把重入攻击拆开揉碎,看看它到底是怎么运作的,又会带来哪些后果,以及开发者该如何防范。

重入攻击是什么?一文解读智能合约中的重入攻击

一、智能合约中的潜在漏洞

智能合约虽然革命性,但并非无懈可击。输入验证不足、业务逻辑设计不当、不安全的外部调用——这些弱点都可能被恶意方利用。其中,重入攻击属于“逻辑漏洞”的一种典型:合约A在完成自身状态更新之前,先对外发起了调用(比如转账),而外部合约B的回调函数恰好能重新进入合约A,在状态还没改完的情况下再次执行同一操作。这种递归调用一旦形成,攻击者就能反复提取资金,造成灾难性后果。

因此,开发者在使用外部合约或数据源时,必须格外谨慎。安全测试、审计流程、以及防御性的编程习惯,都是保护合约免受这类威胁的关键。

二、什么是智能合约中的重入攻击?

重入攻击发生在这样的场景中:合约在完成自己的状态更改之前,调用另一个合约或函数。被调用的合约通过回调重新进入调用合约,再次执行其中部分逻辑,导致不可预见的恶意行为。举个典型例子:合约A调用合约B发送资金,随后才更新自己的余额。合约B的代码里如果包含回调函数,就能在A的余额更新前重新调用A的转账函数。这样一来,攻击者可以在单笔交易中反复取款,直到合约资金耗尽。

最著名的案例是2016年以太坊上的DAO攻击。攻击者利用智能合约代码中的重入缺陷,递归地从DAO中抽取资金,最终导致价值数千万美元的ETH被盗。此后,Uniswap、Lendf.Me、BurgerSwap、SURGEBNB、Cream Finance、Siren Protocol等DeFi协议也先后因类似漏洞蒙受损失,金额从350万美元到2500万美元不等。可以说,重入漏洞是DeFi领域持续存在的威胁。

三、重入攻击如何工作

重入攻击的核心在于:利用智能合约函数的顺序执行和外部调用,形成一个递归循环。攻击者在受害者合约完成状态修改之前,反复执行某个函数,从而实现未经授权的资金提取。

简单来说,攻击者的合约“欺骗”受害合约,在受害合约尚未更新自己的账本前,就回调攻击者的合约。每次回调都会触发一次新的提款操作,直到资金被掏空。

重入攻击流程示意图

上图演示了标准的攻击流程:攻击者调用受害合约的withdraw()函数(该函数在更新余额之前先发送ETH),攻击者的fallback函数被触发,并在其中再次调用withdraw()。由于余额尚未更新,每次调用都符合提款条件,直到资金耗尽。

为了更直观,我们用一个简化案例分步拆解:

具有“变钱”功能的智能合约

假设有一个数字钱&包合约,里边存着用户的余额,并提供了提款功能。通常,提款函数会先检查用户余额是否足够,然后向用户地址转账,最后更新余额。

用户交互与功能执行

用户发起提款请求,填入金额。合约验证余额后,将资金转出。

外部调用

问题出在顺序上:合约在更新用户余额之前,先对外发送了Ether(或代币)。这就给外部合约留下了可乘之机。

递归调用

如果外部合约(攻击者合约)的回调函数里包含对原合约withdraw()的再次调用,就会形成一个递归循环——在余额更新之前,withdraw()可以被反复执行。

利用回退函数

智能合约的fallback函数(当合约收到无数据调用时触发)常被攻击者用来发起递归。通过反复触发fallback,攻击者可以在同一笔交易中多次取款。

反复提款

由于余额延迟更新,攻击者合约可以在同一笔交易中重复调用提款函数,最终提取远超自己份额的资金。受害者合约的用户则遭受严重经济损失。

四、重入攻击的后果

重入攻击最直接的后果就是资金被非法提取。攻击者利用漏洞反复从合约中抽走资金,导致合约余额归零,投资者血本无归。

更深远的影响在于信任崩塌。2016年DAO事件已经证明,一次严重的重入攻击足以动摇整个社区对智能合约和区块链技术的信心。除了财务损失,还可能引发监管介入、法律纠纷,以及项目声誉的长期受损。用户会变得谨慎,不敢再轻易与涉及外部调用的DApp交互,这无疑阻碍了区块链技术的普及。

五、如何减轻重入攻击

防范重入攻击,需要从合约设计、编码实践到审计检验的全流程把控。

首先,优先使用经过安全审计的知名代码库,比如OpenZeppelin。这些库经过了广泛测试和同行评审,能大幅降低引入漏洞的概率。

其次,应用经典的“检查-效果-交互”模式:先验证条件(检查),再更新状态(效果),最后跟外部交互(调用)。确保所有状态修改在外部调用之前完成,从根源上杜绝重入的可能性。

另外,可使用支持重入锁的开发框架(如OpenZeppelin的ReentrancyGuard),通过修饰器为函数加上互斥限制,防止同一函数在未完成前被再次调用。当然,区块链安全仍在演进,开发人员必须持续关注新出现的攻击手法。

六、重入攻击事件分析

回顾历史,重入攻击频发的程度超出想象。以下盘点几个典型案例。

2021年8月17日,BSC上DeFi项目XSURGE遭闪电贷攻击。

事发前一天,XSURGE官方承认SurgeBNB合约存在漏洞,但由于合约已放弃不可更改,无法修补。随后攻击者迅速行动,在SurgeBNB中窃取500万美元。

攻击过程:

(1)攻击者通过闪电贷从PancakeSwap借入10,000 BNB。

(2)用10,000 BNB买入SURGE,再卖出(调用sell函数)。在BNB转账时,攻击合约再次将收到的BNB转回BurgeToken合约,触发购买操作。由于sell函数在状态变量更新前发生了外部调用,导致可重入。

(3)在sell函数中重入purchase函数。此时_totalSupply尚未扣减卖出数量,使攻击者能够买入更多SURGE。

(4)攻击者最终获得约3.9×10^15 BURGE,兑换成22,191 BNB,偿还闪电贷及手续费后获利12,161 BNB。

2022年3月16日,Gnosis链上的借贷协议Hundred Finance与Aga ve遭闪电贷攻击,损失超1100万美元。

攻击过程:

(1)从SushiSwap闪电贷借出钱SDC和wXDAI。

(2)抵押120万USDC,借贷约5999万hUSDC。

(3)超额借贷其他代币,并重复多次。

(4)归还闪电贷,完成攻击。根本原因在于合约存在重入漏洞,导致超额借贷。

2022年3月27日,Revest Finance遭黑客攻击。

攻击者利用Revest合约的逻辑漏洞,盗走近770万ECO、579 LYXe、7.15亿BLOCKS以及35万RENA,价值约200万美元。资金来自Tornado Cash,随后在SushiSwap和Uniswap上兑换成ETH,再通过Tornado Cash转移。

攻击过程:

(1)攻击者通过UniswapV2闪电兑换调用Revest合约中的mintAddressLock函数。

(2)在mintAddressLock函数完成前调用_mint时,攻击者利用ERC1155的onERC1155Received回调重入depositAdditionalToFNFT

(3)由于NFT的nextId在mint函数铸造后才更新,重入时ID仍为1027,且合约未验证下一个ID的Token数量是否为0,攻击者成功铸造了另一个ID为1028的NFT。

2022年7月10日,NFT市场Omni因闪电贷攻击损失1300 ETH(约143万美元)。

攻击过程:

(1)通过Balancer闪电贷借入1000 ETH。

(2)通过flashLoan借入20个DOODLE。

(3)在SushiSwap上用WETH兑换1个DOODLE。

(4)赎回20个NFT(tokenId列表略)。

(5)抵押3个NFT(supplyERC721),铸造nDOODLE。

(6)借贷12.15 WETH。

(7)提取抵押的3个NFT中的2个(tokenId 5251, 4777)。

(8)销毁抵押NFT时铸造的nDOODLE,调用safeTransferFrom将NFT转移到攻击合约,并利用onERC721Received发起重入。

(9)在重入中实现自我清算,将借贷标记为false。

(10)转移剩余NFT时再次重入,抵押全部20个NFT,铸造nDOODLE,借贷81 WETH,最后提取所有NFT。

(11)重复操作,最终获利148.8 ETH。核心原因是safeTransferFrom调用onERC721Received引发的重入漏洞。

从这些案例可以看出,重入漏洞在智能合约中是何等普遍。一边是政策层面推动智能合约与数字软妹币落地(如2022年中国国际金融年度论坛上,央&行数字货币研究所所长穆长春所言),另一边却是频发的合约安全事故。如何在拥抱技术的同时守住安全底线,是每个开发者都需要认真思考的问题。

热门手游

相关攻略

手机号码测吉凶
本站所有软件,都由网友上传,如有侵犯你的版权,请发邮件haolingcc@hotmail.com 联系删除。 版权所有 Copyright@2012-2013 haoling.cc