Eclipse Attacks 日蝕攻擊 : 區塊鏈世界的中間人攻擊 (二)

日蝕攻擊的實現方式

Ken Lin
CryptoCow
13 min readJun 30, 2019

--

圖片出處:https://bitcoinmagazine.com/articles/researchers-explore-eclipse-attacks-ethereum-blockchain/

本文是日蝕攻擊(Eclipse Attacks)文章的第二篇 ,此系列是根據波士頓大學團隊的研究進行探討,瞭解中間人攻擊在區塊鏈世界的可行性 。在前一篇文章中 ,我們已經簡略地介紹了Ethereum的P2P特性 ,本文將繼續探討如何針對這些特性進行攻擊,下文中提到的dbtable等名詞都使用與前一篇相同的定義。

在撰寫此篇文章的時候,最新geth版本為1.8.0,而日蝕攻擊論文的實驗對象為geth 1.6.6 ,本文所描述的各種Ethereum環境 ,若無特別提及 ,則視作與日蝕攻擊論文一致 。

除此之外,Ethereum的重大改版在即,此文中所描述的諸多Ethereum P2P特性都可能面臨巨大的改變,請多加注意。

日蝕攻擊手法

接下來的敘述中,只要受害目標的所有TCP連線都被攻擊者佔據,我們都定義為完成日蝕攻擊

A. Monopolizing Connections — 主動佔據受害目標(victim)的連線

此攻擊的概念就是攻擊者主動去佔據受害目標的所有TCP連線。這種攻擊能夠成功的原因,是基於Ethereum節點的幾個特性:

  • 一個節點的所有TCP連線可以全部是Incoming連線,也就是由其他遠端節點發起請求所形成的連線。
  • 當一個節點重啟時,Outgoing及Incoming的連線數皆為0。
  • 當一個節點重啟時,需要一段頗長的時間才會建立起Outgoing連線。

根據論文的實驗數據顯示,在一台2 vCPU及 2GB RAM的雲端伺服器上啟動Ethereum節點,要8秒鐘之後種子運算才會開始進行,也就是8秒鐘之後才會開始嘗試進行Outgoing TCP連線。

攻擊細節如下:首先,攻擊者會產生N個節點ID,N的數量遠大於一個Ethereum節點所能允許的最大TCP連線數(maxpeers,預設25個)。接下來 ,等到受害節點重啟之後,立即以這N個節點對受害節點進行Incoming連線。當受害者的全部TCP連線都被攻擊者的Incoming連線佔據時,即完成日蝕攻擊。

論文作者嘗試了兩個實驗,在第一個實驗中,攻擊者在兩台主機上建立了1000個攻擊節點,接著重啟受害者節點再去攻擊。這個實驗重複了50次,每次都會將受害者回復到攻擊前的狀態。最後發現50次攻擊裡有49次可以完成日蝕攻擊。在失敗的那一次中,受害者節點成功建立了一條Outgoing連線。

在第二個實驗中,論文作者測試了網路延遲(latency)的影響。作者這次將受害者節點安排在距離攻擊者節點較遠的地方(受害者在新加坡,攻擊者則在紐約),接著一樣建立1000個攻擊節點,最後發現53次的攻擊裡只有43次會完成日蝕攻擊。

根據實驗結果,作者認為Ethereum節點的Incoming連線沒有限制數量是關鍵弱點所在,因此建議應該限制Incoming連線數,以保證Ethereum節點能夠進行Outgoing連線。

這一個建議已經被Ethereum社群所採納,在geth 1.8.0版本中, Incoming連線的數量變成是可以限制的,預設上限是 maxpeers/3

B. Table Poisoning — 竄改受害者的節點資訊列表

在第一種攻擊中,作者在最後提出了防禦補強的建議,假設受害者採納了這個建議,使得本機能夠限制Incoming連線數,那麼攻擊者是否仍有機會完成日蝕攻擊?

在這種前提下,作者設想了另一種可能的攻擊方式 — Table Poisoning 。在Table Poisoning這種攻擊手法中,除了主動佔據受害者的Incoming連線,攻擊者還必須設法侵佔受害者的節點資訊列表,使其列表中的大多數節點都是屬於攻擊者所控制的節點,那麼當受害者嘗試進行Outgoing連線時,仍然會連接到攻擊者的節點,藉此達成佔據其所有TCP連線的意圖,此攻擊經由以下幾個步驟完成。

首先第一步,由於攻擊者知道受害者的節點ID,攻擊者便可計算出受害者table的不同bucket中,可能會儲存哪些節點資訊(logdist函式)。由於Ethereum節點儲存方式的特性,攻擊者並不需要佔滿受害者的所有bucket,攻擊者只要嘗試佔滿受害者的最後nbucket(bucket_num從256~256﹣n),即可以極高的機率佔據其TCP連線。所以攻擊者的第一步工作,便是去算出多個匹配bucket_num的攻擊用節點ID(以下簡稱IDattack)。

可預期的是當n越大,需要越多時間去算出能夠匹配bucket_num的IDattack。

在本論文中,作者選擇n=17作為其bucket攻擊數量,總共需要計算出272個IDattack,作者使用一台MacBook Pro進行計算(CPU:i5 2.9 GH;RAM:16 GB),總共需要15分鐘去算出272個IDattack。

接下來第二步,在計算出IDattack之後,便是設法讓這些IDattack被插入到受害者的db之中。攻擊者會藉由這些IDattack發出ping訊息給受害者,受害者收到ping訊息之後,除了回應pong訊息,還會對這些IDattack進行Bonding,如此便可讓這些IDattack被插入到受害者的db之中。

在這個過程中,攻擊者每24小時便會由這些IDattack發出ping訊息給受害者,並且攻擊者也要確實回應受害者的ping訊息(返回pong)以及findnode訊息(攻擊者會返回空的neighbor訊息),如此這些IDattack便具備了快速佔據受害者table的條件(詳細內容請參考Bonding運算)。

第三步是此攻擊的最後步驟,設法讓受害者節點重新啟動。Ethereum節點重新啟動時,其table是空的 ,攻擊者在這時會不斷的藉由已經產生的IDattack發出ping訊息給受害者,由於在第二步中,我們使這些IDattack具備了快速佔據受害者table的條件,此時便可很快的佔據受害者table

Ethereum節點在啟動時,UDP監聽程序會先運作(此時就可以連接其他節點的Incoming連線,並接受其他節點傳來的ping訊息進行Bonding運算),然後才進行種子運算程序,兩個程序之間大約間隔一秒。

藉由種子運算的特性,我們可以得知,在table已存有節點資訊的情況下,種子運算並不會發生作用,也就是db中沒有任何節點資訊會轉移到table中(妨礙種子運算),如此受害者的Outgoing連線將全部連接到攻擊者的節點,到這個時候,攻擊者只要再配合Monopolizing Connections攻擊的方法想辦法佔據剩餘的Incoming連線,就有機會完成日蝕攻擊。

table的更新可能是外部觸發(Unsolicited pings,遠端節點發出ping給本機)或是自主觸發(本機的種子運算)。Table Poisoning的作用是嘗試讓自主觸發失效。

IDattack只是具備快速佔據受害者table的條件,並無法完全保證table只儲存IDattack。若是有其他誠實節點嘗試發出ping訊息給受害者,table中就有可能儲存了誠實節點。

針對這種攻擊,作者也執行了兩種實驗。第一個實驗,攻擊者先準備了一個已經運行33天的受害者(地點在紐約),此受害者的db中儲存了25580筆節點資訊,在那個時間點,這已經可以視為Ethereum全網的全部節點數量。接著作者依上述步驟開始進行攻擊,第一步和第二步各執行一次,第三步則重複執行51次,每次重複之前都會將受害者主機重新啟動。

攻擊者準備了兩台攻擊用主機,一台主機(位於波士頓)以272個IDattack傳送ping訊息給受害者,另一台主機(位於紐約)則依照Monopolizing Connections攻擊以1000個攻擊節點對受害者進行Incoming連線。在這51次的實驗裡,有49次受害者的Outgoing連線皆被攻擊者佔據(其中只有19次成功地妨礙種子運算),然而這51次中卻只有34次完成日蝕攻擊 。

為何此次攻擊的成功率明顯較為低落(比起單純Monopolizing Connections攻擊)?

作者解釋到,由於此實驗仍是使用舊版geth來進行(在他們實驗的時候,尚未發行geth 1.8.0,也就是尚未發行針對第一種攻擊進行修正的版本),為了模擬出限制Incoming連線數的效果(也就是25個TCP連線中,一部分必須是屬於Outgoing),攻擊者一開始不會積極搶佔受害者的Incoming連線,直到確認受害者建立了Outgoing連線,才會嘗試搶佔受害者的Incoming連線,而在這段等待確認Outgoing的時間,受害者可能已經連接了其他誠實節點的Incoming連線,導致日蝕攻擊無法完成。

而在第二個實驗中,作者測試了網路延遲(latency)的影響。攻擊者準備了一個已經運行1小時的受害者(地點在新加玻),此受害者的db中儲存了7000筆節點資訊。兩台攻擊用主機則與第一個實驗相同,不再贅述。第二個實驗重複了50次,最後有44次完成了日蝕攻擊,6次的失敗中,有1次是因為受害者建立了Outgoing連線,另外5次則是其他誠實節點建立了Incoming連線。

在實際應用上,Table Poisoning仍有缺陷。為了匹配某個受害者的節點ID去產生攻擊用節點ID,攻擊者需要耗費可觀的運算資源,如果攻擊者想攻擊多個不同的受害者,就必須產生大量的攻擊用節點ID,資源的消耗也會急遽增加。

針對這種資源消耗的缺陷,作者設想了另一種產生攻擊用節點ID的方式,稱之為建立尋訪表(lookup table)。

針對Table Poisoning的攻擊手法,作者建議了幾種補強方式,大致上可區分為兩種策略 — 改良節點ID的管理方式以及改良種子運算:

1. 改良節點ID的管理方式

此策略的目的在於讓攻擊者無法輕易的算出IDattack,以及讓攻擊者在同一台機器上(單一個IP)無法操縱多個不同節點ID

作者建議,應該嚴格要求同一台機器(同一個IP)只能同時與一個節點ID相關,也就是在tabledb的儲存結構,以及nieghbor訊息的結構中應該去設定這個限制。此外,為了讓攻擊者無法輕易的算出IDattack,應該要改變logdist函式的輸入參數,而尋訪運算也應該改變其運算目標。

2. 改良種子運算

作者建議,即使table不是空的,仍應執行種子運算。此外,當一個節點在重新啟動之後,在被動的執行聯結更新運算之前(由Unsolicited pings所觸發),應優先執行尋訪運算。如此以來,就可以盡量避免被攻擊用節點ID佔據。

在geth 1.8.0版,作者所建議的改良種子運算已經實作。

C. Manipulating Time — 時間操作攻擊

這個攻擊利用了Ethereum防禦重放攻擊的機制 —若是某個UDP訊息的時間戳記比節點的本機時間還要早20秒以上,該訊息將被丟棄。

攻擊者藉著操弄NTP等方式,使得受害者的本機時間總是比外界真實時間還要遲緩20秒以上(也就是比其他誠實節點遲緩20秒)。如此一來,受害者將不再理會其他誠實節點傳送過來的pongneighbor訊息,而經過數日之後,由於過期檢查機制 ,受害者的db將會清除掉所有的誠實節點。

另外,由於neighbor訊息都被丟棄,也會讓尋訪機制失去效用,導致table內的誠實節點都被清除,最後就會使得受害者節點不再儲存任何誠實節點的資訊。而相對的,因為受害者也不再理會其他誠實節點傳送過來的pingfindnode訊息,在一段時間之後,其他誠實節點也就不會再儲存受害者節點的資訊。

依據以上的敘述,作者設計了一個實驗。作者準備了一台已經運行34天的受害者節點(在紐約),接著便開始對受害者模擬NTP竄改時間攻擊(具體做法是直接改變受害者節點的本機時間),實驗進行6次,每一次受害者節點的本機時間都比真實時間延遲許多(6個不同的延遲時間:25秒,70秒,5分鐘,7分鐘,9分鐘,13分鐘),整個實驗歷時數日(從8月17日至9月4日)。實驗結果顯示,到了攻擊第3天,受害者db中紀錄的節點數量顯著的減少,而且之後便趨於平緩幾乎不再增加(從一開始的數萬個變成10幾個),而table中的數量也有一樣的變化趨勢。

雖然dbtable中的節點數量大幅減少並且幾乎不再增加,但是與受害者連接的節點數量卻呈現大幅波動,有時可以達到預設上限25個,有時又不到10個,進一步分析之後發現,這些與受害者連接的節點,極大部分不屬於geth版本,而是諸如parity,Ethereum(J)等其他Ethereum的實作版本,在實驗的最後11天裡,作者統計了與受害者連結的節點數量與類別,其中屬於geth版本僅有130個,而非geth版本的則高達64374個。

Manipulating Time攻擊能夠弱化受害者節點,使得受害者幾乎無視其他節點,也讓其他節點幾乎遺忘了受害者節點,這樣一來,就能夠以更少的資源消耗來執行Table Poisoning攻擊。

而針對Manipulating Time攻擊 ,作者建議應該改良防禦重放攻擊的方式,也就是每一個UDP消息不再以時間戳記(timestamp)進行標記,而是以隨機的nonce進行標記,當送出pingfindnode訊息時附加一個nonce,而之後送回的pongneighbor也應該附加相對應的nonce才視作合法訊息。

作者自己也坦承,這樣的改良只能保證pong或neighbor不會重放,卻無法保證ping或findnode本身重放.

以上便是波士頓大學團隊研究所提出的幾種日蝕攻擊手法,在論文中,作者還有提出一些更深入的分析及實驗,例如,怎麼樣去放大攻擊的規模,怎麼樣做出最有效率(最省成本)的攻擊。本文並未敘述這些更深入的部份,有興趣的讀者們可以閱讀原文做進一步的瞭解。

後記

由於Ethereum重大改版在即,此論文中關於Ethereum的P2P基礎都面臨資訊過期的可能,再加上還沒去實作論文中的實驗,曾經一度中斷了此文的撰寫。

在這邊必須感謝台北以太坊社群(Taipei Ethereum Meetup)的雅信以及陳品,在他們的鼓勵(督促?)之下,最終還是把這篇文章完成了。

最後,謝謝讀者們花時間閱讀本文,波士頓大學團隊的這篇日蝕攻擊論文,其內容既深且廣,若是我的文章中有描述不完整或謬誤之處,還請大家不吝指教(請來信losesong@hotmail.com),謝謝。

--

--

Ken Lin
CryptoCow

Have experience and interest in pursuing Blockchain/DevOps.