背景介紹
2025年2⽉21⽇晚,我們監測到⼀筆涉及Bybit 交易所的重⼤安全事件。當晚02:16 UTC ,我們監測到Bybit Cold Wallet發起⼀筆⼤額轉帳:
https://etherscan.io/tx/0xb61413c495fdad6114a7aa863a00b2e3c28945979a10885b12b30316ea9f072c ,
轉出401,346 ETH 價值約1.5 BillionUSD 。經過多⽅確認,確定這是⼀起針對Bybit 的攻擊。
關於Safe{Wallet}
經過多⽅的分析與調查,整個事件的⼤致流程已經比較清晰。攻擊者⾸先利⽤釣⻥的⼿段,攻擊了Safe{Wallet} 和核⼼開發者,竊取到了AWS 的CloudFront 或S3 的Access Key 。隨後,利⽤ Access Key 向Safe{Wallet} 的前端注入惡意程式碼。恰好,受影響時, Safe{Walllet} 被archive.org 的Wayback Machine 收錄。具Wayback Machine 顯⽰, Safe{Wallet} 的前端程式碼在2025年2⽉19⽇17:28:33 已經被注入惡意程式碼。
惡意程式碼出現在前端js ⽂件_app-52c9031bfa03da47.js 中,
我們講其中惡意程式碼的核⼼邏輯取出,如下:
整個邏輯比較簡單,當sd.getAddress() 即Safe錢包的地址在["0x1db92e2eebc8e0c075a02bea49a2935bcd2dfcf4","0x19c6876e978d9f12814743924921"
則將to 位址設定為: 0x96221423681a6d52e184d440a8efcebb105c7242 ,
data設定為: 0xa9059cbb000000000000000000000000bdd077f651ebe7f7b3ce16fe5f2b025be29 695160000000000000000000000000000000000000000000000000000000000000000 ,然後調⽤ executeTransaction 簽章交易。
其中,惡意的js 程式碼中: 0x1db92e2eebc8e0c075a02bea49a2935bcd2dfcf4 ,
這個錢包位址就是Bybit 失竊的多簽冷錢包位址。也就是說,攻擊者的惡意程式碼是針對Bybit 的冷錢包進⾏定向攻擊,這樣做的好處是盡量減少被發現的⼏率。防⽌其他⽤戶注意到。其中to 位址也就是Safe 錢包即將調⽤的合約位址為0x96221423681a6d52e184d440a8efcebb105c7242 ,這個智慧合約未開源,經過反編譯發現合約功能很簡單,僅僅實作了⼀個transfer 函數的功能是將功能是將程式設定為 0個裝置。
se.data.data 就是調⽤上述合約的calldata ,其中前四個位元組為0xa9059cbb ,就是transfer(address recipient, uint256value) 的簽章。後續的參數分別為recipient 為: 0xbdd077f651ebe7f7b3ce16fe5f2b025be2969516 ,value 為0 。因為, Bybit 皮夾讓⽤的Safe{Wallet} 版本為1.1.1 ,改版本的皮夾執⾏合約調⽤的邏輯為MultiSig Address-[Signature]->Wallet MasterCopy Proxy-[Delegatecall]-> Wallet Logictract-[Delegatectectract-[Callwg.的slot0 ,也就是正式接管該錢包。
惡意程式碼中,其中的另⼀個位址: 0x19c6876e978d9f128147439ac4cd9ea2582cd141,是攻擊者⽤來測試攻擊流程的測試位址。也就是說,改惡意程式碼會劫持兩個錢包,錢包1為Bybit的Cold Wallet ,錢包2為攻擊者的測試錢包。由於Bybit Cold Wallet 的程式碼版本為1.1.1 ,所以攻擊者同樣創建了⼀個1.1.1 版本的Safe錢包,創建的交易為:https://etherscan.io/tx/0x8df9884dd022f900ea7ebcbd0d47356137e3dd022f900ea7ebcbd0d47356137e3dcc ,由於Safe的App已經⽆法創建舊版本的錢包,攻擊者是如何創建的呢?
我們看到,攻擊者是調⽤ Proxy Factory 1.1.1 的createProxyWithNonce 來創建的在Ethereum mainnet 上測試錢包
於是,我們在Sepolia 測試鏈上同樣利⽤ createProxyWithNonce 創建了⼀個Safe 錢包, version 為1.1.1 。我們的創建交易為https://sepolia.etherscan.io/tx/0xa7ce1ce4cb5ccb65eb9a35842ebde8f9a161dd561bce80528dbb7362efc33ff0 ,創建的錢包位址為:0xfdfd440e9d920a8a577eb3d586547986b889ad56。
但是,我們創建的錢包位址卻⽆法匯入到Safe的app中。
我們可以看到Safe創建Multisig wallet的程式碼如下:
由於Safe 創建Wallet 使⽤create2來創建proxy := create2(0x0, add(0x20, deploymentData), mload(deploymentData),salt) ,所以只需要保證MasterCopy , initializer , saltNonce ⼀直,就可以創建相同地址的錢包。於是,我們利⽤和攻擊者同樣的參數,在Sepolia 測試鏈上創建了與攻擊者在Ethereum mainnet 上相同的地址0x19c6876e978d9f128147439ac4cd9ea2582cd141 ,創建交易為https://sepolia.etherscan.io/tx/0x3ec6ef599d1df75c9f255f4c1a0edaed8ef992a4fd6ea90af50a05ca962c9e69 ,但是該地址仍⽆法導入Safe 的app 中。
⽽攻擊者在Ethereum mainnet 上建立的位址即可成功匯入到Safe app 中,
隨後,我們在官⽅的⽂檔中發現,Safe錢包在L1上使⽤trace-base來索引創建好的錢包,https://github.com/safe-global/safedocs/blob/f48 7ace5e0221437277bd9d56fb340794dda424c/pages/advanced/cli-guides/recovery-safe-deployment.mdx#L42
理論上,所有透過Factory創建的錢包都可以使⽤Safe app,因為攻擊者篡改了Safe app的前端代碼,導致只有使⽤Safe app才會收到攻擊。但是,我們透過Factory 1.1.1創建的Safe錢包始終⽆法被索引,所以也⽆法測試。我們也不知道為何攻擊者創建的錢包可以被Safe索引。
關於安全
由於Bybit使⽤的Safe{Wallet}版本為1.1.1比較老,⽬前最新的版本1.4.0對於本次攻擊的攻擊⼿法(利⽤修改slot0來接管錢包)已經失效了
我們可以看到,這裡已經由delegatecall 變成了call ,也意味著只能修改被調⽤合約本⾝的slot ,⽆法修改proxy 的slot 。但是,後續還需防範類似的攻擊⼿段,攻擊者可能直接建構轉移資產的交易,因此,我們建議在簽章交易前,先使⽤ Safe 內建的Tenderly 對交易進⾏模擬後,確認⽆誤再進⾏簽章。