以太坊parity客戶端全版本遠端DoS漏洞分析

買賣虛擬貨幣
前言:本文由五個章節組成,分別是Parity相關介紹、UTF-8編碼是什麼、Rust危險的字串切片、漏洞分析、修復方案和總結。今天我們將由淺入深地為各位讀者展示以太坊的parity客戶端全版本遠端DoS漏洞分析。一、Parity相關介紹以太坊Parity客戶端是除Geth之外使用量最高的一款以太坊客戶端,使用的是Rust語言。

根據ethernodes最新資料顯示:以太坊parity客戶端在整個以太坊網路中佔30%,Geth客戶端佔40%。

在今年2月3日時,這款客戶端官方發表公告稱修復了一個遠端拒絕服務的嚴重漏洞,這個漏洞影響2.2.9之前的版本和2.3.2-beta之前的版本,而2.2.9和2.3.2-beta已經是最新版。從官方的通告來看,可理解為:目前這個漏洞通殺漏洞修復前的所有版本。

雖然該漏洞影響版本很多,但影響範圍有限。原因便是該漏洞需要攻擊者能夠訪問目標Parity客戶端的JSONRPC,而Parity預設是不對外開放JSONRPC埠。

該漏洞具體影響範圍可以透過FOFA統計出結果:

從上圖,我們可以看到目前公網上有1195個parity節點開放了JSONRPC埠,故該漏洞影響版本多,但影響範圍有限。

二、UTF-8編碼是什麼?

我們在研究這個漏洞之前需要了解一下UTF-8編碼,來幫助我們更好為漏洞研究做準備。

Unicode是一種字元編碼,是目前計算機行業內比較通用的一個編碼,因為Unicode把所有語言都統一到一套編碼裡,解決了行業內由於語言不一致而導致的亂碼問題。

而UTF-8(8-bit Unicode Transformation Format)是一種針對Unicode的可變長度字元編碼,又稱萬國碼。

在這篇漏洞分析中,你只需要知道以下知識點就夠了:UTF-8編碼中,一個英文字元佔一個位元組,一箇中文(含繁體)佔三個位元組。

三、Rust危險的字串切片

在上個章節中介紹了UTF-8編碼的原因是:Rust就是使用的UTF-8編碼,以太坊Parity客戶端使用的程式語言是Rust。

字串切片很好理解,就是擷取出字串中的某一段字串,不過Rust的字串切片有一個毛病:

切的是位元組,不是字元

筆者簡單來測試一下,如下圖:

透過圖片內容顯示,我們可以看到當切片str1字串的0-3個元素的時候,切出來了”DVP”3個字元,但是當切片3-6個元素的時候,如果按字元切的話應該切出來“是最棒”,但是並沒有。

為什麼會出現這種情況?

原因是Rust按位元組切片。在文章此部分之前提到過:在UTF-8中英文佔1個位元組,中文佔3個位元組,所以我們切3-6就只切出來了“是”這一個字。

這是正好3個位元組切片切到了一個完整中文字元的情況。設想一下:假如切片切的是2個位元組呢?

—  會顯示半個中文嗎?
—  答案是:當然不會了。

當切片切出來不是一個完整字元的時候,Rust不會給你切出來任何字元,而是報錯。

簡單測試一下

透過圖片我們可以看到,當切片3-5的時候程式報錯了,因為切到的不是一個完整的中文字元。

以太坊Parity客戶端正是犯了這個錯誤,這也是我們今天本文中漏洞分析的關鍵所在。

四、漏洞分析

DVP安全團隊在編寫本文時,官網沒有披露任何漏洞詳情,可能是因為一些節點還未更新到新版修復漏洞的緣故,而且檢索一番之後發現網路上也沒見到有人在討論這個漏洞,於是只能去Parity的github中翻查commit記錄,試圖找到關於這個漏洞的修復補丁,透過補丁來分析漏洞,最終我們看到了這個commit:https://github.com/paritytech/parity-ethereum/commit/3b23c2e86d09a8a8b8cd99dfa02390177498e6b7

大概看了一下,基本可以確認這就是修復補丁了,補丁中多處把字串切片換成了starts_with函式:

透過上圖,可以看到,在之前的寫法中是先把字串的0至2個元素切出來,並判斷是不是以”0x”開頭,如果長度小於2並且前兩個元素的字串不是”0x”的話就返回一個error.本文上面我們瞭解了Rust的切片是存在一定危險性的,如果被切片的字串可控的話就會導致程式報錯。

那麼,這些使用了字串切片的地方是否能被遠端利用呢?

仔細看圖可以發現,圖中被修改的兩個檔案都在rpc目錄的types目錄下,我們猜測應該是為JSONRPC介面傳來的資料定義的一些型別,圖中就有hash和uint。

再去翻查以下官方的RPC文件:

原來官方文件其實都有說明,由於json裡面只有字串和數值兩個型別,所以像integers、byte、hashes這些資料型別都是透過以0x為字首的字串形式編碼傳輸的。

根據官方文件的描述,我們測試漏洞就很方便了。在文件給的請求樣例中任意找一個引數中有0x字首的,省去了看函式呼叫鏈的時間。

這裡找了一個比較常見的eth_getTransactionByHash介面,請求方式如下:


curl --data '{"method":"eth_getTransactionByHash","params":["交易hash"],"id":1,"jsonrpc":"2.0"}' -H "Content-Type: application/json" -X POST localhost:8545

利用的話也很簡單,將”交易hash”替換為中文字串就行了,例如:

curl --data '{"method":"eth_getTransactionByHash","params":["你好DVP"],"id":1,"jsonrpc":"2.0"}' -H "Content-Type: application/json" -X POST localhost:8545

實際演示一下:


可以看到在請求介面後節點確實發生了異常並崩潰了。

五、修復方案和總結

官方的修復方案前面有提到,就是將字串[a..b]這種切片寫法全部修改掉。

不過這只是一時的修補方案,若想長久的預防此類漏洞,我們認為公鏈開發者應該要比傳統軟體開發者更瞭解語言的特性,因為很多程式碼用常規程式設計思維去看問題不大,但是語言本身可能存在一些開發者並不瞭解的特性,在特性的輔助下漏洞就產生了,之前就有公鏈使用go語言濫用make函式,而且引數控制不當,然後產生由OOM導致的拒絕服務漏洞。

故DVP安全團隊透過本期漏洞分析希望能夠藉此給大家警示,區塊鏈開發者在未來的開發之路上,需要更加了解語言的特性,這樣才能讓區塊鏈生態更加穩固、安全。


更多數字貨幣資訊:www.qukuaiwang.com.cn/news

免責聲明:

  1. 本文版權歸原作者所有,僅代表作者本人觀點,不代表鏈報觀點或立場。
  2. 如發現文章、圖片等侵權行爲,侵權責任將由作者本人承擔。
  3. 鏈報僅提供相關項目信息,不構成任何投資建議

推荐阅读

;