在我們寫完《以太坊defi生態當前最大的安全隱患》這篇文章後,大家對defi濫用授權的行為開始提高了重視。
其間還有不少關心資產安全的使用者來問我們一些相關事情,其中有一個問題大家最為關心,那就是:
歷史上有沒有發生過因為濫用授權引發的資產損失事件呢?
答案是,有。
這一切不僅存在理論中,它就發生在你我身邊。
我們一起回顧一個真實案例:
故事的主人公是以太坊生態中大名鼎鼎的defi專案——bancor
而一切就發生在不久前的 2020年6月16日,
看到這大家是不是會疑惑,“不久之前”、“明星專案”、“巨大漏洞”這些詞彙組合在一起必定是行業討論的熱點。但為什麼自己的腦海中沒有這件事情的任何印象呢?這樣一件巨大的安全事故好像從來沒有發生過?
先快取你的疑惑,讓我們把時間回退到2020年6月16日。
看上去很普通的一天,正如你我這些上班族一樣,bancor團隊也都在工位上照舊更新自己的bancor v0.6合約程式碼。一行又一行的程式碼,就這樣堆疊出 defi 打算聳入雲霄的新基建。
但誰也不會想到,接下來他們將為這簡單幾行程式碼,經歷驚心動魄的48小時。
在這之中,到底發生了什麼呢?
原來,bancor 團隊的合約開發者犯了一個普通程式設計師經常不在意的“小失誤”,
將一個合約轉賬操作方法的訪問許可權誤寫成了public。這一下就能帶來災難性的後果:任何人都有許可權呼叫這個方法以合約的許可權來執行“轉賬”操作。
至此,任何一個對 bancor 協議進行過無限授權的普通使用者,都只能是待宰的羔羊,在每一秒都面臨著自己地址裡的資產被他人隨意掠奪揮霍的結局,程式碼並不會同情你為資產的積累付出了多少血淚。
那麼這些使用者的資產就這樣灰飛煙滅了嗎?
萬幸,這次漏洞並沒有被駭客先發現。
bancor 團隊趕在駭客之前,搶先利用起此漏洞,緊急轉移了使用者地址中的資產,共計455,349 美元。
在接下來的時間,bancor釋出了版本更新,並於2天后的2020年6月18日,對外公佈了此次事件的始末,同時對使用者進行道歉,承認自己的巨大失誤。
在其公告中還提到,bancor在倉促轉移使用者地址上資產的過程中引起了市場的波動,並被兩個套利機器人藉此此獲利135,229 美元。bancor團隊呼籲其歸還資產,但最終的結果,我們不得而知。
在這次 defi 事件中,使用者從毫無察覺地丟幣再到毫無察覺地失而復得,既風平浪靜,又波譎雲詭。
至此,整個事件就算告一段落。
但事情應該這樣結束嗎?
瞭解完這件事情之後,普通使用者可能都會有所反思
“要為自己資產負責,警惕 defi 向自己索要無限授權”
“參與defi合約的資產最好要分開儲存”
“要定期檢查下自己有哪些過度授權”
“要......”
但仔細想來,更應該反思的不應該是各個defi專案方嗎?
但現實並未如你所想,這也正如你的困惑。
為什麼幾乎沒有 defi 專案方為此事發表討論?
為什麼生態裡的“頭部團隊們”都捂住了嘴巴?
為什麼一件巨大的安全事故最終好像從未發生?
因為幾乎所有的 defi 專案方和部分錢包團隊都在無節制的濫用授權,共同的利益使得所有知情人全部變成了沉默者。
沒有修正自身的越權行為,沒有展開對風險的思考;
轉而將使用者的質疑搪塞於各種理論,將使用者的安全寄託於各種萬幸,
但當不幸真的降臨時,誰又能站出來呢?
程式碼不會同情每個普通使用者為資產的積累付出了多少血淚,但是人類的本能會。
作為開發者、作為專案方、作為理應為安全保駕護航的錢包方,不應對濫用授權無動於衷,也不應為了自己能濫用授權就拋棄使用者安全。
要時刻記得,僅僅一個月前,大量的使用者離錢包內資產灰飛煙滅只差了一個萬幸!
位元派安全實驗室
2020年7月31日
位元派安全實驗室將持續在智慧合約安全領域投入自身的力量,為使用者安全保駕護航。
bancor案例原文:
bancor’s response to today’s smart contract vulnerability
https://blog.bancor.network/bancors-response-to-today-s-smart-contract-vulnerability-dc888c589fe4
三個問題合約程式碼:
https://etherscan.io/address/0x8dfeb86c7c962577ded19ab2050ac78654fea9f7#code
https://etherscan.io/address/0x5f58058c0ec971492166763c8c22632b583f667f#code
https://etherscan.io/address/0x923cab01e6a4639664aa64b76396eec0ea7d3a5f#code
有問題的合約方法:
function safetransferfrom(ierc20token _token, address _from, address _to, uint256 _value) public