Parity 錢包合約漏洞
還記得今年 7 月 Parity 錢包合約被找到漏洞,結果駭客偷走了將近 150,000 個以太幣,會發生是因為智能合約的 callback 裡使用了 delegatecall(msg.data),這個函數會呼叫 data 中的函數並將 msg.sender 設為原呼叫函數的地址,駭客利用這一點呼叫了 initWallet,這時你們可能會以為 Parity 應該有在 initWallet 設置條件阻擋駭客就不能呼叫,結果竟然是沒有!所以駭客就成功並改變合約的擁有者,最後再把以太幣轉走,細節的部分可以看這篇文章。
Parity 也在幾天後修復了這個問題,修復的方式就是在 init* 函數加上 only_uninitialized modifier 判斷,當 m_numOwners > 0 時這個函數就不能使用,這時應該會想說不會再有漏洞了吧,畢竟智能合約能操作以太幣,誰知道……
就在前幾天有人發布了新 issue 說他不小心刪除了錢包的合約,因為只有合約的擁有者可以刪除,那麼他到底怎麼刪除合約?可以看到錢包合約被刪除前共有兩筆交易,第一筆交易呼叫 initWallet 並將合約的擁有者設為自己。
function initWallet(address[] _owners, uint _required, uint _daylimit) only_uninitialized { initDaylimit(_daylimit); initMultiowned(_owners, _required); }
交易結果:
Function: initWallet(address[] _owners, uint256 _required, uint256 _daylimit) MethodID: 0xe46dcfeb [0]:0000000000000000000000000000000000000000000000000000000000000060 [1]:0000000000000000000000000000000000000000000000000000000000000000 [2]:0000000000000000000000000000000000000000000000000000000000000000 [3]:0000000000000000000000000000000000000000000000000000000000000001 [4]:000000000000000000000000ae7168deb525862f4fee37d987a971b385b96952
第二筆交易呼叫了 kill 函數,而 kill 函數呼叫了 suicide (selfdestruct 函數的別稱,功能是將合約程式從區塊鏈移除,並將合約剩餘的以太幣轉給參數的位置),錢包的程式就從區塊鏈上移除了。
function kill(address _to) onlymanyowners(sha3(msg.data)) external { suicide(_to); }
交易結果:
Function: kill(address _to) MethodID: 0xcbf0b0c0 [0]:000000000000000000000000ae7168deb525862f4fee37d987a971b385b96952
因為很多使用這個錢包的合約引入位置都寫死導致很多合約不能運作,在 Polkadot 裡第 451 行就將錢包合約地址寫死:
address constant _walletLibrary = 0x863df6bfa4469f3ead0be8f9f2aae51c91a907b4;
因為所有邏輯判斷都在錢包合約中,所以其他相依於錢包合約的現在以太幣都被凍結,且看起來像這樣 (無法提款):
contract Wallet {
function () payable {
Deposit(...)
}
}
Parity 官方還在了解可行的解決方案,如果想查詢自己有沒有被影響可以到這個網站。
如何預防
這次的事件 Parity 說明有兩種預防方式。一種是智能合約不該有自殺的函數,這樣即便黑客獲得了權限也無法把合約移除。一種是有新的建議及改善時,要及時更新線上的合約或是找尋線上合約可能的漏洞,因為在這問題發生前,就有網友提議在合約部屬時要自動呼叫 initWallet(pr) 加強合約的安全。
如何取得凍結的資金
目前沒有其他方式可以取得凍結的資金,只能期待未來有相關的改善建議實作在以太坊,或是以太坊實行硬分叉回復狀態到錢包合約刪除之前。
參考
原文地址:https://medium.com/taipei-ethereum-meetup/parity-%E9%8C%A2%E5%8C%85%E5%90%88%E7%B4%84%E6%BC%8F%E6%B4%9E-43ed412ebcd2
上一篇: 二进制转为十进制 C实现
推荐阅读