Back to Blog

Web3 每週安全事件匯總 | 2026 年 2 月 9 日 – 2 月 15 日

Code Auditing
February 18, 2026
12 min read

在過去的一週(2026年2月9日至2026年2月15日),BlockSec 偵測並分析了三起攻擊事件,總估計損失約為 $657K。下表總結了這些事件,詳細分析將在後續小節中提供。

日期 事件 類型 估計損失
2026/02/10 未知事件 業務邏輯缺陷 ~$10K
2026/02/14 OCA 事件 業務邏輯缺陷 ~$422K
2026/02/14 SOF 事件 業務邏輯缺陷 ~$225K

1. 未知事件

簡要總結

2026年2月10日,BNB Smart Chain 上的合約 0x560d39 遭到攻擊,導致估計約 $10K 的損失。根本原因是函數 0xb1a87f2c() 中的業務邏輯缺陷,導致其添加流動性的過程易受夾心攻擊(Sandwich Attack)。

背景

在合約 0x560d39 中,函數 0xb1a87f2c() 根據輸入參數從用戶那裡轉移相應數量的 USDT。接收到的 USDT 經過處理,其中 85% 的總額會被分配用於後續的流動性操作。

在這 85% 的份額中,一半通過 PancakeSwap 資金池換成 AFX,並將獲得的 AFX 轉移至合約 0x671ce4。隨後該函數從 0x671ce4 提取 AFX

接下來,通過 PancakeSwap V2 路由器,將剩餘的一半 USDT 和從 0x671ce4 提取出的 AFX 用於向 USDT-AFX 交易對添加流動性。任何剩餘的 USDTAFX 都會退還給用戶。

在完成 USDT-AFX 流動性添加後,該函數會從地址 0x146933 檢索額外的 AFX 代幣。從 0x146933 提取的 AFX 數量設定為與之前從 0x671ce4 提取的數量相匹配。接著,該函數根據 PancakeSwap V2 AFX-AHT 流動性池中的當前價格比率計算所需的 AHT 數量,然後提供從 0x146933 獲得的 AFX 以及相應數量的 AHT(同樣來自 0x146933)來為 AFX-AHT 交易對添加流動性。

漏洞分析

受漏洞影響的合約是 0x560d39。合約 0x146933 作為 AFX-AHT 流動性添加中使用的 AFX 的資金來源,並最終承擔了損失。

根本原因在於 0x560d39 中函數 0xb1a87f2c() 的業務邏輯漏洞。在檢索通過合約 0x671ce4 兌換 USDT 而獲得的 AFX 時,該函數未驗證 0x671ce4 在兌換前後的 AFX 餘額變化,而是直接提取了 0x671ce4 持有的所有 AFX

這允許攻擊者提前向 0x671ce4 捐贈大量 AFX,然後僅使用少量的 USDT 調用 0xb1a87f2c()。由於從 0x146933 中提取的 AFX 數量定義為與從 0x671ce4 中提取的 AFX 相匹配,因此增加從 0x671ce4 的提取量直接迫使 0x146933AFX-AHT 流動性添加貢獻了過多數量的 AFX

攻擊者可以通過 0x560d39 退還剩餘的 USDTAFX 來收回他們的捐贈,而 0x146933 則承擔了超額流動性供應的成本。

隨後,攻擊者通過夾擊 AFX-AHT 流動性添加來獲利,即在受害者交易前後分別進行 AFXAHT 的兌換(前置交易)和 AHTAFX 的兌換(後置交易)。

攻擊分析

攻擊交易 的關鍵步驟總結如下:

  • 步驟 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,執行參數設置為 1000xb1a87f2c() 函數。由於該函數提取了 0x671ce4 中的所有 AFX(包括攻擊者捐贈的代幣),導致其試圖為 USDT-AFXAFX-AHT 交易對添加不成比例的超額流動性。任何無法配對的殘餘 USDTAFX 都會退還給攻擊者,使其能收回大部分成本。

  • 步驟 5:攻擊者將 26,158e18 AHT 兌換為 1,129,417e18 AFX

  • 步驟 6:攻擊者償還閃電貸並將剩餘的 AFX 兌換為 USDT,獲利約 $10K。

結論

此事件是由於合約 0x560d39 在檢索通過兌換 USDT 獲得的 AFX 時,直接從合約 0x671ce4 提取了所有 AFX,且未驗證 0x671ce4 在兌換前後的餘額變化所導致的。


2. OCA 事件

簡要總結

2026年2月14日,BNB Smart Chain 上的一個未知協議遭到攻擊,導致約 $422K 的損失。根本原因是業務邏輯缺陷:在兌換完成後,協議會調用 OCA 代幣合約中的回收函數,從去中心化交易所(DEX)檢索代幣並將其返回給調用者和其他指定地址。這種 OCA 代幣的單向提取人為地減少了資金池中的 OCA儲備,抬高了其鏈上價格,從而允許攻擊者反覆耗盡資金池中的 USDC

背景

該協議合約 (0xe0d5ec) 暴露了一個 sellOCA() 函數(選取器 0x9c1dad28),用於在 DEX 上將用戶指定數量的 OCA 賣出換取 USDCOCA 包含了一種通縮「回收」機制:在兌換完成後,該合約會將剛賣出的等量 OCA 從池中拉回,並重新分配給調用者和其他指定地址。由於當 USDC 已經支付出去後 OCA 才被移出池子,此舉減少了池內的 OCA 儲備,而其 USDC 儲備保持較低水平,從而人為推高了 OCA 的鏈上價格。

漏洞分析

其核心漏洞在於 sellOCA() 中的兌換後「回籠」機制創造了一個可重複的價格操縱原語。每次調用對 DEX 資金池的淨影響如下:兌換期間池內的 USDC 減少,當通縮機制從池中收回代幣時 OCA 也減少,而調用者在收到 USDC 收益的同時,還通過重新分配機制收回了 OCA。由於池中的 OCA 儲備在沒有對應的 USDC 流入來平衡交易的情況下被減少,每個週期都會人為地抬高 DEX 上 OCA/USDC 的價格。攻擊者可以通過買入 OCA、調用 sellOCA() 觸發回籠,然後以抬高的價格賣出回籠的 OCA 來重複此過程,從而逐步耗盡資金池內的所有 USDC 流動性。

攻擊分析

攻擊交易 的關鍵步驟總結如下:

  • 步驟 1:閃電貸了 8,704,860e18 USDC

  • 步驟 2:在 PancakeSwap 上將 8,704,860e18 USDC 兌換為 940,991e18 OCA

  • 步驟 3:使用全部 940,991e18 OCA 調用 sellOCA()。該函數在 DEX 上將 OCA 兌換為 USDC,隨後通縮回收機制從資金池中收回了賣出的 OCA 並將其重新分配——將 OCA 返還給調用者。因此,攻擊者在收到兌換收益 USDC 的同時,還收回了他們的 OCA 代幣。資金池中的 OCA 儲備大幅下降,推高了 OCA 的價格。

  • 步驟 4:將收回的 940,991e18 OCA 以此刻膨脹後的價格在 PancakeSwap 上賣回 USDC,並重複步驟 2–4 以逐步耗盡資金池。

  • 步驟 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 Smart Chain 上的 SOF 代幣遭到攻擊,損失約 $225K。原因是其 _update() 邏輯和費用豁免系統中存在錯誤的白名單機制。漏洞允許攻擊者使用費用豁免地址繞過購買限制,隨後觸發了「銷毀後賣出」(burn-on-sell)機制,從而操縱了 Uniswap V2 (PancakeSwap) 的資金池儲備。通過迫使資金池將其自身的代幣轉移到一個銷毀地址,並立即調用 sync(),攻擊者人為地抬高了代幣價格。這使得攻擊者能夠通過以操縱後的匯率兌換少量 SOF 來耗盡池中的 USDT。漏洞利用還因不充分的閃電貸保護機制而變得容易,該機制未能追蹤 tx.origin,允許攻擊的買入和賣出階段在同一筆交易中使用多個地址完成。

背景

SOF 是一個部署在 BNB Smart Chain 上的 BEP-20 代幣,設計有自定義的通縮機制和自動化費用管理。該代幣與一個 Uniswap V2 兼容的流動性對(特別是與 USDT 組成的 PancakeSwap 池)互動以促進交易。

對於費用豁免用戶,買入和賣出操作免費。對於所有其他用戶,買入操作受到限制,否則將發生回滾。

在賣出操作期間,合約直接將賣出金額的 90% 從資金對中轉移到 _destroyAddress,並調用 sync() 以立即更新儲備金以反映餘額減少。

漏洞分析

根本原因源於 0x1f3863 合約在第 438 行 _update() 函數中的白名單機制漏洞。如果地址 to 在白名單中,任何 from 地址都可以處理買入操作。

 /// SOF.sol:433-480
433|      function _update(
434|          address from,
435|          address to,
436|          uint256 amount
437|      ) internal override {
438|          if (isExcludedFromFees[to] || isExcludedFromFees[from]) {
439|              super._update(from, to, amount);
440|              return;
441|          }
442|  
443|          require(!_blackList[from] && !_blackList[to], "refuse address");
444|  
445|          if (!inSwap && _isPairs[to]) {
446|              if (feeAmount1 >= swapTokensAtAmount) {
447|                  swapTokenForUsdt(feeAmount1, feeAddress);
448|                  feeAmount1 = 0;
449|              }
450|              if (feeAmount2 >= swapTokensAtAmount) {
451|                  swapTokenForUsdt(feeAmount2, feeAddress2);
452|                  feeAmount2 = 0;
453|              }
454|          }
455|  
456|          bool isSell;
457|          uint256 taxAmount;
458|  
459|          if (_isPairs[from]) {
460|              //buy
461|              revert("not alw buy");
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|          }
470|  
471|          emit TranserFeeLog(amount, taxAmount);
472|  
473|          if (isSell) {
474|              _antiFlashloanGuard(from, to, false, isSell);
475|          }
476|  
477|          amount = amount - taxAmount;
478|  
479|          super._update(from, to, amount);
480|      }

攻擊分析

攻擊交易 的關鍵步驟總結如下:

  • 步驟 1:攻擊者閃電貸了 315,520,309e18 USDT 用於步驟 2,並向地址 0xc4DB5B 轉移了 875e18 SOF 用於步驟 3。

  • 步驟 2:通過 swapTokensForExactTokens()313,567,718e18 USDT 兌換為 991,223e18 SOF。接收地址是一個費用豁免地址,滿足了 SOF 合約中 isExcludedFromFees[to] 的檢查,從而跳過了 _isPairs[from] 的檢查(否則買入操作會回滾)。這使攻擊者能夠在步驟 3 中燒毀池中幾乎所有的 SOF 代幣。這也繞過了 _antiFlashloanGuard() 檢查——該合約沒有記錄這筆買入操作,允許步驟 3 在不被攔截的情況下繼續進行。關鍵的是,這筆大規模買入操作旨在使資金對中僅剩下 787e18 SOF(以及 313,816,344e18 USDT)。

  • 步驟 3:從地址 0xc4DB5B 出發,通過 swapExactTokensForTokensSupportingFeeOnTransferTokens()875e18 SOF 兌換為 USDT。PancakeSwap V2 路由器首先執行 SOF.transferFrom(),然後處理兌換。在 SOF.transferFrom() 期間,_update() 中的賣出邏輯將 875e18 的 90%(即 787e18)從資金對中轉移到 _destroyAddress——正如步驟 2 中設計的,這幾乎是資金對中所有的 SOF 餘額。在這次銷毀和 sync() 之後,資金對中剩餘 313,816,344e18 USDT 和僅 10e9 SOF。由於 SOF 的價格現在被大幅高估,隨後的兌換產生了一筆巨大的 USDT 支付。

  • 步驟 4:攻擊者償還閃電貸並保留了約 $225K 的利潤。

結論

該漏洞證明,對於支持「銷毀後賣出」機制的代幣,控制誰可以買入代幣至關重要。任何能夠賣出代幣的人都有利可圖;如果攻擊者能夠從池中購買代幣,他們就可以人為地抬高價格,然後通過反向兌換來榨乾整個資金池。

調查注意到 _antiFlashloanGuard() 函數的實現不當。它僅限制同一個 msg.sender 進行買入和賣出,而不是追蹤 tx.origin。這允許攻擊者通過在買入操作期間選擇一個費用豁免地址作為 to(接收方)地址來繞過該守衛。

為了防止類似的攻擊,開發人員必須確保只有授權角色才能從資金池中購買。此外,_antiFlashloanGuard() 的實現應同時記錄 tx.origin 和用戶地址,以防範攻擊者在同一筆交易中使用多個地址執行買入和賣出操作。


關於 BlockSec

BlockSec 是一家全棧區塊鏈安全與加密合規服務提供商。我們開發的產品和服務旨在幫助客戶進行代碼審計(包括智能合約、區塊鏈底層架構及錢包)、實時捕獲攻擊、分析安全事件、追蹤非法資金,並在協議和平台的整個生命週期內履行反洗錢(AML/CFT)義務。

BlockSec 已在各大頂級會議上發表多篇區塊鏈安全論文,披露了多項 DeFi 應用的零日漏洞,成功阻截多次黑客攻擊從而挽救了超過 2,000 萬美元的資金,並保護了價值數十億美元的加密貨幣。

Best Security Auditor for Web3

Validate design, code, and business logic before launch. Aligned with the highest industry security standards.

BlockSec Audit