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

日蝕攻擊的實現方式

Ken Lin
Ken Lin
Jun 30, 2019 · 13 min read
Image for post
Image for post
圖片出處: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),謝謝。

CryptoCow

區塊牛-區塊鏈技術共筆平台

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store