2022年1月18日,我們的異常交易監測系統檢測到了針對AnySwap項目(即Multichain)的攻擊。由於anySwapOutUnderlyingWithPermit()
函數未能正確地實現相關校驗機制,導致用戶授權給該項目的token可被攻擊者取出,關於漏洞細節和相關處置詳情可參考項目方的官方說明(https://medium. com/multichainorg/multichain-contract-vulnerability-post-mortem-d37bfab237c8)。
儘管項目方嘗試了多種方法試圖提醒受影響的用戶(如發送交易提醒,圖1所示),仍然有很多用戶未能及時響應(撤回自己的授權),攻擊者得以持續地實施攻擊獲利。
由於攻擊持續進行,為了保護潛在的受害者,BlockSec團隊決定採取應急響應措施。本次救援特別針對以太坊(Ethereum)上受到影響的賬戶,與之關聯的項目方合約地址為0x6b7a87899490EcE95443e979cA9485CBE7E71522 ,我們將相關的賬戶資金轉移到我們專門設立的多簽白帽賬戶中( 0xd186540FbCc460f6a3A9e705DC6d2406cBcc1C47 ) 。為了保證行動的透明性,我們將相關行動計劃在pdf文件中做了說明,並立即將文件hash(而非內容)向社區公開。這樣既能夠保證將我們的行為與攻擊者行為做區分,也不會洩漏任何細節(因為攻擊仍在持續)。我們的救援行動從2022年1月21日正式開始,到2022年3月11日正式結束,相關的公開聲明分別如圖2、圖3所示。
應急救援並非是一件容易達成的任務,有各種技術和非技術方面的挑戰需要克服。由於行動已經結束,我們得以重新復盤整個過程,並將相關心得與體會與社區分享。我們希望也相信這樣的分享對社區,以及DeFi生態的安全會有所幫助。
簡要總結(太長不看版)
不同陣營的參與者對Flashbots的廣泛使用產生了激烈競爭,包括白帽和攻擊者兩個群體之間,乃至各自群體內部,向Flashbots支付的費用也隨著時間的推移迅速增長。
Flashbots不是萬靈丹,並非總是有效。有些攻擊者轉而使用mempool,通過巧妙的策略安排了攻擊交易,成功實施了攻擊。
某些攻擊者與項目方達成協議,歸還部分攻擊所得,保留部分攻擊所得作為獎賞,得以成功洗白。這種現像不是第一次出現,其激勵的公平性也在社區內部引起了很大的爭議和討論。
從透明性考量,白帽可以在不洩露敏感信息的同時向社區公開宣告自己的行為,這樣取信於社區的方式在實踐中表現良好。
社區的各方力量可以攜手合作,使得救援行動更為迅速和有效。比如可以在白帽之間開展協同,減少或避免無效競爭。
以下我們將從四個方面展開。首先是對本次事件的總體性回顧,而後介紹我們實施救援的方法以及在整個過程中面臨的挑戰,接下來討論我們在本次行動中的一些心得和體會,最後提出一些想法和建議。
0x1 攻擊和救援情況概覽
0x1.1 總體結果
在我們觀察範圍內(從2022年1月18號區塊高度14028474 - 2022年3月20號區塊高度14421215),總體的攻擊和救援情況如表1所示,按照參與攻擊或救援的以太坊賬戶地址統計(為方便顯示,地址只顯示了前4位)。具體來說,一個賬戶地址或者是救援賬戶,或者是攻擊賬戶,而類型是根據Etherscan.io的標籤和資金轉移地址來確定的。此外,在攻擊和救援的過程中,白帽和攻擊者均大量使用了Flashbots來發送交易,因而需要額外向礦工支付費用,我們稱之為Flashbots費用。
總體而言,有9個救援賬戶保護了483.027693 ETH,其中需扣除支付給Flashbots費用為295.970554 ETH(佔比61.27%);有21個攻擊賬戶獲利1433.092224 ETH,其中需扣除給Flashbots的費用為148.903707 ETH(佔比10.39%)。值得注意的是,由於存在一些複雜的交互情況(比如某些攻擊者在與項目方協商達成一致後返還部分獲利,相關的地址標籤可能發生變化,被標記為白帽賬戶,對於這種情況我們也會在報告中展開討論),表格中列出的只是大概的統計。
0x1.2 Flashbots費用的變化趨勢
如前所述,白帽們需要和攻擊者競爭發送Flashbots交易來實施救援,支付給Flashbots的費用的變化趨勢可以反映競爭的激烈程度。為了對其作定量的評估,我們按照交易區塊,對攻擊和救援交易分別統計了各自Flashbots費用的佔比。
圖4給出了我們觀察範圍內的佔比趨勢。剛開始的一些攻擊交易的Flashbots費用為0,表示在那段時間攻擊者尚未使用Flashbots,在早期其他人對漏洞尚未有了解,因此競爭並不激烈。在高度為14029765的區塊中,出現了第一筆使用Flashbots的攻擊交易,Flashbots費用佔了獲利的10%。在這之後,Flashbots費用佔比隨著參與競爭者數量的增加而快速上升,比如在區塊高度14072385時Flashbots費用佔比達到80%,隨後在區塊高度14129449費用佔比即達到91%。簡而言之,這樣的趨勢表明這業已成為由於Flashbots上鍊權之爭而導致的費用軍備競賽。
0x2 我們實施的救援行動和麵臨的挑戰
0x2.1 我們如何開展救援行動?
救援的基本思路是簡單而直接的。具體而言,我們需要監控一批潛在的受害者賬戶,這些賬戶已將WETH授權給有問題的項目方合約使用。當有任何的WETH轉賬進入該賬戶,我們利用合約漏洞直接將其轉出至我們的白帽多簽錢包。這裡的關鍵是要滿足以下三個要求:
R1 : 有效地定位轉賬給受害者賬戶的交易,為方便敘述,以下我們將這些交易命名為轉賬交易( transferred TXs )。
R2 : 正確地構造交易實施拯救,為方便敘述,以下我們將這些交易命名為拯救交易( rescue TXs )。
R3 : 成功地搶跑攻擊者(或其它第三方)交易,為方便敘述,以下我們將這些交易命名為攻擊交易( attack TXs )。
R1和R2對我們而言並不構成阻礙。因為我們已經構建了一套內部系統來監控mempool,得以及時定位到轉賬交易;與此同時,我們也研發了一套工具用以自動化地構造拯救交易。
然而R3仍然是一個挑戰。雖然在理論上Flashbots可被用來贏得搶跑,然而這並不是一個容易達成的目標。首先,攻擊者也可能採用Flashbots,作為一個採用費用競拍模式的系統,成功率取決於費用的高低,而費用設置的策略需要額外考量。其次,由於上述競拍模式導致的競爭存在,使用Flashbots並不總是一個好的選擇。因此,我們也使用mempool發送普通交易。為了確保成功,交易在mempool中的位置和順序是關鍵因素,其設置策略也需納入考量。最後,我們也與其它的一些“白帽”產生了競爭,而在某些情況下這些所謂“白帽”的行為其實是較為可疑的。
0x2.2 我們捲入的競爭
總體而言,我們嘗試保護171個獨立的潛在受害者賬戶。其中有10個通過及時撤銷了授權做了自我保護,而在餘下的161個賬戶中,由於前述各類競爭的存在,我們僅成功救援了14個。我們將失敗的情況總結在下面的表格中,涉及3個救援賬戶和16個攻擊賬戶。
0x3 我們的經驗教訓
0x3.1 如何確定Flashbots費用?
在整個救援過程中,我們先後被12個同樣利用Flashbots的競爭者擊敗,包括2個救援賬戶和10個攻擊賬戶。
我們設置Flashbots費用的策略相對而言是較為保守的。具體而言,為了保護受害者的利益,我們總是傾向於盡可能較少地設置Flashbots費用。因此除非已經有成功地使用Flashbots的攻擊交易出現,我們並不會主動地使用Flashbots或增加Flashbots費用。比如一個成功的攻擊交易設置的Flashbots費用比例為10%,我們可能會在下一次救援交易中將之設置為11%。但是,結果證明這樣的策略並不太成功,攻擊者(甚至一些白帽)通常會採用較為激進的策略設置費用以贏得競爭,例如:
圖5展示了區塊高度為14071986的一筆攻擊交易,攻擊者0x5738** 將比例設置為70%。
圖6展示了區塊高度為14072255的一筆攻擊交易,白帽0x14ca** 將比例設置為79%。
圖7展示了區塊高度為14072385的一筆攻擊交易,白帽0x14ca** 將比例設置為80%。
圖8展示了區塊高度為14072417的一筆攻擊交易,白帽0x9117** 將比例設置為81%。
圖9展示了區塊高度為14073395的一筆攻擊交易,攻擊者0x5738** 將比例設置為86%。
簡而言之,這似乎是一個零和遊戲,可以通過建模來探索各參與方的行為模式。但在具體實踐中這是一項頗具挑戰的任務:一方面需要盡可能降低代價,另一方面要找到較優/最優的策略贏得競爭。
0x3.2 如何在mempool中正確地安排交易位置?
目前看起來救援成功與否依賴於Flashbots費用的軍備競賽。然而我們確實發現,由於多個參與方引發的激烈競爭的存在,使得Flashbots並非總是有效,這裡的激烈競爭來自於和攻擊/救援無關的其它交易發送方,比如套利等。在這種情況下,即便某個攻擊交易所設置的最高(相較於其它攻擊和救援交易)Flashbots費用,都無法保證贏得Flashbots競爭。
另一個可行的方法是使用通過mempool發送正常交易,如果交易被安排在合適的位置,也有可能實現目標。這里合適的位置指的是攻擊/救援交易位於轉賬交易之後,且非常接近轉賬交易(越近越好,如果恰好處在轉賬交易的下一個位置則最為理想)。事實上,攻擊者0x48e9**運用這樣的策略成功的收割了312.014657 ETH,且並沒有付出任何Flashbots費用的成本。以下四幅圖展示了該攻擊者獲利最高的兩次攻擊:
圖10和圖11分別展示了在區塊高度14051020,受害者0x3acb**的轉賬交易(轉入50 ETH)位於65,而攻擊交易(獲利50 ETH)位於66。
圖12和圖13分別展示了在區塊高度14052155,受害者0xbea9**的轉賬交易(轉入200 ETH)位於161,而攻擊交易(獲利200 ETH)位於164。
顯然,這樣巧妙的策略兼具實用性和啟發性,值得關注和學習。
0x4 一些其它的思考
0x4.1 如何區分白帽和攻擊者?
識別白帽及其行為可能並不像一般人認為的那樣簡單直白。舉例來說,賬戶地址0xfa27被Etherscan.io標記為白帽: Multichain Exploiter 4 (Whitehat) 。然而在一開始的時候,這個地址被標記為攻擊者: Multichain Exploiter 4 。這裡的變化來自於項目方和攻擊者的互動, 在若干輪協商之後,攻擊者同意保留50 ETH的獲利作為獎賞,返還其它獲利(扣除Flashbots費用等):
在交易0x3c3d**中,項目方聯繫該攻擊者:
在交易0xd360**中,攻擊者回复:
在交易0x354f**中,項目方在受到返還的資金後表示感謝:
毫無疑問,該攻擊者通過這樣的方式不僅獲利也成功洗白了自己。這種現像不是第一次出現,其激勵的公平性也在社區內部引起了很大的爭議和討論。
0x4.2 白帽之間的競爭
社區有必要建立一個溝通協調機制來降低/避免白帽之間的競爭。一方面,這樣的競爭會浪費救援資源。比如在本次救援中,我們和其它三個白帽(組織)試圖同時保護54個受害者(涉及450 ETH損失)。另一方面,這樣的競爭也提高了救援成本。這些競爭會不可避免地加劇Flashbots費用比例的提高。如之前的圖7和圖8所示,不同白帽先後設置了80%和81%的Flashbots費用比例。然而可以想見的是,如果沒有相應的協調機制,白帽們是無法放棄/停止這樣的競爭的。
0x4.3 如何更好地開展救援行動?
一方面,從透明性考量,白帽可以在不洩露敏感信息的同時向社區公開宣告自己的行為,這樣取信於社區的方式在實踐中表現良好。與針對某個特別攻擊的阻斷(blocking)任務相比,這樣的救援(rescuing)行動通常是拉鋸戰,白帽和攻擊者之間會在一段時間內交手多次,因此會有充足的時間做宣告。當然,在剛開始行動的時候,漏洞相關的細節信息並不需要披露,以免造成不必要的危害(但記錄行動意圖的文件hash可以與社區共享,如同我們在此次救援中所做的那樣) ;在行動結束後,這些信息應該向社區充分公開。
另一方面,社區的各方力量可以攜手合作,使得救援行動更為迅速和有效,包括但不限於:
Flashbots/Miners向認證過且可信的白帽提供綠色通道,既可用於搶跑攻擊交易,也能避免白帽間的競爭。
被攻擊的項目方負責Flashbots費用的成本。
項目方採用更為方便和快捷的機制及時向用戶預警。
項目方在代碼中採用一些必要的應急措施。