致命殘留:一場由瞬態存儲引發的30萬美元鏈上劫案
作者:九九 & Lisa
編輯:Sherry
背景
2025年 3 月30 日,根據慢霧 MistEye 安全監控系統監測,Ethereum 鏈上的槓杆交易項目 SIR.trading (@leveragesir) 遭攻擊,損失價值超 30 萬美元的資產。慢霧安全團隊對該事件展开分析,並將結果分享如下:
(https://x.com/SlowMist_Team/status/1906245980770746449)
相關信息
攻擊者地址:
https://etherscan.io/address/0x27defcfa6498f957918f407ed8a58eba2884768c
存在漏洞的合約地址:
https://etherscan.io/address/0xb91ae2c8365fd45030aba84a4666c4db074e53e7#code
攻擊交易:
https://etherscan.io/tx/0xa05f047ddfdad9126624c4496b5d4a59f961ee7c091e7b4e38cee86f1335736f
前置知識
Solidity 0.8.24 版本(2024 年 1 月發布)引入了基於 EIP-1153 的瞬態存儲(transient storage) 特性。這是一種新的數據存儲位置,旨在為开發者提供一種低成本、交易期間有效的臨時存儲方式。
瞬態存儲是一種與存儲(storage)、內存(memory) 和調用數據(calldata) 並列的新數據位置。其核心特點是數據僅在當前交易執行期間有效,交易結束後會被自動清除。訪問和修改瞬態存儲通過兩個新的 EVM 指令實現:
- TSTORE(key, value):將256 位的值value存儲到瞬態存儲的指定鍵key對應的內存中。
- TLOAD(key):從瞬態存儲的指定鍵key對應的內存中讀取256 位的值。
該特性主要有以下特點:
- 低 gas 成本:TSTORE 和 TLOAD 的 gas 成本固定為 100,相當於熱存儲訪問(warm storage access)。相比之下,常規存儲操作(SSTORE) 在首次寫入(從 0 到非 0)時可能高達 20,000 gas,更新時也至少需要 5,000 gas。
- 交易內持久性:瞬態存儲的數據在整個交易期間保持有效,包括所有函數調用和子調用,適合需要跨調用共享臨時狀態的場景。
- 自動清除:交易結束後,瞬態存儲自動重置為零,無需手動清理,減少了开發者維護成本。
根本原因
本次被黑事件的根本原因是,在函數中調用tstore 進行瞬態存儲的值在函數調用結束後並沒有被清空,導致攻擊者可以利用這個特性構造特定的惡意地址來繞過權限檢查轉出代幣。
攻擊步驟
1. 攻擊者首先創建兩個惡意代幣 A 和 B,之後在 UniswapV3 上為這兩個代幣創建池子並注入流動性,其中 A 代幣為攻擊合約。
2. 接着攻擊者調用 Vault 合約的 initialize 函數,以 A 代幣為抵押品代幣,B 代幣為債務代幣創建一個槓杆交易市場 APE-21。
3. 緊跟着攻擊者調用 Vault 合約的 mint 函數,存入債務代幣 B 鑄造槓杆代幣 APE。
跟進到mint 函數中,我們發現當需要存入債務代幣 B 去鑄造槓杆代幣時,需要傳入的 collateralToDepositMin 參數的值不能等於 0,之後會通過 UniswapV3 先將 B 代幣兌換成抵押品代幣 A 並轉入 Vault 中,其中會將攻擊者先前創建的 UniswapV3 池子的地址進行第一次瞬態存儲。
當UniswapV3 池子進行兌換操作時,會回調 Vault 合約的uniswapV3SwapCallback函數。可以看到:該函數首先會用tload 從先前瞬態存儲的指定鍵 1 對應的內存中取出值,來驗證調用者是否是 UniswapV3 池子,接着從鑄造者地址轉出債務代幣 B 並鑄造槓杆代幣 APE,最後將鑄造的數量 amount 進行第二次瞬態存儲,保存在指定鍵 1 對應的內存中,用作 mint 函數的返回值。這裏需要鑄造的數量是攻擊者提前計算控制好的,其值為 95759995883742311247042417521410689。
4. 攻擊者之後調用 Keyless CREATE2 Factory 合約的 safeCreate2 函數來創建一個惡意的合約,其合約地址 0x00000000001271551295307acc16ba1e7e0d4281,與第二次瞬態存儲的值相同。
5. 接着攻擊者通過該惡意合約去直接調用 Vault 合約的uniswapV3SwapCallback函數轉出代幣。
因為uniswapV3SwapCallback函數是通過tload(1) 來獲取驗證調用者是否是 UniswapV3 池子,然而在先前的鑄造操作中,指定鍵 1 對應內存中的值被保存為鑄造的數量 95759995883742311247042417521410689,並且該內存中的值在mint 函數調用後並沒有進行清空,所以使得此刻 uniswapPool 的地址被獲取為 0x00000000001271551295307acc16ba1e7e0d4281,導致對調用者的身份檢查被錯誤地通過。
並且攻擊者提前計算好了需要轉出的代幣數量,將最終鑄造的數量amount 構造為指定的值:1337821702718000008706643092967756684847623606640。同樣的,在這一次調用uniswapV3SwapCallback函數的最後,會進行第三次的瞬態存儲,將該值保存到指定鍵1 對應內存中。這是需要讓該值與攻擊合約(A 代幣)的地址的值 0xea55fffae1937e47eba2d854ab7bd29a9cc29170 相同,才能讓之後對調用者的檢查通過。
6. 最後,攻擊者就可以直接通過攻擊合約(A代幣)去調用 Vault 合約的uniswapV3SwapCallback函數,將Vault 合約中的其他代幣(WBTC、WETH) 轉出獲利。
MistTrack 分析
據鏈上反洗錢與追蹤工具MistTrack 的分析,攻擊者 (0x27defcfa6498f957918f407ed8a58eba2884768c) 盜取了約 30 萬美元的資產,包括 17,814.8626 USDC, 1.4085 WBTC 和 119.871 WETH。
其中WBTC 被兌換為 63.5596 WETH,USDC 被兌換為 9.7122 WETH:
接着,共193.1428 WETH 被轉入 Railgun:
此外,攻擊者的初始資金來源於Railgun 轉入的 0.3 ETH:
總結
本次攻擊的核心在於攻擊者利用項目中瞬態存儲不會在函數調用後將保存的值立即清空,而是會在整個交易期間中一直保存的特性,從而繞過了回調函數的權限驗證來獲利。慢霧安全團隊建議項目方應該根據相應的業務邏輯在函數調用結束後立即使用tstore(key, 0) 將瞬態存儲中的值進行清除。此外,應當對項目的合約代碼加強審計與安全測試,從而避免類似情況的發生。
鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播信息之目的,不構成任何投資建議,如有侵權行為,請第一時間聯絡我們修改或刪除,多謝。
美國非農數據今晚來襲!分析:比特幣嚴重超賣,勞動力市場疲軟或加密貨幣反彈
美 國總統川普昨(3)日推出的 關稅 政策引發全球動蕩,股市慘遭血洗的同時,加密貨幣市場也被帶崩,...
時間變現?BNB 鏈上時間經濟創新項目 Pieverse Timepot 深度詳解
在 Web3 的發展進程中,SocialFi 和時間經濟始終被認為是最有潛力的應用方向之一。圍繞影...
評論