以太坊蜜罐智能合約之神奇的邏輯漏洞區塊鏈
細數在以太合約里的神奇邏輯漏洞
神奇的邏輯漏洞
該類蜜罐合約用2012年春晚小品《天網恢恢》中這么一段表現是及其合適的:
送餐員: 外賣一共 30 元
騙子 B: 沒零的,100!
送餐員: 行,我找你 ......70!(送餐員掏出 70 給騙子 B)
騙子 A: 哎,等會兒等會兒,我這有零的,30 是吧,把那 100 給我吧!給,30!(騙子 A 拿走了 B 給送餐員的 100 元,又給了送餐員 30 元)
送餐員: 30 元正好,再見 !該類漏洞也是如此,在看起來正常的邏輯下,總藏著這樣那樣的陷阱。
1.天上掉下的餡餅:Gift_1_ETH
合約關鍵代碼如下:
三個關鍵函數功能如下:
SetPass(): 在轉賬大于 1ether 并且 passHasBeenSet 為 false (默認值就是 false), 就可以設置密碼 hashPass。
GetGift(): 在輸入的密碼加密后與 hashPass 相等的情況下,就可以取走合約里所有的以太幣。
PassHasBeenSet():如果輸入的 hash 與 hashPass 相等,則 passHasBeenSet 將會被設置成 true
如果我們想取走合約里所有的以太幣,只需要按照如下流程進行操作:
推特用戶 Alexey Pertsev 還為此寫了一個獲取禮物的 EXP。
但實際場景中,受害者轉入一個以太幣后并沒有獲取到整個智能合約的余額,這是為什么呢?
這是因為在合約創立之后,任何人都可以對合約進行操作,包括合約的創建者:
合約創建者在合約 被攻擊 前,設置一個只有創建者知道的密碼并將 passHasBeenSet 置為 True,將只有合約創建者可以取出智能合約中的以太幣。與之類似的智能合約還有 NEW_YEARS_GIFT:
2.合約永遠比你有錢
合約關鍵代碼如下:
對于 multiplicate() 而言,只要你轉賬的金額大于賬戶余額,就可以把 賬戶余額 和 你本次轉賬的金額 都轉給一個可控的地址。在這里我們需要知道:在調用 multiplicate() 時,賬戶余額 = 之前的賬戶余額 本次轉賬的金額。所以 msg.value >= this.balance 只有在原余額為 0,轉賬數量為 0 的時候才會成立。也就意味著,賬戶余額永遠不會比轉賬金額小。
3.誰是合約主人:TestBank
關鍵代碼如下:
根據關鍵代碼的內容,如果我們可以通過 useEmergencyCode() 中的判斷,那就可以將 owner 設置為我們的地址,然后通過 withdraw() 函數就可以取出合約中的以太幣。
如果你也有了上述的分析,那么就需要學習一下 Solidity 中繼承的相關知識:Solidity 的繼承原理是代碼拷貝,因此換句話說,繼承的寫法總是能夠寫成一個單獨的合約。
情況五:子類父類有相同名字的變量。 父類 A 的 test1 操縱父類中的 variable,子類 B 中的 test2 操縱子類中的 variable,父類中的 test2 因為沒被調用所以不存在。 解釋:對 EVM 來說,每個 storage variable 都會有一個唯一標識的 slot id。在下面的例子說,雖然都叫做 variable,但是從 bytecode 角度來看,他們是由不同的 slot id 來確定的,因此也和變量叫什么沒有關系。
根據樣例中的代碼,我們將合約的核心代碼修改如下:
變量 owner1 是父類 Owner 中的 owner 變量,而 owner2 是子類 TestBank 中的變量。useEmergencyCode() 函數只會修改 owner2,而非 owner1,自然無法調用 withdraw()。 由于調用 useEmergencyCode() 時需要轉作者設置的 evalue wei 的以太幣,所以只會造成以太幣白白丟失。
1.TMT觀察網遵循行業規范,任何轉載的稿件都會明確標注作者和來源;
2.TMT觀察網的原創文章,請轉載時務必注明文章作者和"來源:TMT觀察網",不尊重原創的行為TMT觀察網或將追究責任;
3.作者投稿可能會經TMT觀察網編輯修改或補充。