當智慧合約安全遇見《海上鋼琴師》,自由與限制應是怎樣的關係?
安全是區塊鏈領域舉足輕重的話題。本期咱們聊聊,有關函式呼叫許可權引起的巨大安全隱患。
「區塊鏈大本營」攜手「成都鏈安科技」團隊重磅推出「合約安全漏洞解析連載」,以講故事的方式,帶你回顧區塊鏈安全走過的歷程;分析漏洞背後的玄機。讓開發者在趣味中學習,寫出更加牢固的合約,且防患於未然。
當然,這些文章並不是專為開發者而作的,即使你不是開發者,當你讀完本連載,相信再有安全問題爆出時,你會有全新的理解。
天下難事,必作於易,天下大事,必作於細 —— 《道德經·第六十三章》
上回書說到
邏輯判斷失誤事與願違
功能實現不周弄巧成拙
自1995年尼克薩博第一次提出智慧合約理念以來,智慧合約的功能延展越來越迅速,程式碼邏輯功能也越來越複雜。
在開發的過程中,由於欠缺全域性考慮和邏輯測試,非常容易出現邏輯判斷和功能實現的不理想,導致合約的正常功能出現異常甚至產生可以被攻擊者繞過的邏輯漏洞。
稽核程式碼的通篇邏輯或者從歷史教訓中汲取開發經驗成為規避此類漏洞最有效,可行的方案。
本期話題
可見修飾字斟句酌,函式呼叫約法三章
自由與限制,兩個矛盾又相輔相成的狀態。有人說,沒有限制的自由不是真正的自由。
正如《海上鋼琴師》的臺詞:“鋼琴有低音的開頭,也有高音的結束,八十八個琴鍵是有限的,卻可揮灑出無限的動人音符,我喜歡這說法,這也是我生存的方式…陸地對我而言就是一艘大船,這世界上有數以千計的街道,而你要如何走到盡頭,你要如何選擇一個妻子,一棟房子,一幅風景,甚至何種方式死去?這些在我面前就像無窮多琴鍵的鋼琴,但我卻一個音符也彈不出來…”
當自由掙脫限制的束縛,會讓人感到恐懼和迷茫。
自由和限制的關係,也正是科技發展和安全的關係。合約安全的精髓就是限制及控制理念,精確的附加限制條件是防禦安全漏洞的有效手段。在函式呼叫許可權的問題上,正確新增函式說明符或者修飾符來控制呼叫的範圍和許可權,是協助預防攻擊者呼叫重要和敏感函式的“保護傘”。
基礎知識
函式可見性說明符(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,仍能被所有人檢視到裡面的資料。訪問許可權只是阻止了其它合約訪問函式或修改資料。
由於變數的可見性說明符與函式類似,這個特殊情況也可以造成變數的外部讀取,我們在第九期重點解析了這個問題,請移步:外部讀取狀態變數
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
--【完】--
公眾號又又又改版了,為了不錯過第一手推送訊息,建議你按照圖片的提示,將【區塊鏈大本營】設為星標(安卓使用者設為“置頂”),標星看大圖更爽喲!
推薦閱讀
大力戳↑↑↑ 加入區塊鏈大本營讀者⑦號群
(內容轉載請聯絡微信:CSDN_qkldby)
(商務合作請聯絡微信:fengyan-1101)
免費公開課|掃碼即可報名
想學習超級賬本的同學千萬不要錯過!開課前報名可免費觀看直播和回放,課程結束後只有會員才可免費觀看回放哦