以太坊JSON-RPC接口多種盜幣揭秘之知識篇區塊鏈
WF曲速未來表示:以太坊,作為區塊鏈2.0時代的代表,通過智能合約平臺,解決比特幣拓展性不足的問題,在金融行業有了巨大的應用。
前面寫的話:
以太坊,作為區塊鏈 2.0 時代的代表,通過智能合約平臺,解決比特幣拓展性不足的問題,在金融行業有了巨大的應用。
通過智能合約進行交易,不用管交易時間,不用管交易是否合法,只要能夠符合智能合約的規則,就可以進行無限制的交易。在巨大的經濟利益下,總會有人走上另一條道路。
在2018年6月29日,以太坊黑色情人節事件(即偷渡漏洞)新型攻擊手法被發現。該攻擊手法在本文中亦稱之為:離線攻擊。在結合蜜罐數據復現該攻擊手法的過程中發現,在真實場景中,還存在另外兩種新型的攻擊方式:重放攻擊和爆破攻擊,由于此類攻擊方式出現在偷渡漏洞曝光后,我們將這些攻擊手法統一稱為后偷渡時代的盜幣方式。
下面將會在介紹相關知識點后,針對偷渡漏洞及后偷渡時代的盜幣方式,模擬復現盜幣的實際流程,對攻擊成功的關鍵點進行分析。
關鍵知識點
1.1 RLP 編碼
RLP(遞歸長度前綴)從名字可以看出它的特點:一個是遞歸,被編碼的數據是遞歸的結構,編碼算法也是遞歸進行處理的;二是長度前綴,也就是RLP編碼都帶有一個前綴,這個前綴是跟被編碼數據的長度相關的,RLP提供了一種適用于任意二進制數據數組的編碼,RLP已經成為以太坊中對對象進行序列化的主要編碼方式。
RLP編碼會對字符串和列表進行序列化操作,具體的編碼流程如下圖:
在此,也以3.4.1節中eth_signTransaction接口返回的簽名數據為例,解釋該簽名數據是如何經過tx編碼后得到的。
根據RLP編碼的規則,我們對tx字段當作一個列表按順序進行編碼(hash 除外)。由于長度必定大于55字節,所以采用最后一種編碼方式。
暫且先拋開前兩位,對所有項進行RLP編碼,結果如下:
合并起來就是:
一共是214位,長度是107比特,也就意味著第二位是0x6b,第一位是0xf7 len(0x6b)=0xf8, 這也是最終raw的內容:
1.2 keystore 文件及其解密
keystore文件用于存儲以太坊私鑰。為了避免私鑰明文存儲導致泄漏的情況發生,keystore文件應運而生。讓我們結合下文中的keystore文件內容來看一下私鑰是被如何加密的:
在此,將結合私鑰的加密過程說明各字段的意義:
加密步驟一:使用aes-128-ctr對以太坊賬戶的私鑰進行加密
開頭那里已經說到,keystore文件是為了避免私鑰明文存儲導致泄漏的情況發生而出現的,所以加密的第一步就是對以太坊賬戶的私鑰進行加密。這里使用了aes-128-ctr方式進行加密。設置解密密鑰和初始化向量iv就可以對以太坊賬戶的私鑰進行加密,得到加密后的密文。
keystore文件中的cipher、cipherparams、ciphertext參數與該加密步驟有關:
加密步驟二:利用kdf算法計算解密密鑰
經過加密步驟一,以太坊賬戶的私鑰已經被成功加密。我們只需要記住解密密鑰就可以進行解密,但這里又出現了一個新的問題,解密密鑰長達32位且毫無規律可言。所以以太坊又使用了一個密鑰導出函數(kdf)計算解密密鑰。在這個keystore文件中,根據kdf參數可以知道使用的是scrypt算法。最終實現的效果就是:對我們設置的密碼與kdfparams中的參數進行scrypt計算,就會得到加密步驟 1中設置的解密密鑰.
keystore文件中的kdf、kdfparams參數與該加密步驟有關:
加密步驟三:驗證用戶密碼的正確性
假設用戶輸入了正確的密碼,只需要通過步驟一二進行解密就可以得到正確的私鑰。但我們不能保證用戶每次輸入的密碼都是正確的。所以引入了驗算的操作。驗算的操作十分簡單,取步驟二解密出的密鑰的第十七到三十二位和ciphertext進行拼接,計算出該字符串的sha3_256的值。如果和mac的內容相同,則說明密碼正確。
keystore文件中的mac參數與該步驟有關:
綜上所述,要從keystore文件中解密出私鑰,所需的步驟是:
流程圖如下:
1.3 以太坊交易的流程
根據源碼以及網上已有的資料總結了以太坊的交易流程如下:
1.用戶發起轉賬請求。
2.以太坊對轉賬信息進行簽名
3.校驗簽名后的信息并將信息加入交易緩存池 (txpool)
4.從交易緩存池中提取交易信息進行廣播
對本文來說,步驟2:以太坊對轉賬信息進行簽名對于理解3.4節利用離線漏洞進行攻擊十分重要。
從上文中我們可以知道,私鑰已經被加密在keystore文件中,所以在步驟2進行簽名操作之前,需要將私鑰解密出來。在以太坊的操作中有專門的接口用于解鎖賬戶:personal.unlockAccount
在解鎖對應的賬戶后,我們將可以進行轉賬操作。在用私鑰進行簽名前,存在一些初始化操作:
這里可以注意一點:Transaction結構體中是不存在from字段的。這里不添加from字段和后面的簽名算法有著密切的關系。
使用私鑰對交易信息進行簽名主要分為兩步:
對構造的列表進行RLP編碼,然后通過sha3_256計算出編碼后字符串的hash值。
由于以太坊的地址是公鑰去除第一個比特后經過sha3_256加密的后40位,所以在交易信息中不包含from的情況下,我們依舊可以知道這筆交易來自于哪個地址。這也是前文說到Transaction結構體中不存在from的原因。
在簽名完成后,將會被添加進交易緩存池(txpool),在這個操作中,from將會被還原出來,并進行一定的校驗操作。同時也考慮到交易緩存池的各種極端情況,例如:在交易緩存池已滿的情況下,會將金額最低的交易從緩存池中移除。
最終,交易緩存池中存儲的交易會進行廣播,網絡中各節點收到該交易后都會將該交易存入交易緩存池。當某節點挖到新的區塊時,將會從交易緩存池中按照gasPrice高低排序交易并打包進區塊。
所謂磨刀不誤砍柴功,只有清楚地掌握了關鍵知識點,才能在理解下面的漏洞原理時游刃有余。
1.TMT觀察網遵循行業規范,任何轉載的稿件都會明確標注作者和來源;
2.TMT觀察網的原創文章,請轉載時務必注明文章作者和"來源:TMT觀察網",不尊重原創的行為TMT觀察網或將追究責任;
3.作者投稿可能會經TMT觀察網編輯修改或補充。