以太坊JSON-RPC接口多種盜幣揭秘之重放攻擊區(qū)塊鏈
WF曲速未來提醒:對(duì)于曾經(jīng)被盜幣,修復(fù)方案僅為:關(guān)閉對(duì)公網(wǎng)暴露的RPC接口,關(guān)閉后繼續(xù)使用節(jié)點(diǎn)中相關(guān)賬戶的節(jié)點(diǎn),可能會(huì)受到該攻擊。
交易緩存池的重放攻擊
WF曲速未來提醒:對(duì)于曾經(jīng)被盜幣,修復(fù)方案僅為:關(guān)閉對(duì)公網(wǎng)暴露的RPC接口,關(guān)閉后繼續(xù)使用節(jié)點(diǎn)中相關(guān)賬戶的節(jié)點(diǎn),可能會(huì)受到該攻擊。
在之前講到,為了實(shí)現(xiàn)攻擊者不停的發(fā)送轉(zhuǎn)賬請(qǐng)求的功能,筆者使用了while True循環(huán),并且在geth終端中看到了多條成功簽名的交易hash。由于交易緩存池?fù)碛幸欢ǖ男r?yàn)機(jī)制,所以除了第一筆交易0x4ad68aafc59f18a11c0ea6e25588d296d52f04edd969d5674a82dfd4093634f6外,剩下的交易應(yīng)該因?yàn)橘~戶余額不足而被移出交易緩存池。
但是在測(cè)試網(wǎng)絡(luò)中卻出現(xiàn)了截然不同的情況,在我們關(guān)閉本地的geth客戶端后,應(yīng)該被移出交易緩存池的交易在余額足夠的情況下會(huì)再次出現(xiàn)并交易成功:
(為了避免該現(xiàn)象的出現(xiàn),可以在成功轉(zhuǎn)賬之后利用break終止相關(guān)的循環(huán))
這個(gè)交易奇怪的地方在于:在賬戶余額不足的情況下,查找不到任何Pendding Transactions:
當(dāng)賬戶余額足夠支付時(shí),被移出交易緩存池的交易會(huì)重新出現(xiàn),并且是 Pendding 狀態(tài)。
在部分pendding的交易完成后,剩余的交易將會(huì)繼續(xù)消失。
這也就意味著,如果攻擊者能夠在利用偷渡漏洞的過程中,在交易被打包進(jìn)區(qū)塊,賬號(hào)狀態(tài)發(fā)生改變前發(fā)送大量的交易信息,第一條交易會(huì)被立即實(shí)行,剩余的交易會(huì)在受害人賬號(hào)余額大于轉(zhuǎn)賬金額 gas 消耗的金額的時(shí)候繼續(xù)交易,而且這個(gè)交易信息在大多數(shù)情況下不會(huì)被查到。
對(duì)于這個(gè)問題進(jìn)行分析研究后,我們認(rèn)為可能的原因是:以太坊在同步交易緩存池的過程中可能因?yàn)榫W(wǎng)絡(luò)波動(dòng)、分布式的特點(diǎn)等原因,導(dǎo)致部分交易多次進(jìn)入交易緩存池。這也導(dǎo)致部分應(yīng)該被移出交易緩存池的交易多次重復(fù)進(jìn)入交易緩存池。
具體的攻擊流程如下:
本地復(fù)現(xiàn)過程
對(duì)于前面講到的現(xiàn)象進(jìn)行了多方面的猜測(cè)。最終在低版本的geth中模擬復(fù)現(xiàn)了該問題。但由于現(xiàn)實(shí)環(huán)境的復(fù)雜性和不可控性,并不能確定該模擬過程就是造成該現(xiàn)象的最終原因,故該本地復(fù)現(xiàn)流程僅供參考。
攻擊復(fù)現(xiàn)環(huán)境位于私鏈中,私鏈挖礦難度設(shè)置為0×400000,保證在挖出區(qū)塊之前擁有足夠的時(shí)間檢查各節(jié)點(diǎn)的交易緩存池。geth的版本為1.5.0。
被攻擊者的節(jié)點(diǎn)A:通過geth–networkid 233–nodiscover–verbosity6–ipcdisable–datadir data0–rpc–rpcaddr0.0.0.0console啟動(dòng)。
礦機(jī)節(jié)點(diǎn)B,負(fù)責(zé)挖礦:通過geth–networkid 233–nodiscover–verbosity 6–ipcdisable–datadir data0–port30304–rpc–rpcport 8546 console啟動(dòng)并在終端輸入miner.start(1),使用單線程進(jìn)行挖礦。
存在問題的節(jié)點(diǎn) C:通過geth–networkid 233–nodiscover–verbosity 6–ipcdisable–datadir data0–port 30305–rpc–rpcport 8547 console啟動(dòng)。
各節(jié)點(diǎn)啟動(dòng)后通過admin.nodeInfo和admin.addPeer()相互添加節(jié)點(diǎn)。
1. 攻擊者掃描到被攻擊節(jié)點(diǎn)A開放了rpc端口,使用如下代碼開始攻擊:
2.節(jié)點(diǎn)A的用戶由于轉(zhuǎn)賬的需求,使用personal.unlockAccount()解鎖賬戶,導(dǎo)致偷渡漏洞發(fā)生。由于一共進(jìn)行了三次轉(zhuǎn)賬請(qǐng)求并成功廣播,所以A、B、C交易緩存池中均存在這三筆交易。
3. 由于網(wǎng)絡(luò)波動(dòng)等原因,此時(shí)節(jié)點(diǎn)C與其它節(jié)點(diǎn)失去連接。在這里用admin.removePeer()模擬節(jié)點(diǎn)C掉線。節(jié)點(diǎn)B繼續(xù)挖礦,完成相應(yīng)的交易。后兩筆交易會(huì)因?yàn)橛囝~不足從交易緩存池中移除,最終節(jié)點(diǎn)A,B的交易緩存池中將不會(huì)有任何交易。
4.上述步驟1-3即是前文說到的偷渡漏洞,被攻擊者A發(fā)現(xiàn)其節(jié)點(diǎn)被攻擊,迅速修改了節(jié)點(diǎn)A的啟動(dòng)命令,去除了–rpc–rpcaddr 0.0.0.0,避免RPC端口暴露在公網(wǎng)之中。之后繼續(xù)使用該賬戶進(jìn)行了多次轉(zhuǎn)賬。例如,使用其它賬號(hào)給節(jié)點(diǎn)A上的賬號(hào)轉(zhuǎn)賬,使的節(jié)點(diǎn)A上的賬號(hào)余額為1.980065000882e 24
5.節(jié)點(diǎn)C再次連接進(jìn)網(wǎng)絡(luò),會(huì)將其交易池中的三個(gè)交易再次廣播,發(fā)送到各節(jié)點(diǎn)。這就造成已經(jīng)移除交易緩存池的交易再次回到交易緩存池中。
6.由于此時(shí)節(jié)點(diǎn)A的賬戶余額足夠,第二個(gè)交易將會(huì)被打包進(jìn)區(qū)塊,節(jié)點(diǎn)A中的余額再次被盜。
WF曲速未來提醒:在實(shí)際的場(chǎng)景中,不一定會(huì)出現(xiàn)節(jié)點(diǎn) C 失去連接的情況,但由于存在大量分布式節(jié)點(diǎn)的原因,交易被其它節(jié)點(diǎn)重新發(fā)送的情況也是可能出現(xiàn)的。這也可以解釋為什么在前文說到:賬戶余額足夠時(shí),會(huì)出現(xiàn)大量應(yīng)該被移除的pendin交易,在部分交易完成后,pending交易消失的的情況。當(dāng)賬戶余額足夠時(shí),重新廣播交易的節(jié)點(diǎn)會(huì)將之前所有的交易再次廣播出去,在交易完成后,剩余pending交易會(huì)因?yàn)橛囝~不足再次從交易緩存池中被移除。
除了文章說到的現(xiàn)象外,亦不排除攻擊者設(shè)置了惡意的以太坊節(jié)點(diǎn),接收所有的交易信息并將部分交易持續(xù)廣播。但由于該猜想無法驗(yàn)證,故僅作為猜測(cè)思路提供。
1.TMT觀察網(wǎng)遵循行業(yè)規(guī)范,任何轉(zhuǎn)載的稿件都會(huì)明確標(biāo)注作者和來源;
2.TMT觀察網(wǎng)的原創(chuàng)文章,請(qǐng)轉(zhuǎn)載時(shí)務(wù)必注明文章作者和"來源:TMT觀察網(wǎng)",不尊重原創(chuàng)的行為TMT觀察網(wǎng)或?qū)⒆肪控?zé)任;
3.作者投稿可能會(huì)經(jīng)TMT觀察網(wǎng)編輯修改或補(bǔ)充。