2026年1月25日,我們偵測到一系列針對 SwapNet 與 Aperture Finance 部署在 Ethereum、Arbitrum、Base 和 BSC 上的受害者合約的疑似交易,造成的總損失超過 1,700 萬美元。從宏觀角度來看,這兩起事件的根本原因很直接,且已在我們最初的警報中概述 [1, 2]:
受害者合約由於輸入驗證不足,暴露了任意呼叫(arbitrary-call)的功能,使得攻擊者能夠濫用現有的代幣授權(token approvals)並呼叫 transferFrom 來耗盡資產。
然而,這兩套受害者合約均為閉源合約,反編譯後會產生數千行代碼,且包含深度嵌套與複雜的分支邏輯,這顯著增加了分析的難度。此外,受影響專案隨後發布的事後檢討報告 [3, 4] 主要集中在補救與復原上,對底層技術細節的討論有限。因此,許多重要的問題仍未得到解答,包括脆弱的呼叫路徑是如何構成的,以及為何現有的檢查未能防止漏洞被利用。
在本報告中,我們基於反編譯的位元組碼(bytecode)與鏈上執行追蹤,提供了更詳細的技術分析。雖然缺乏原始碼限制了可見度,但位元組碼層級的分析足以重建易受攻擊的邏輯,並揭示了一些關於合約設計的有趣觀察,這些觀察從高層次的警報中並不能直接看出來。
我們首先深入探討 SwapNet 事件,隨後詳細分析 Aperture Finance 事件。
SwapNet 事件
背景
SwapNet [5] 是一個去中心化交易所(DEX)聚合器,旨在透過匯總來自多個鏈上來源(包括 AMM 和私人做市商)的流動性來尋找最佳掉期路徑。該協議還允許使用者在執行掉期時指定自訂路由器或資金池,從而提供額外的靈活性。
根本原因分析
此事件源於對使用者提供的輸入缺乏足夠的驗證,這使得攻擊者能夠使用任意參數觸發 transferFrom() 呼叫。因此,先前已授權給受害者合約(例如 0x616000e384Ef1C2B52f5f3A88D57a3B64F23757e)的資產可能會被轉移給攻擊者。
根據反編譯的位元組碼,函數 0x87395540() 對關鍵輸入似乎缺乏適當的驗證。透過將預期的路由器或資金池位址替換為代幣位址(例如 USDC),合約錯誤地將代幣視為有效的執行目標。這導致了一個底層呼叫被執行,且帶有攻擊者控制的 calldata。
因此,受害者合約執行了以下格式的呼叫:approvedAsset.transferFrom(victim, attacker, amount),允許攻擊者竊取所有已授權的資產。
攻擊流程
我們觀察到針對 SwapNet 的多起攻擊。此處我們以 Base 交易 0xc15df1d131e98d24aa0f107a67e33e66cf2ea27903338cc437a3665b6404dd57 作為範例。
攻擊者僅僅使用惡意輸入呼叫了受害者合約的 0x87395540() 函數。此調用包含兩個主要步驟:
- 一個關鍵的內部變數(例如
v51)被設定為 USDC,繞過了預期的路由邏輯。
- 一個底層呼叫被執行,其使用的是由攻擊者控制的 calldata,導致
USDC.transferFrom()被呼叫,所有已授權的 USDC 隨之被耗盡。
損失摘要、交易與受影響合約
SwapNet 事件在多條鏈上造成的估計損失約為 1,341 萬美元。下表總結了關鍵的攻擊交易與所涉及的受害者合約位址。
Aperture Finance 事件
背景
Aperture Finance [6] 是一個 DeFi 協議,代表使用者管理集中流動性頭寸(例如 Uniswap V3 LP)。其閉源合約(例如 0xD83d960deBEC397fB149b51F8F37DD3B5CFA8913)允許使用者使用原生代幣鑄造與管理 Uniswap V3 頭寸。
鑄造 UniswapV3 頭寸的預期工作流程
當透過 0x67b34120() 函數鑄造 Uniswap V3 頭寸時,合約遵循一個預期的三步驟工作流程:
-
封裝原生代幣(Wrap native tokens)
-
透過內部函數
0x1d33()交換原生代幣 -
鑄造 UniswapV3 頭寸
問題出在第 2 步:0x1d33() 透過底層呼叫執行自訂交換,其中關鍵參數(例如呼叫目標與 calldata)似乎是由使用者控制且驗證不足的,這導致了非預期的外部呼叫。後續章節提供了更多細節。
根本原因分析
與 SwapNet 事件類似,Aperture Finance 事件是由於對底層呼叫的輸入驗證不足所造成的。當呼叫 0x67b34120() 時,內部函數 0x1d33() 使用由使用者提供的 calldata 執行底層呼叫,而沒有對呼叫目標或函數選擇器實施嚴格限制。
如下圖所示,用於觸發底層呼叫的 calldata 完全基於攻擊者的輸入。
這使攻擊者能夠構建惡意的 calldata,導致:在受害者合約的內容中執行 approvedToken.transferFrom(victim, attacker, amount)。結果,不僅是 ERC20 代幣,就連已授權的 Uniswap V3 頭寸 NFT 也可能被竊取。
攻擊流程
我們觀察到針對 Aperture Finance 的多起攻擊。在本節中,我們以 Ethereum 交易 0x8f28a7f604f1b3890c2275eec54cd7deb40935183a856074c0a06e4b5f72f25a 作為代表性範例。
-
攻擊者創建了一個攻擊合約
0x5c92884dFE0795db5ee095E68414d6aaBf398130。 -
攻擊合約以惡意輸入及
100wei ETH(即msg.value==100)呼叫了函數0x67b34120()。
- a) 原生 ETH 透過
WETH.deposit()函數被封裝成 WETH。
- b) 內部函數
0x1d33()被呼叫以執行底層呼叫。在此步驟中,受害者合約中觸發了WBTC.transferFrom(victim, attacker, amount)的呼叫,允許攻擊者竊取已授權的代幣。值得注意的是,0x1d33()函數在結束時通過了一個餘額檢查。具體來說,函數0x1d33()將餘額變化與攻擊者指定的交換輸出值(即varg2.word2)進行了比較。因此,該操作通過接收零來成功執行。
- 最後,呼叫函數
NonfungiblePositionManager.mint(),使用100weiWETH為攻擊者鑄造一個頭寸。
有趣的發現
透過比較正常與異常的鑄造交易,我們觀察到兩者都將代幣授權給了同一個 spender(例如 OKX DEX: TokenApprove),但指定了不同的路由器位址(即 DexRouter 與 WBTC)。這表明該合約可能對批准的 spender 實施了驗證,但在驗證實際執行目標時失敗了,從而留下了一個可透過任意呼叫利用的重大漏洞。
損失摘要、交易與受影響合約
Aperture Finance 事件在多條鏈上造成的總損失估計約為 367 萬美元。下表總結了關鍵的攻擊交易與相關的受害者合約位址。
結論
雖然 SwapNet 與 Aperture Finance 事件影響了不同的協議與鏈,但這兩起案例的潛在問題並不複雜:由使用者控制的底層呼叫,結合了持有代幣授權合約中輸入驗證的不足。這些事件提醒我們,在合約設計中,靈活性必須與嚴格的呼叫限制仔細平衡,特別是在外部審計受限的閉源系統中。
參考文獻
[1] https://x.com/Phalcon_xyz/status/2015614087443697738
[2] https://x.com/Phalcon_xyz/status/2015624519898234997
[3] https://meta.matcha.xyz/SwapNet-Incident-Post-Mortem
[4] https://x.com/ApertureFinance/status/2015938720453820752
[6] https://x.com/ApertureFinance
關於 BlockSec
BlockSec 是一家提供全端區塊鏈安全與加密合規服務的供應商。我們致力於建構產品與服務,協助客戶在協議與平台的生命週期中執行程式碼審計(包含智慧合約、區塊鏈與錢包)、即時攔截攻擊、分析事件、追蹤非法資金,並滿足 AML/CFT 合規義務。
BlockSec 已在知名會議上發表多篇區塊鏈安全論文,通報了多項 DeFi 應用程式的零日漏洞,攔截了多次駭客攻擊並挽救了超過 2,000 萬美元的資金,並保障了數十億美元的加密貨幣安全。
-
官方 Twitter 帳號:https://twitter.com/BlockSecTeam
-
🔗 BlockSec 審計服務 : 提交請求



