智能合約的漏洞與攻擊2/3-漏洞2

以太坊 ethereum andy 4年前 (2020-09-07) 1329次浏览 已收录 0个评论 扫描二维码

智能合約的漏洞與攻擊2/3-漏洞2

這是智能合約的漏洞與攻擊中,漏洞第二篇。

require()違規

require() 函數是用來驗証條件式,像是外來的輸入值或是合約的狀態變數,或是從外部合約返回的值。外來的輸入值可能是來自調用的合約或是被調用的合約。在被調用合的輸入違規的情況有兩種

  • 被調用的合約發生了bug 而產生的錯誤返回值
  • 被調用合約返回值的檢查太嚴格

發生這種情況,優先考慮是不是檢查太嚴格,如果是就把檢查的條件適當地放寬,讓外來的輸入值可以通過檢查。如果不是檢查太嚴格,就一定是外部合約的bug 所產生的輸入值,應該驗証外合約的輸入值是否有效。

寫入任意的存儲位置

只有已授權的地址才能寫入敏感的資料。如果合約內沒有正確的授權檢查,惡意的用戶就可能寫入敏感資料。但是就算在寫入敏感資料時有授權檢查,還是可能把敏感資料錯誤地複寫,像是合約的擁有者這樣的資料。要防範這種情況,不只要保護敏感資料的授權檢查,還要確保資料結構不要被其他資料複寫

錯誤的繼承順序

在 Solidity 裡可以多重繼承,如果沒有正確的了解,會導致引用不明確。這種不明確也叫做鑽石繼承問題(diamond problem),如果兩個基礎合約,有同名的函數的話,哪一個應該被優先調用?Solidity 使用 反向C3線性化 (reverse C3 linearization) 來解決這個問題,使繼承從右到左線性化,所以繼承順序很重要。建議在寫繼承順序的時候,從一般合約開始,然後再寫特殊合約,來解決這個問題。

隨意跳入函數類型的變數

Solidity 允許函數型態的變數。意思就是函數類型的變數可以分配給函數,可以像是函數一樣的被其他的函數調用。用戶不應該允許修改函數變數,但有時候這也是可以的。如果合約使用了某些組合語言指令,例如 mstore ,攻擊者也許就可以用來指向任何函數,這樣就給攻擊者有能力來中斷合約的功能,這可能讓攻擊者抽乾合約內的資金。由於行內的組合語言是訪問EVM底層的方法,所以繞過了許多重要的安全特徵。所以很重要的就是,只在有必要並且正確的理解下使用。

存在未使用的變數

雖然允許,但是最好是避免未使用的變數。未使用的變數會導致一些問題,

  • 增加計算量,不必要的燃料消費。
  • 有 bug 的跡象或是異常的資料結構
  • 降低代碼可讀性

建議從代碼裡面移除所有未使用的變數。

意外的 Ether 餘額

強制發送 ether 到合約內是可能的。所以合約內如果要求特定的餘額,表示合約容易受到攻擊。假

設有一個合約檢查一個條件,合約內存在 ether 餘的話就會禁止所有函數執行。如果惡意用戶用強制發送ether,就導致 DoS 阻斷服務,使合約不能使用。因此,不要在合約內對ether餘額使用嚴格的等於檢查。

未加密的機密

Ethereum 的智能合約代碼是可以被閱讀的。就算你的合約沒有被 etherscan 驗証檢查,攻擊者還是可以透過反組譯,甚至只是檢查交易來分析合約。

一個猜猜看遊戲的例子,一個合約用戶透過猜中內部的變數值可以贏得 ehter 。這樣的方式很容易被利用,重點是你也不應該使用。

另一個常見問題,是在 oracle 調用中使用未加密的機密資料,例如 API 密鑰。如果API密鑰可以被檢測到,有惡意的用戶,就會自己調用,或是用其他媒介調用,來消耗API調用次數,如果耗盡了調用次數,可能會返回錯誤頁面,這種情況會不會導致問題,取決於合約的結構。

錯誤的合約檢測

有些合約不希望與其他合約交互。一般防止的方式是檢查調用的地址是否有代碼存在。但是合約帳號的建構函數初始調用時不會顯示有代碼存在,從而繞過了合同檢測。

沒有阻塞的區塊鏈依賴

許多合約都依賴於限制在一段時間內的調用,但是Ethreum 可以透過發送很高 Gwei 的交易,致使在一段很長的時間內產生垃圾訊息,而且這個方式比起獎勵可能是相對便宜的。

比如, Fomo3D(一個倒數計時遊戲,最後一位投資合約的用戶會贏得彩金,但是每一位投資者都會增加一些倒數計時的時間),會由一位完全阻塞了區塊鏈一小段時間的用戶,贏得彩金。不允許其他人在倒數計時完成之前再進行投資,他就贏了。

現在的某些經記賭博合約依整於已過去的區塊hash來提供隨機數產生器RNG,這還不是最可怕的RNG來源,這些合約甚至在256個區塊之後會剪去hash值,這可能導致不派彩並返還投資。重點是這些下注只是下注,而沒有下注內容。例如說,在1號或2號或3號,這種號碼上投入金額,這種投注是沒有下注內容的。這就允許某些人,投注這些類似的投注函數,當結果不利但是經紀人還沒輸入結果判斷輸的時候,就阻斷區塊鏈,直到合約剪hash 值的動作發生,然後就能拿回投資。

不遵守標準

在開發智能合約的時候,遵守標準是很重要的。標準就是用來預防漏洞,預防導致意外情況發生。

以幣安 Binance 的原始代幣 BNB 為例,原本是以 ERC20 規格為市場,但後來指出不是完全相符於 ERC20 ,有以下三點理由:

  • 防止送出到 0x0地址
  • 禁止轉移0值
  • 成功或失敗時不返回 true 或 false

這種非標準的的實現,主要擔心的原因是,如果在智能合約中把它當成標準的 ERC20 代幣使用,它會以意外的方式表現出來,甚至導致永遠鎖定在合約中。

由於標準也不是完美的,也可能在一段時間之後過期,但是標準促進了最安全的智能合約。

參考資料
https://github.com/ethereum/wiki/wiki/Safety
https://swcregistry.io/
https://eprint.iacr.org/2016/1007.pdf
https://www.dasp.co/
https://consensys.github.io/smart-contract-best-practices/
https://github.com/sigp/solidity-security-blog
https://solidity.readthedocs.io/en/latest/bugs.html


神隊友學長Andy , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:智能合約的漏洞與攻擊2/3-漏洞2
喜欢 (0)
[[email protected]]
分享 (0)
andy
关于作者:
中年大叔,打拼 like young students.
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址