智慧合約安全——私有資料訪問

語言: CN / TW / HK

這次我們將瞭解如何訪問合約中的私有資料(private 資料)。

目標合約

話不多說,直接上程式碼

這次我們的目標合約是部署在 Ropsten 上的一個合約。 

合約地址:0x3505a02BCDFbb225988161a95528bfDb279faD6b

連結: https://ropsten.etherscan.io/...

漏洞分析

由上面的合約程式碼我們可以看到,Vault 合約將使用者的使用者名稱和密碼這樣的敏感資料記錄在了合約中,我們知道合約中修飾變數的關鍵字僅限制其呼叫範圍,這也就間接證明了合約中的資料均是公開的,可任意讀取的,將敏感資料記錄在合約中是不安全的。 

讀取資料 

首先,讓我們來學習一下solidity的 storage儲存方式:1)storage 中的資料被永久儲存。其以鍵值對的形式儲存在 slot 插槽中。

2)storage在插槽中資料從右向左排列,空間不足時,打包當前插槽,開啟下一個插槽儲存資料;儲存定長陣列(長度固定)時,陣列中每一個數據佔據一個插槽。

3)儲存變長陣列(長度隨元素的數量而改變)比較特殊,在遇到變長陣列時,會先啟用一個新的插槽 slotA 用來儲存陣列的長度,其資料儲存在另外的編號為 slotV 的插槽中。slotA 表示變長陣列宣告的位置,同時也儲存著變長陣列的長度length:length = sload(slotA)用slotV表示變長陣列資料儲存的位置(即key),index 表示 value 對應的索引下標:slotV = keccak256(slotA) + index

用 value 表示變長陣列某個資料的值:value = sload(slotV)下面我們就帶大家來讀取這個合約中的資料。首先我們先看 slot0 中的資料: 由合約中可以看到 slot0 中只儲存了一個 uint 型別的資料,我們讀取出來看一下:我這裡使用 Web3.py 取得資料,首先寫好程式

執行結果:

“7b”是16進位制數,轉換成10進位制數就是123。這裡我們就成功的去到了合約中的第一個插槽 slot0 中儲存的 uint 型別的變數 count=123 ,下面我們繼續: slot1 中儲存三個變數:u16, isTrue, owner

執行結果:

從右往左依次為owner = f36467c4e023c355026066b8dc51456e7b791d99isTrue = 01 = trueu16 = 1f = 31 slot2 中就儲存著私有變數 password 我們讀取看看

執行結果:

slot 3, 4, 5 中儲存著定長陣列中的三個元素

執行結果:

slot6 中儲存著變長陣列的長度

執行結果:

返回的結果顯示變長陣列的長度為3。我們從合約程式碼中可以看到使用者的 id 和 password 是由鍵值對的形式儲存的,下面我們來讀取兩個使用者的 id 和 password:user1

執行結果:

user2

執行結果:

這樣我們就成功的將合約中的所有資料讀取完成。由此可見,合約中的私有資料也是可以讀取的。總結大家可以看到,合約中的私有資料也是可以讀取的,所以一定不要將任何敏感資料存放在合約中哦。 如果想了解更多的智慧合約和區塊鏈知識,歡迎到區塊鏈交流社群CHAINPIP社群,一起交流學習~ 社群地址: https://www.chainpip.com/