今天,我們繼續介紹文獻中提到的以太坊合約的安全性弱點與案例。
資料保密
solidity 智慧型合約中的變數分 public 和 private 兩種。private 變數表示這個數值不能被其他合約直接讀取。
但是,將乙個變數標記為 private 不意味著裡面的資訊就是保密的。因為以太坊是公開的,每次合約函式執行的位元組碼,引數都是公開的,任何人都可以推斷出每次函式執行後是否修改了變數,修改後的數值是多少。private 只是能夠保證其他合約執行的時候,無法讀取其中的變數罷了。
然而,一些本應該隱藏玩家資料的遊戲,卻錯誤地使用了這一點。以下是乙個示例:
兩個玩家在玩乙個賭博遊戲,每個玩家選乙個正整數,兩個正整數加起來的奇偶性,決定了獲勝者。
儲存玩家選擇的變數是 players, 這個變數具有 private 屬性。玩家通過呼叫智慧型合約函式選數的時候,決策並不是保密的。
為了實現保密性,更好的方式是使用乙個稱為「委託」的密碼學原語。當玩家需要秘密地做出乙個決定時,可以將 sha3(決策內容,隨機數) 得到的雜湊值存到合約裡。當玩家需要公開自己選擇的時候,將 決策內容 與 隨機數 公開,並由智慧型合約驗證雜湊值與先前儲存的是否一致。可以實現類似於「先在紙上秘密寫下選擇,到後面乙個環節再亮出來」的功能。
隨機數生成
evm 的位元組碼執行是確定性的。因此,如果智慧型合約想生成乙個隨機數,就需要通過乙個隨機數種子生成乙個偽隨機數。而隨機數種子的選取方式,對生成隨機數的公平性有很大的影響。
乙個常用的做法是,使用乙個給定時間或給定高度區塊的雜湊值或時間戳。這件事情在給定區塊被確認以後,在每個礦工看來都是一樣的。
看起來這是乙個公平的做法,因為沒有人能**未來的區塊。但是,乙個惡意的礦工可能嘗試操縱自己生成的區塊來影響隨機數的生成與合約的執行結果。乙個分析表示,乙個控制少數算力的礦工,只需要投入 50 個位元幣就可以顯著地改變輸出結果的概率分布。
另乙個方式是使用「延時委託協議」。在這個協議中,每個參與者選擇乙個秘密的隨機數,並將雜湊值廣播給其他人。在晚些時候,所有參與者公布它們選取的秘密隨機數,或者丟失押金。最終隨機數由所有公布的秘密隨機數和乙個公開的演算法生成。攻擊者可以在「其他所有人都已經公布了隨機數,自己還沒有公布」時,預先計算最終生成的隨機數,如果生成的結果它不滿意,就通過拒絕公布自己選擇的隨機數方式,來使這個結果無效。當然,攻擊者要損失一些押金。所以,押金的設定要足夠高,高於隨機數生成中改變結果可能帶來的收益。
不可**狀態
乙個合約的狀態包括合約變數和合約餘額。一般情況下,當使用者通過一筆交易呼叫合約函式的時候,從交易廣播到交易被加入區塊之間,可能有其他的交易改變了合約的狀態。也就是說,當使用者發起一筆交易時,並不能確定這筆交易被執行時,合約的狀態是什麼。
乙個基於 library 和不可**狀態的攻擊
下面我們來看乙個例子,以下的 solidity **定義了乙個名為 set 的 library。
下面是乙個名為 setprovider 的合約,提供了乙個 set library 的位址,合約擁有者可以修改這個位址,任何人/合約可以獲取這個位址。
假設 bob 合約是乙個使用 setprovider 的誠實使用者,他的**如下:
bob 記錄了乙個 setprovider 合約的位址,在 getsetversion() 中,使用這個位址獲取了乙個 set library 的版本號。
現在,假設 setprovider 合約的控制者是個壞人。他製造了乙個惡意的 set library, 希望偷得一些錢存到他自己的錢包位址 0x42 中。
如果合約 setprovider 中 setlibaddr 的位址被修改為 maliciousset 的位址, bob 合約中呼叫 getsetversion() 函式時,會呼叫 maliciousset 的 version() 函式,而不是 set 的。因為 bob 合約中將 set 宣告為乙個 library, 所以對 version() 的呼叫採用的是 delegatecall 模式。 delegatecall 模式意味著轉賬操作 attackeraddr.send(this.balance); 是從 bob 合約中轉賬出來。 bob 合約中的錢將被偷走。
上述例子說明了,對 library 函式的呼叫使用的是較為危險的 delegatecall 模式。因此合約編寫者在使用其他合約位址作為 library 時,一定要保證通過 library 載入進來的**是自己可控的。比如,手動指定乙個已經在區塊鏈上不可修改的 library 的位址。而不是在本例中依靠於乙個不可靠的 setprovider 合約來獲取 library 的位址。
另外,「不可**狀態」問題也加劇了這件事情。即使在呼叫 bob 合約的 getsetversion() 函式時, setprovider 指向的是誠實的 set library. 攻擊者也可以在這一交易還沒有被加入區塊的時候,通過發起一筆交易費數額較大的交易,搶在 getsetversion() 被加入區塊之前,將 setprovider 的指向修改為 maliciousset。
以太坊智慧型合約安全
智慧型合約就是自主執行的合約,其條款是用 規定的。雖然這個概念已經存在一段時間了,但至少從1996年nick szabo提出了這一概念以來,直到圖靈完備的以太坊區塊鏈來臨,智慧型合約的使用才變得普遍。對智慧型合約理念的字面解釋造成了 即法律 code is law 的正規化理解,意思是那些智慧型合約...
智慧型合約 以太坊
智慧型合約是執行在可複製 共享的賬本上的電腦程式,可以處理資訊,接收 儲存和傳送價值。2.1 什麼是以太坊 以太坊 ethereum 是乙個分布式計算機,有許多的節點,其中的每乙個節點都會執行智慧型合約,然後把結果存在區塊鏈上。由於整個網路是分布式的,且應用就是乙個個的狀態組成,儲存了狀態就有了服務...
以太坊和智慧型合約
1 什麼是以太坊?以太坊的官方 告訴我們 以太坊是乙個執行著智慧型合約的分布式平台 應用程式完全按照程式執行,不存在故障 審查 欺詐或第三方干預的可能性 2 智慧型合約就是可以處理資金的指令碼。開發語言 solidity 整合開發工具ide remix,乙個基於瀏覽器的整合開發環境 開發框架 tru...