起因
近期,發生了幾起非常嚴重的跨鏈橋黑客事件,造成了重大損失:
2022 年2 月2 日,Wormhole 遭到攻擊,損失3.2 億美元;
2022 年3 月29 日,Ronin 遭到攻擊,損失超過6 億美元。
這些損失引發了一個關於異構鏈互操作性安全級別方面的長遠思考,尤其集中在如何能夠減少或緩解這些攻擊的方面。實際上,所有這些攻擊都源於一個跨鏈預言機問題——如何確保某些事件(例如,鎖定/銷毀事件)在源鏈上發生,以避免發生下列情況:
API故障:如Wormhole所經歷,黑客利用一些已棄用而Wormhole仍信任的API進行攻擊;或者
密鑰被盜:正如Ronin 所經歷的,黑客獲取了9 個驗證者密鑰中的5 個。
當API 被利用或密鑰被盜時,黑客可以在目標鏈(尤其是去中心化程度比較高的以太坊等)上提交一個取走全部交易的指令轉走所有鏈上資產,即便源鏈上沒有相應的鎖定/燒毀事件。儘管跨鏈橋可能在幾個小時後檢測到這種異常活動,然而資產已經轉移到黑客的賬戶中,並且很難追回。
通過速率限制器緩解攻擊
速率限制器是一種確保稀缺資源在特定時間內不被濫用的通用技術。例如,通過將服務器的訪問限制設置為每秒100 萬個請求,我們可以防止服務器被DDoS 攻擊的大量流量沖垮。
運用到跨鏈橋場景,速率限制器的基本思想是如果每天的提款金額超過預設限制(例如,2000 萬美元),則暫停提款。此外,速率限制器將通知跨鏈橋的項目方,並進行人工干預以檢查跨鏈橋的安全狀況。如果一切正常,可以重置一天的限額來再次進行提款。注意,速率限制也是CEX 的常用安全措施。
速率限制器能夠緩解攻擊造成的損失,尤其是對這種一次取走全部資產的攻擊。例如,假設我們將橋的提現額限制為每天2000 萬美元,那麼攻擊者一天最多只能進行2000 萬美元額度的攻擊。也就是說,如果跨鏈橋的項目方可以在一天內發現遭到了攻擊,就可以將跨鏈橋總鎖倉的損失減少到僅為每天限額值(例如,在Ronin 案例中,僅損失2000 萬美元而非6 億美元)。
速率限制器類型
鏈下速率限制器
在公證/多簽場景中,鏈下速率限制器可能是最簡單的實現方式。中繼/共同簽名者將實現一個鏈下算法(實際上QuarkChain 橋也實現了這部分),如果超額,他們將拒絕簽署交易到目標鏈。他們可能會進一步要求人工干預以確認跨鏈橋的健康狀態,然後再重置限額並繼續工作。
鏈下速率限制器的優勢在於非常高效——不需要更改鏈上合約,也無鏈上GAS 成本。此外,鏈下速率限制器可以減輕API攻擊的情況(如Wormhole ),一旦請求3 億美元的提款,多簽節點將停止簽名。其結果是,黑客只能請求一個比3億美元小得多的提款金額,最多只能竊取2000 萬美元(因為限額)。
鏈下速率限制器的缺點是它無法緩解密鑰被盜的情況。因為一旦密鑰被盜,黑客可以通過直接對提款交易進行簽名來繞過多簽部分。這意味著對Ronin的攻擊仍可發生。
鏈上速率限制器
我們可以採用鏈上速率限制的方式來減輕多簽秘鑰被盜的損失,但會以額外的鏈上GAS 消耗為代價。除非金額小於允許的限額,否則即使黑客用秘鑰簽署了提款交易,鏈上合約也會阻止此類提款。這為項目方提供了額外的時間(例如24 小時)來檢測攻擊並在發現時停止跨鏈橋。
一個關鍵問題是如何以高效使用GAS 的方式實施限額合約。 Consensys 提供了一個速率限制器的版本
https://consensys.github.io/smart-contract-best-practices/development-recommendations/precautions/rate-limiting/。 Consensys 版本的基本理念是將時間劃分為不重疊的時間段,每個時間段有一個最大提取金額。
雙倍限額攻擊示意圖
雖然Consensys 速率限制器比鏈下更安全,但通過執行以下策略,可以造成2倍限額的損失(例如,假設限制是2000 萬美元,但攻擊最多可以竊取4000 萬美元) :
在一個時間段的最後操作一次提款;
在下一個時間段開始時再進行一次提款。
如果兩次提款的間隔很小,那麼跨鏈橋的項目方可能沒有足夠的時間來檢測第一次的提款攻擊,並停止下一次提款。
基於滑動窗口的鏈上速率限制器
對於Consensys 的實現而言,其問題在於速率限制時間段的粒度太大(例如,24 小時)。我們可以在多個速率計算的時間單位(bin)上使用滑動窗口的方式來獲得更小的粒度:
每個bin 定義了一個更細粒度的時間間隔(例如,1 小時);
每個bin 用來累計在該bin定義的時間的取款數目;
取款的速率可以通過添加最近的bin 的數目來產生(例如,24小時24個包);
過期的bin 可以重複使用以節省存儲成本(以及GAS 成本)。
下圖說明了有滑動窗口的鏈上速率限制器的基本思想(以每個bin 6小時為例)。
滑動窗口速率限制器示意圖
滑動窗口速率限制器的優勢在於,攻擊者現在必須等待速率限制的持續時間減去bin 持續時間才能提交下一個攻擊交易。如果以24 小時作為限速持續時間,1 小時作為bin 持續時間,我們可以將下一次攻擊推遲到23 小時後,並且希望跨鏈橋能夠在23 小時內檢測到第一次攻擊並停止工作。
基於智能合約的高效實現
我們在這裡https://github.com/quarkchain/rate-limiting 實現了一個高度優化的滑動窗口限額的實現(請注意,代碼未經審計,因此使用風險自負)。平均gas 成本約為20k,小於Ronin 提款交易(約230k gas)的10%。主要優化部分是在存儲上,我們在其中使用了壓縮的bin 表示,以便最大限度地減少sload/sstore 操作碼的使用。
結論
在本文中,我們提出了一種帶有滑動窗口的速率限制器,以減輕跨鏈橋的攻擊損失。此外,我們還提供了一種高效且低gas成本的實現方式。我們相信速率限制器的思想和實現可以大大降低跨鏈互操作協議的風險。