日蝕攻擊(Eclipse Attack)是一種針對點對點網路(p2p)特殊拓撲結構的攻擊手段。
大家都知道日蝕是一種天體物理現象,月球在白天的時候執行到地球與太陽之間,遮住太陽光,形成日蝕。日蝕攻擊取其意相,在網路中透過惡意網路連線將目標節點從網路連線環境中隔離,使目標節點無法獲取網路上的正常資料,就好像日蝕下地球無法獲取太陽光,故名“日蝕攻擊”。
針對傳統P2P網路的日蝕攻擊由來已久。而針對區塊鏈網路的日蝕攻擊首次出現於2015年的資訊保安頂級會議USNIX。波士頓大學的 Ethan Heilman在其論文 《Eclipse Attacks on Bitcoin’s Peer-to-Peer Network》中,分析了日蝕攻擊針對區塊鏈網路的手段可行性和可能造成的嚴重後果。
- 論文地址 -
https://eprint.iacr.org/2015/263.pdf
在比特幣網路中,目前理論上幾乎唯一存在的攻擊手段是51%算力攻擊,雖然這種攻擊手段在別的基於PoW共識演算法中已經被成功實施了很多次,比如以太經典的51%算力攻擊。
- 「以太經典51%算力攻擊」原文地址 -
https://bravenewcoin.com/insights/etc-51-attack-what-happened-and-how-it-was-stopped
但在比特幣網路裡卻從來沒有過被人成功實施過的跡象,畢竟花費數億美元的代價去實施攻擊,無論怎麼看都是得不償失的。但透過日蝕攻擊,攻擊者可以不對整個網路進行攻擊,而是針對特定的節點,比如攻擊交易所,這樣的攻擊成本將遠小於51%的算力需求。
在實施日蝕攻擊時,攻擊者可以向受害者發起大量的網路連線的建立請求,讓自己成為目標節點的Peer node。透過這種手段,一旦受害者所有的peer node都變成由攻擊者控制的節點,受害者在區塊鏈網路的所有input和output都將收到攻擊者的監視和控制。
一旦控制了受害者的所有區塊鏈網路通訊,攻擊者就可以攔截正常區塊鏈網路裡同步的交易,新區塊等資訊,轉而向受害者廣播自己挖出的新區塊,而由於受害者無法獲取正常網路的區塊資訊,攻擊者將不再受限於攻擊正常網路所需的51%算力,而只需要掌握比受害者多的算力即可完成攻擊過程。
針對普通節點的日蝕攻擊可使目標節點的算力無效,挖出無效區塊,相應地使自己的算力在區塊鏈網路中的佔比增加。而針對交易所的日蝕攻擊則可能透過一個單獨對交易所發起的轉賬交易或者提款交易而在交易所節點中完成雙花攻擊或者直接竊取交易所持有的加密貨幣。
來自peer node的網路封鎖
以我的瞭解來看,想發起日蝕攻擊,攻擊者就必須用自己控制的節點完全取代受害者在區塊鏈網路中的正常peer node,否則任何一個可能的連結都會使得受害者接收到正常的區塊和交易。此外,攻擊者應該有能力構建偽造的新區塊並且可以透過受害者節點的驗證,否則,僅僅是將目標節點從區塊鏈網路中隔離開來,攻擊者所能獲得的收益將無法最大化。
基於以上,我們來分析對Neo網路發起日蝕攻擊的可能性。
先來看下將Neo節點在網路上進行封鎖的可行性。關於網路部分的更多內容,歡迎閱讀《Neo從原始碼分析看網路通訊》。
-《Neo從原始碼分析看網路通訊》 -
https://my.oschina.net/u/2276921/blog/1622015
除了從Neo伺服器獲取之外,還能以主動獲取的方式來獲取網路節點,即將網路節點的請求廣播給所有與本地節點建立連線的節點,透過已連線遠端節點的節點列表來實時收集整個網路中的節點資訊。
分析Neo的網路機制,就能知道Neo在網路通訊這塊能夠直接跟目標節點建立通訊,這是一個好的開頭。接下來,再看看其存在的潛在限制,是否能透過單一節點來發起大量的網路連線以請求阻塞目標節點。
透過分析原始碼,我們在src.neo.Network.P2P.ChannelsConfig.cs 裡看到了Neo針對peer節點IP的限制,同時也有針對最大連結數量的限制。但這是好事,至少意味著隔絕節點的工作量是有上限的。
/// <summary>
/// Max allowed connections
/// </summary>
public int MaxConnections { get; set; } = Peer.DefaultMaxConnections;
/// <summary>
/// Max allowed connections per address
/// </summary>
public int MaxConnectionsPerAddress { get; set; } = 3;
但是對同一IP的連結限制也意味著沒辦法僅透過一臺機器發出大量連結請求來實施廉價高效的攻擊。從攻擊者角度來說,這很不友好。更不友好的是,Neo在初始化的時候,會先載入一個seedlist作為初始peer nodes的候選人。
- 原始碼位置 -
src.neo.Network.P2P.LocalNode.cs
private readonly IPEndPoint\[\] SeedList = new IPEndPoint\[ProtocolSettings.Default.SeedList.Length\];
而這個SeedList裡明顯不會有攻擊者的地址。
"seed1.neo.org:10333",
"seed2.neo.org:10333",
"seed3.neo.org:10333",
"seed4.neo.org:10333",
"seed5.neo.org:10333"
這裡就會出現麻煩,因為我們沒辦法在不直接攻擊目標節點或者DNS的前提下讓目標節點和這些seedlist斷開連結。
從共識入手
接下來,我們再來分析下Neo的共識機制。更詳細的內容,歡迎閱讀《Neo從原始碼分析看共識協議》。
Neo採用的是dBFT共識機制,在dBFT共識過程中,並不是所有的節點都有參與共識的資格,而是需要投票選舉出一票議員(目前還是官方指定)。一票議員的列表在每一個節點中都有備份,所以想要把自己偽造成議員是不太現實的。在共識過程中,新區塊由議員輪流化身議長主持生成,並需由超過2/3的議員驗證簽名確認後才能生效。在普通節點同步新區塊的時候,是會驗證區塊的簽名,如果簽名資料不合法,那麼新區塊就會被無情拒絕。
dBFT的這種共識結構對日蝕攻擊本身是不友好的,當然,你也可以說是更安全的。因為議長生成區塊議員進行驗證的機制本身就意味著,即使我們成功把目標節點隔離開,那麼也沒辦法生成合法的新區塊。因為攻擊者本身不是議員,沒機會生成新區塊。而且即使攻擊者是議員,又假設剛好是議長,這時候情況會稍微樂觀點,但是想要往下進展依然很難。
來自惡意議員的協助
我們假設議員裡有剛好1/3,1個議員統一協助我們發起攻擊,並且無視Neo對peer節點的一系列限制。
情況看似一片大好,我們擁有了這麼多的臥底,哪怕我們再拉一個人加入我們,我們就可以光明正大的給Neo使絆子了,但我們偏不,我們就要這種剛剛好的感覺。但是真的前景光明麼?
由於每個共識週期的區塊是在共識週期內的檢視裡生成的,所以我們可以在共識週期裡重置檢視的地方看到,對於新生成區塊其實是由一個多籤賬戶來生成的,這個多籤賬戶就是透過全體議員中超過2/3議員簽名來驗證透過的。
- 原始碼位置 -
src.neo.ledger.Blockchain.cs
public static UInt160 GetConsensusAddress(ECPoint\[\] validators)
{
return Contract.CreateMultiSigRedeemScript(validators.Length - (validators.Length - 1) / 3, validators).ToScriptHash();
}
由於我們的議員數量無法達成生成新區塊的必要條件,所以除了已有的臥底之外,我們還需要新增新議員進入我們的陣營。但是透過“合法”手段獲取新的節點似乎是一件不可能完成的任務。
首先,在Neo網路中新增新議員是需要經過選舉過程的,這個過程中的所有交易都需要經過已有的超過2/3議員的驗證才能透過,即先要透過選舉增加攻擊者的實力,才能“光明正大”地攻擊Neo。因此,對Neo網路實施日蝕攻擊似乎是不現實的。
總結
本文從Neo原始碼的角度,一方面分析了日蝕攻擊的攻擊手段和可能造成的後果,另一方面也探索了面對日蝕攻擊的時候Neo系統本身的穩固性。
本文是關於區塊鏈安全的科普性文章,部分內容可能不符合專業性,嚴謹性,酌情飲用。作者實力所限,文中難免疏漏,望不吝交流指點。