尋夢新聞LINE@每日推播熱門推薦文章,趣聞不漏接❤️
針對區塊鏈安全問題,成都鏈安科技團隊每一周都將出智能合約安全漏洞解析連載,希望能幫助工程師寫出更加安全牢固的合約,防患於未然。
引子:天下難事,必作於易,天下大事,必作於細 —— 《道德經·第六十三章》
本期話題
可見修飾字斟句酌,函數調用約法三章
自由與限制,兩個矛盾又相輔相成的狀態。有人言,沒有限制的自由不是真正的自由。正如《海上鋼琴師》的台詞:「鋼琴有低音的開頭,也有高音的結束,八十八個琴鍵是有限的,卻可揮灑出無限的動人音符,我喜歡這說法,這也是我生存的方式…陸地對我而言就是一艘大船,這世界上有數以千計的街道,而你要如何走到盡頭,你要如何選擇一個妻子,一棟房子,一幅風景,甚至何種方式死去?這些在我面前就像無窮多琴鍵的鋼琴,但我卻一個音符也彈不出來…」當自由掙脫限制的束縛,會讓人感到恐懼和迷茫。
自由和限制的關係,也正是科技發展和安全的關係。合約安全的精髓就是限制及控制理念,精確的附加限制條件是防禦安全漏洞的有效手段。在函數調用權限的問題上,正確添加函數說明符或者修飾符來控制調用的範圍和權限,是協助預防攻擊者調用重要和敏感的函數的「保護傘」。
基礎知識
函數可見性說明符(Function Visibility Specifiers)和函數修飾符(Function Modifiers)都可以歸納為修飾函數的成分,為了區分我們分開講解兩個概念:
1. 什麼是函數可見性說明符(Function Visibility Specifiers)?
Solidity有兩種函數調用方式,一種是內部調用,不會創建一個EVM調用(也叫做消息調用),另一種則是外部調用,會創建EVM調用(會發起消息調用)。Solidity對函數和狀態變量提供了四種可見性。分別是external,public,internal,private。其中函數默認是public。
external
· 聲明為external的函數可以從其它合約或通過Transaction進行調用,所以聲明為external的函數是合約對外接口的一部分。
· 不能直接進行內部調用。
public
· 函數默認聲明為public。
· public的函數既允許內部調用,也允許外部調用。
· public的函數由於被外部合約訪問,是合約對外接口的一部分。
internal
· 在當前的合約或繼承的合約中,只允許內部調用。
private
· 只能在當前合約中被訪問(不可在被繼承的合約中訪問)。
· 即使聲明為private,仍能被所有人查看到里面的數據。訪問權限只是阻止了其它合約訪問函數或修改數據。
由於變量的可見性說明符與函數類似,這個特殊情況也可以造成變量的外部讀取,我們在第九期重點解析了這個問題,請移步:https://mp.weixin.qq.com/s/hP_Cc2CiqFyrnYqK9W_3nQ
2. 什麼是函數修飾符(Function Modifiers)
修飾符可以用來輕鬆改變函數的行為,比如在執行的函數之前自動檢查條件。他們可繼承合約的屬性,也可被派生的合約重寫。除了官方的一些修飾符,例如,view(函數不會更改和保存任何數據);pure(函數既不會往區塊鏈寫數據,也不從區塊鏈讀取數據)之外,我們還有自定義修飾符,用來自定義其對函數的約束邏輯。這些函數可以同時作用於一個函數,例如:
function test() external view oneModifier anotherModifier
限制缺失,函數迷失
從上面的知識我們可以總結,可見性說明符和函數修飾符直接關係到函數可以被誰調用。如果重要和敏感函數缺少相關的修飾成分,就可能淪為攻擊者不勞而獲的工具。如同各種電影動漫中神秘的力量需要被封印一樣,不能正確限制這種力量,勢必帶來無法挽回的後果。
函數調用權限漏洞
我們按照可見性說明符和修飾符將漏洞分為兩類:
1. 可見性權限漏洞
在基礎知識中我們提到,函數默認的可見性為public,允許用戶從外部調用它們。可見性說明符的不正確使用可能會導致智能合約中的資金流失:
Ø 錯誤代碼示例
函數的默認可見性是public,意味著任何人都可以操作上面的_transfer函數,做到不需要授權就可以轉走他人的代幣。
2. 調用權限不符
部分敏感函數需要onlyOwner權限,如果該函數忘記添加onlyOwner函數修飾器,那麼任何人都可以操作該函數,破壞合約執行邏輯。
Ø 錯誤代碼示例
setOwner() 函數的作用是修改 owner,通常情況下該函數只有當前 owner 可以調用。 但問題代碼中,任何人都可以調用 setOwner() 函數,這就導致了任何人都可以修改合約的 owner。 該問題本質上是函數調用權限不符的漏洞。
Ø 漏洞修復
水能載舟,亦能覆舟
做到函數重要功能的環節變為使項目功虧一簣的致命漏洞,這是所有人不願意看到的。
開發過程中準確理解函數執行的安全范疇,在充分理解智能合約知識的基礎上加以精確的權限控制,是防止合約函數功能被利用的重要舉措。同時,權限的控制需要對合約邏輯的全面理解以及細節掌握。在智能合約開發時,注意細微之處的重要權限相關問題,才能做到合約真正的自由發展。
結語:夫禍患常積於忽微,而智勇多困於所溺。
引用:
[1]: solidity中的函數修飾符
https://steemit.com/solidity/@a186r/solidity
[2]: 函數修改器(Function Modifiers)
http://www.tryblockchain.org/Solidity-FunctionModifiers-%E5%87%BD%E6%95%B0%E4%BF%AE%E6%94%B9%E5%99%A8.html
[3]: 深入理解Solidity——函數修飾符:
https://blog.csdn.net/qq_33829547/article/details/80378135
[4]: 【Solidity入門系列】函數的可見性與訪問權限控制
http://me.tryblockchain.org/solidity-function-advanced1.html
[5]: 可見性或權限控制(Visibility And Accessors)
http://www.tryblockchain.org/Solidity-VisibilityandAccessors-%E5%8F%AF%E8%A7%81%E6%80%A7%E5%92%8C%E8%AE%BF%E9%97%AE%E6%8E%A7%E5%88%B6%E5%99%A8.html
[6]: CVE-2018-10705 Detail
https://nvd.nist.gov/vuln/detail/CVE-2018-10705
(作者:成都鏈安科技,內容來自鏈得得內容開放平台「得得號」;本文僅代表作者觀點,不代表鏈得得官方立場)