1. 程式人生 > >繼承變數覆蓋及建構函式失配,竟然會導致這些漏洞

繼承變數覆蓋及建構函式失配,竟然會導致這些漏洞

  640?wx_fmt=gif    


640?wx_fmt=jpeg  


安全,區塊鏈領域舉足輕重的話題。本期咱們聊聊由於名稱書寫、宣告語句、繼承中變數覆蓋等細節問題引起的巨大安全隱患。


「區塊鏈大本營」攜手「成都鏈安科技」團隊重磅推出「合約安全漏洞解析連載」,以講故事的方式,帶你回顧區塊鏈安全走過的歷程;分析漏洞背後的玄機。讓開發者在趣味中學習,寫出更加牢固的合約,且防患於未然。


當然,這些文章並不是專為開發者而作的,即使你不是開發者,當你讀完本連載,相信再有安全問題爆出時,你會有全新的理解。



引子: 《易》曰:‘君子慎始,差若毫釐,繆以千里。’ - 《禮記·經解》


上回講到:

機制依賴引數主導

礦工操縱投機取巧


區塊引數作為區塊屬性的資料,對於挖掘區塊的礦工來說,並不具有完全的隨機性,因此將其作為隨機數生成的依據是有侷限性和危險性的。而以太坊本身又沒有提供類似於傳統語言的rand()函式,所以隨機數生成的來源,儘量來源於區塊鏈外部或者利用新的信任模型RanDAO來完成。隨機數生成作為目前以太坊遊戲的核心,在原理的定製上直接決定了專案質量和專案壽命。


本回咱們來聊聊:

繼承變數名同實不同

建構函式名異失其義


廣義的名字,指明瞭一個特定的人或物,將其與相似的其他人或物區別開來。我們把名字作為對一個人或物的稱呼,初次瞭解人或物,我們都會先嚐試記住他們的名字。


640?wx_fmt=jpeg


計算機也是如此,在區塊鏈開發,合約的編寫當中,我們給予不同函式、不同變數以不同的名字,程式才能按照編寫的意願呼叫和執行。正確書寫名稱、正確宣告函式自然就成為智慧合約安全開發的基礎。


然而,這樣的問題在區塊鏈發展到近期依然屢次出現,導致安全事件的發生,例如Morphtoken, B2X, DoubleOrNothinglmpl等多個合約中出現的Owned合約建構函式Owned大小寫問題。


本期咱們就來聊聊由於名稱書寫,宣告語句,繼承中變數覆蓋等細節問題引起的巨大安全隱患。



01

基礎知識


Solidity中的建構函式


Solidity的使用與面向物件程式語言非常相似。建構函式(constructor)用於初始化合約物件。一個合約的建構函式的方法名與合約的名字相同,在合約建立時,

對於狀態變數的資料初始化操作是通過呼叫建構函式完成的,一般包括:設定代幣名稱、識別符號、發幣、將所有代幣傳送給owner,注意此呼叫僅存在於合約部署時。此外,合約的所有者(owner)的設定一般也放在建構函式當中。因此,建構函式相當於合約啟動的引擎


640?wx_fmt=jpeg


以太坊solidity0.4.22引入了新的建構函式宣告形式constructor(),該函式引入的目的是避免程式設計人員在編寫建構函式時的命名錯誤。


Solidity中的繼承


Solidity支援多繼承和多型,其原理是程式碼拷貝。換句話說,繼承的寫法總是能夠寫成一個單獨的合約。當一個合約從多個合約繼承時,只有一個合約(子類)會被部署到鏈上,而其他的程式碼都會被拷貝到這個單一的合約當中去。



02

因小失大


MorphToken出現的安全漏洞只是因為在建構函式中Owned大小寫沒有注意Owned寫成的owned,使owned函式失去建構函式僅在部署時才能呼叫的特殊性,導致任何賬戶都能呼叫,來實現更改owner變數,轉移合約所有權的惡性事件。攻擊者在初次刺探時可能以為要黑建構函式可能相當於打李逵,結果細看之後發現對方不過是個李鬼。


640?wx_fmt=jpeg


繼承的情況有許多種,在合約繼承中出現的漏洞是因為:子類重新定義的變數繼承父類的函式,而且還取了同樣的名字來方便理解,而其實呼叫父類函式並不會操作子類的這個變數。開發者認為函式操作的是子合約的變數,沒想到操作的父合約的變數。這個失誤還曾被當作蜜罐手段偽裝成漏洞吸引想要改變合約許可權、偷取合約內資金的玩家上鉤。



03

建構函式失配漏洞


上面講到如果建構函式在宣告時出錯,變成了一個普通函式,那麼,合約將存在重大安全風險。我們建構函式失配的情況分為兩大類:


一、建構函式名和合約名不一致


  • 案例合約:


640?wx_fmt=png


在這個合約中,ownerWallet和合約的函式名不一致,變成了普通的函式,導致使用者可以執行此函式,變成合約的owner,然後取出合約地址下的Ether。


  • 漏洞修復


Solidity 0.4.22提出了建構函式的新的寫法constructor() public {},如果可能,推薦這種寫法,如果版本低於0.4.22,那麼一定要著重檢測建構函式的名稱是否和合約名相同


二、constructor宣告形式錯誤


  • 案例合約


640?wx_fmt=png


其中,owned合約的function constructor()函式的功能是將建立者地址賦予owner,用於後續的身份驗證。但是,使用constructor宣告建構函式時,開發者錯誤的在其前面添加了一個function關鍵字,導致其變成一個名為constructor普通的函式。任意賬戶地址都可以呼叫constructor()函式,並修改owner的值,導致合約管理許可權被盜用。


  • 漏洞修復


Solidity 0.4.22 提出的新的建構函式的完整宣告形式如下,注意:constructor前無function


640?wx_fmt=png



04

合約繼承中的變數覆蓋漏洞


這裡我們拿Owned合約做一個簡單的例子。


640?wx_fmt=png


呼叫useEmergencyCode函式,只會更改TestBank合約中的owner,並不會更改Owned中的owner,onlyOwner中的owner仍是合約的部署者地址。


換句話說,TestBank合約中的owner與Owned中的owner是不一樣的兩個變數。根據上面提到的Solidity原理的解釋:對於EVM來說,每個Storage 變數都會有一個唯一標識的slot id。在這裡,雖然都叫做owner,但是從bytecode的角度來看,他們都是由不同的slot id來確定的,因此也和變數的名字沒有什麼關係。


關於Storage變數以及slot的相關知識我們也曾在漏洞連載分析第七期儲存器區域性變數未初始化中講到過,在此就不贅述。



05

失之毫釐,差之千里


正確記住對方的名字,在社交禮儀中是非常重要的一點,代表著對他人的尊重。


640?wx_fmt=jpeg


在合約編寫的過程中,規範書寫,正確宣告,辨析不同變數也是對程式碼的尊重,更是對工作的尊重。在做到這份尊重的同時,也能帶來專案質量和資金安全的提升,當大部分開發者都做到這一點,這個產業的良性迴圈也就慢慢啟動。


本回結語

藺相如,司馬相如,名相如,實不相如;

魏無忌,長孫無忌,人無忌,爾勿無忌。


引用:

[1]: Solidity原理(一):繼承(Inheritance):

https://blog.csdn.net/Programmer_CJC/article/details/80042261

[2]: 以太坊蜜罐智慧合約分析:

https://paper.seebug.org/631/

[3]: Solidity語法---以太坊智慧合約生命週期:

https://www.jianshu.com/p/61e2d9e31aab

[4]: 深入理解Solidity:

https://solidity-cn.readthedocs.io/zh/develop/solidity-in-depth.html

[5]: 注意!3份合約又存在Owner許可權被盜問題——低階錯誤不容忽視:

https://mp.weixin.qq.com/s/xPwhanev-cjHhc104Wmpug



相關閱讀:



楊霞  

成都鏈安科技CEO,創始人。電子科技大學副教授,最早研究區塊鍊形式化驗證的專家。一直為航空航天、軍事領域提供形式化驗證服務。主持國家核高基、裝發重大軟體課題等近10項國家課題。CC國際安全標準成員、CCF區塊鏈專委會委員。發表學術論文30多篇,申請20多項專利。是成都鏈安科技有限公司創始人之一,該公司專注於區塊鏈安全領域,其核心技術為形式化驗證。


640?wx_fmt=jpeg


大力戳↑↑↑  加入區塊鏈大本營讀者⑦號群

(群滿加微信 CSDN_qkldby 入群)

(內容轉載請聯絡微信:CSDN_qkldby)

(商務合作請聯絡微信:fengyan-1101)


2018 AI開發者大會

拒絕空談,技術爭鳴


2018 AI開發者大會是一場由中美人工智慧技術高手聯袂打造的AI技術與產業的年度盛會!是一場以技術落地為導向的乾貨會議!大會設定了10場技術專題論壇,力邀15+矽谷實力講師團和80+AI領軍企業技術核心人物,多位一線經驗大咖帶你將AI從雲端落地。


大會5折優惠票價進入倒計時,10月13日開啟8折購票通道。點選閱讀原文」,瞭解AI開發者大會更多資訊。


640?wx_fmt=jpeg