solidity智慧合約[51]-安全—dos***
Dos***
dos***也叫做拒絕服務***,通過使程式操作無效完成***的目的。
下面的一段合約是2016年KotET(“紛爭時代”)合約,其遭受了dos***。本小節將揭開此合約被***的祕密。
原始碼
在下面KotET合約程式碼中,模擬了爭奪皇位的功能。只有出價最高的人才能夠奪得桂冠。 合約中的bid方法正是最核心的競價合約。只有當msg.value即附帶的以太幣大於當前最大的出價人,就會首先將從前的最高價格轉移給從前的出價人。完成之後,新的價格和資金會替換掉舊的資金。
1 |
pragma solidity ^0.4 |
***合約
下面是******的合約。***手法為:首先部署POC合約。假設為0x3456
將Auction合約的地址傳遞給setInstance,構建auInstance介面例項。從而能夠在外部呼叫合約。執行attack方法,附帶以太坊,例如100wei。假設還沒有進行過拍賣,那麼當前的最高出價地址為當前合約,最高價格為100wei。假設有另外一個人想爭奪皇位,其出價了200wei 呼叫了Auction合約的bid方法。雖然其價格最高,但是這筆操作不能成功。原因就在於currentLeader.send(highestBid)轉賬,如果是合約地址,會呼叫合約中自定義的回撥函式,而在當前案例中的回撥函式,revert()意味著操作回滾,不成功。因此始終沒有辦法將錢還給合約,此合約將霸佔王位。
1 |
pragma solidity ^0.4.23; |
解決辦法
讓使用者自己去取錢,而不是自動的轉移資金到失敗者的賬戶中。
1 |
pragma solidity ^0.4.23; |
dos***案例2
dos***的第二個例子是,謹慎的使用迴圈。
如下,refundAll方法為動態陣列refundAddresses中每一個賬戶轉移資金。由於refundAddresses長度不確定。一旦超過了以太坊gaslimit的限制,就會導致這筆操作不能夠成功。
對可以被外部使用者人為操縱的資料結構進行批量操作,建議使用取回模式而不是傳送模式,每個投資者可以使用withdrawFunds取回自己應得的代幣。
如果實在必須通過遍歷一個變長陣列來進行轉賬,最好估計完成它們大概需要多少個區塊以及多少筆交易。
下面合約的第二個錯誤在於,一旦某一個賬戶轉賬不成功,就會導致所以交易回滾,全部失敗。
1 |
address[] private refundAddresses; |
參考資料
本文連結: https://dreamerjonson.com/2018/11/24/solidity-51-dos-attrack/
版權宣告: 本部落格所有文章除特別宣告外,均採用 CC BY 4.0 CN協議 許可協議。轉載請註明出處!