在上周(2026年2月9日至2月15日),BlockSec 检测并分析了三起攻击事件,总估计损失约为 65.7 万美元。下表总结了这些事件,并在以下子节中提供了详细的分析。
| 日期 | 事件 | 类型 | 估计损失 |
|---|---|---|---|
| 2026/02/10 | 未知事件 | 业务逻辑缺陷 | ~$10K |
| 2026/02/14 | OCA 事件 |
业务逻辑缺陷 | ~$422K |
| 2026/02/14 | SOF 事件 |
业务逻辑缺陷 | ~$225K |
1. 未知事件
简要概述
2026年2月10日,BNB 智能链上的合约 0x560d39 被利用,导致估计损失约为 1 万美元。根本原因在于函数 0xb1a87f2c() 中存在的业务逻辑缺陷,这使得其流动性添加过程容易受到三明治攻击。
背景
在合约 0x560d39 中,函数 0xb1a87f2c() 根据输入参数从用户那里转移相应数量的 USDT。接收到的 USDT 被处理,其中 85% 被分配用于后续的流动性操作。
从这 85% 的部分中,一半通过 PancakeSwap 池兑换成 AFX,获得的 AFX 被转移到合约 0x671ce4。然后,该函数从 0x671ce4 中提取 AFX。
接下来,通过 PancakeSwap V2 Router,剩余的一半 85% USDT 和从 0x671ce4 中提取的 AFX 被用于向 USDT-AFX 交易对添加流动性。任何剩余的 USDT 或 AFX 将退还给用户。
在完成 USDT-AFX 流动性添加后,该函数会从地址 0x146933 提取额外的 AFX。从 0x146933 提取的数量被设定为等于之前从 0x671ce4 中提取的 AFX 数量。然后,该函数根据 PancakeSwap V2 AFX-AHT 池中的当前价格比率计算所需的 AHT 数量,并使用从 0x146933 中提取的 AFX 和计算出的 AHT 来向 AFX-AHT 交易对添加流动性。
漏洞分析
易受攻击的合约是 0x560d39。合约 0x146933 作为 AFX-AHT 流动性添加中使用的 AFX 的资金来源,并最终承担损失。
根本原因在于 0x560d39 中函数 0xb1a87f2c() 的业务逻辑缺陷。在检索通过合约 0x671ce4 兑换获得的 AFX 时,该函数在兑换前后都不会验证 0x671ce4 中 AFX 的余额变化。相反,它会提取 0x671ce4 持有的所有 AFX。
这使得攻击者可以提前向 0x671ce4 捐赠大量 AFX,然后仅用少量 USDT 调用 0xb1a87f2c()。由于从 0x146933 中提取的 AFX 数量被定义为匹配从 0x671ce4 中提取的 AFX,因此夸大了从 0x671ce4 的提取,直接导致 0x146933 在 AFX-AHT 流动性添加中贡献了过多的 AFX。
攻击者可以通过 0x560d39 中的剩余 USDT 和 AFX 退款来收回其捐赠,而 0x146933 则承担了过量流动性提供的成本。
攻击者随后通过三明治攻击 AFX-AHT 流动性添加来获利,在受害者交易之前进行 AFX 到 AHT 的兑换(抢跑),并在交易之后进行 AHT 到 AFX 的兑换(后跑)。
攻击分析
攻击交易 的关键步骤总结如下:
-
步骤 1:攻击者在 PancakeSwap V2 上闪贷了 1,130,500e18 个
AFX代币。 -
步骤 2:攻击者将 511,965e18 个
AFX转移到合约0x671ce4。
-
步骤 3:攻击者使用剩余的
AFX在 PancakeSwap V2 上的AFX-AHT池中兑换了 52,316e18 个AHT。由于AHT是一个手续费转账代币,攻击者最终只收到了 26,158e18 个AHT。
-
步骤 4:攻击者调用合约
0x560d39,并传入参数 100 调用函数0xb1a87f2c()。由于该函数提取了0x671ce4中的所有AFX(包括攻击者捐赠的代币),因此它试图向USDT-AFX和AFX-AHT交易对添加不成比例的大量流动性。任何未能配对的剩余USDT和AFX都被退还给攻击者,使他们能够收回大部分成本。 -
步骤 5:攻击者将 26,158e18 个
AHT兑换成 1,129,417e18 个AFX。
-
步骤 6:攻击者偿还了闪贷,并将剩余的
AFX兑换成USDT,获利约 1 万美元。
结论
此事件是由合约 0x560d39 在通过兑换 USDT 获取 AFX 时,直接从合约 0x671ce4 中提取所有 AFX 造成的,而没有在兑换前后验证合约 0x671ce4 中 AFX 余额的变化。
2. OCA 事件
简要概述
2026年2月14日,BNB 智能链上的一个未知协议遭受了利用,导致损失约 42.2 万美元。根本原因是业务逻辑缺陷:在兑换完成后,该协议会调用 OCA Token 合约中的回收功能,从 DEX 检索代币并将其返回给调用者和其他指定地址。这种单边提取 OCA Token 会人为地减少池子的 OCA 储备,从而膨胀其链上价格,并允许攻击者反复从池子中提取 USDC。
背景
协议合约(0xe0d5ec)公开了一个 sellOCA() 函数(选择器 0x9c1dad28),该函数将用户指定的 OCA 数量兑换成 DEX 上的 USDC。OCA 包含一个通缩的“回收”机制:在兑换完成后,该合约会从池子中提取与刚刚售出的 OCA 相同的数量,并将其重新分配给调用者和其他指定地址。由于在 USDC 已支付的情况下移除了 OCA,池子的 OCA 储备减少,而其 USDC 储备保持较低水平,这人为地推高了 OCA 的链上价格。
漏洞分析
核心漏洞在于 sellOCA() 中兑换后的回收机制,它创建了一个可重复的价格操纵原语。每次调用对 DEX 池的净影响如下:池子在兑换过程中损失 USDC,并且在通缩机制收回代币后也损失 OCA,而调用者获得 USDC 收益并通过重新分配收回 OCA。由于池子的 OCA 储备在没有相应 USDC 流入来平衡交易的情况下减少,每次循环都会人为地膨胀 OCA/USDC 的价格。攻击者可以通过重复此过程来提取 USDC 流动性:购买 OCA,调用 sellOCA() 触发回收,然后以膨胀后的价格出售回收的 OCA,逐步从池子中提取 USDC。
攻击分析
攻击交易 的关键步骤总结如下:
-
步骤 1:闪贷了 8,704,860e18 个
USDC。 -
步骤 2:在 PancakeSwap 上将 8,704,860e18 个
USDC兑换成 940,991e18 个OCA。
-
步骤 3:调用
sellOCA(),使用所有 940,991e18 个OCA。该函数在 DEX 上将OCA兑换成USDC,然后通缩的回收机制从池子中回收了售出的OCA并重新分配——将OCA返回给调用者。结果是,攻击者获得了兑换的USDC收益,同时也收回了自己的OCA代币。池子的OCA储备急剧下降,推高了OCA的价格。
-
步骤 4:在现在膨胀的价格下,将回收的 940,991e18 个
OCA兑换回USDC,并在 PancakeSwap 上重复步骤 2-4,逐步提取池子中的USDC。 -
步骤 5:在最后一次迭代中,攻击者仅用 9,999e18 个
OCA兑换了 433,238e18 个USDC(反映了极度膨胀的OCA价格),然后偿还了闪贷,完成了利用。
结论
此漏洞的根本原因是协议 sellOCA 流中的逻辑缺陷:在用用户提供的 OCA 兑换 USDC 后,该合约通过 OCA 的通缩“回收”机制从 DEX 中回收了几乎所有的 OCA 输入,并将其重新分配给调用者和其他指定地址。这种兑换后的回收操作人为地减少了剩余在流动性池中的 OCA 数量,导致 OCA 的链上价格急剧飙升。通过重复“购买 OCA → 调用 sellOCA 触发回收 → 以膨胀的价格出售 OCA”的循环,攻击者能够以相对较少的 OCA 提取几乎所有的 USDC 流动性。
3. SOF 事件
简要概述
2026年2月14日,BNB 智能链上的 SOF 代币遭受了利用,导致损失约 22.5 万美元。根本原因是 _update() 函数中的业务逻辑缺陷:在卖出操作期间,合约直接将代币从 Uniswap V2 对转移到一个销毁地址并立即调用 sync()。这种操纵池子储备的行为会在同一笔交易中人为地膨胀代币价格。攻击者构建了一个触发此错误卖出逻辑的兑换交易,迫使流动性对销毁其自身的代币并更新储备,从而以人为膨胀的价格提取了池子的 USDT。
背景
SOF 是部署在 BNB 智能链上的 BEP-20 代币,具有自定义的通缩机制和自动费用管理。该代币与 Uniswap V2 兼容的流动性对(特别是与 USDT 的 PancakeSwap)进行交互以促进交易。
对于免除费用的用户,买卖操作是免费的。对于所有其他用户,买入操作受到限制,将回滚。
在卖出操作期间,合约将卖出金额的 90% 从交易对转移到 _destroyAddress,并立即调用 sync() 来更新储备以反映减少的余额。
漏洞分析
根本原因在于 0x1f3863 合约的 _update() 函数中的业务逻辑缺陷。在卖出操作期间(当 to 是 Uniswap Pair 时),该合约执行第 467 行:
/// SOF.sol:462-469
462| } else if (_isPairs[to]) {
463| //sell
464|
465| isSell = true;
466| taxAmount = takeFee(from, amount);
467| super._update(_uniswapV2Pair, _destroyAddress, amount - taxAmount);
468| IUniswapV2Pair(_uniswapV2Pair).sync();
469| }
此逻辑将代币直接从 Uniswap Pair 地址转移到销毁地址(_destroyAddress),从而耗尽了流动性池的代币储备。随后调用 IUniswapV2Pair(_uniswapV2Pair).sync() 立即更新储备,导致代币价格飙升,并允许攻击者提取池子的 USDT。
攻击分析
攻击交易 的关键步骤总结如下:
-
步骤 1:攻击者闪贷了 315,520,309e18 个
USDT用于步骤 2,并将 875e18 个SOF转移到地址0xc4DB5B用于步骤 3。 -
步骤 2:通过
swapTokensForExactTokens()将 313,567,718e18 个USDT兑换成 991,223e18 个SOF。to地址是一个免除费用的地址,满足了SOF合约中的isExcludedFromFees[to]检查,从而跳过了_isPairs[from]检查(否则买入操作将回滚)。这也绕过了_antiFlashloanGuard()检查——合约不会记录此买入操作,允许步骤 3 在不被阻止的情况下进行。至关重要的是,这次大规模买入被设计为使交易对只剩下 787e18 个SOF(以及 313,816,344e18 个USDT),为步骤 3 做好了准备:卖出逻辑中的 90% 销毁将销毁交易对几乎全部剩余的SOF余额。 -
步骤 3:从地址
0xc4DB5B,通过swapExactTokensForTokensSupportingFeeOnTransferTokens()将 875e18 个SOF兑换成USDT。PancakeSwap Router V2 首先执行SOF.transferFrom(),然后处理兑换。在SOF.transferFrom()期间,_update()中的卖出逻辑将 875e18 的 90%(即 787e18)从交易对转移到_destroyAddress——如步骤 2 中设计的那样,这几乎是交易对SOF余额的全部。在这次销毁和sync()之后,交易对持有 313,816,344e18 个USDT和仅 10e9 个SOF。随着SOF价格现在呈天文数字般膨胀,随后的兑换产生了巨额的USDT支付。 -
步骤 4:攻击者偿还了闪贷,并保留了约 22.5 万美元的利润。
结论
SOF 事件凸显了在代币转账逻辑中操纵 AMM 池储备的风险。卖出路径将代币从 Uniswap 对余额中移除并立即调用 sync(),因此当 swapExactTokensForTokensSupportingFeeOnTransferTokens()运行时,转账到交易对会在兑换完成前改变储备,扭曲了定价并实现了提取。
_antiFlashloanGuard() 也未能提供有意义的保护。它只限制同一用户地址的买卖,攻击者通过将买入部分路由到免除费用的接收者来绕过它。
为了缓解类似问题,避免任何转移钩子或 _update() 逻辑,这些逻辑会将代币从交易对地址移动或调用 sync()。如果需要防闪贷保护,可以通过跟踪 tx.origin 和相关地址来实施整个交易的规则,这样攻击者就无法在一笔交易中将买卖分开到不同的接收者。
关于 BlockSec
BlockSec 是一家全栈式区块链安全和加密合规提供商。我们构建产品和服务,帮助客户在协议和平台的整个生命周期内进行代码审计(包括智能合约、区块链和钱包)、实时拦截攻击、分析事件、追踪非法资金,并满足 AML/CFT 的义务。
BlockSec 在享有盛誉的会议上发表了多篇区块链安全论文,报告了多起 DeFi 应用的零日攻击,阻止了多次黑客攻击并挽救了超过 2000 万美元,并保障了数十亿美元的加密货币。
-
官方 Twitter 账号:https://twitter.com/BlockSecTeam
-
🔗 Phalcon 安全应用: 预约演示



