文章目錄
- 前言
- 漏洞代碼
- 代碼審計
- 攻擊步驟
- 修復/開發建議
- 審計思路
前言
在【區塊鏈安全 | 第三十七篇】合約審計之獲取私有數據(一)中,介紹了私有數據、訪問私有數據實例、Solidity 中的數據存儲方式等知識,本文通過分析具體合約代碼進行案例分析。
漏洞代碼
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;contract Vault {// 公共變量,可以通過 getter 函數讀取// slot 0uint public count = 123;// 部署合約的地址會成為 owner// slot 1address public owner = msg.sender;// 示例布爾值和 uint16 類型變量// slot 1bool public isTrue = true;uint16 public u16 = 31;// 私有密碼變量,不能通過合約外部直接訪問// slot 2bytes32 private password;// 常量值,在部署時就固定,不可更改// 編譯時嵌入,不占 slotuint public constant someConst = 123;// 固定長度的 bytes32 數組,長度為 3// slot 3、slot 4、slot 5bytes32[3] public data;// 用戶結構體,包含用戶 ID 和密碼字段struct User {uint id;bytes32 password;}// 用戶動態數組,僅限內部訪問// slot 6User[] private users;// 映射:通過用戶 ID 查找對應的用戶結構體mapping(uint => User) private idToUser;// 構造函數,在部署時設置初始密碼constructor(bytes32 _password) {password = _password;}// 添加新用戶,自動分配 ID,并存儲在數組和映射中function addUser(bytes32 _password) public {User memory user = User({id: users.length,password: _password});users.push(user);idToUser[user.id] = user;}// 工具函數:用于計算數組中元素的 storage 位置function getArrayLocation(uint slot,uint index,uint elementSize) public pure returns (uint) {return uint(keccak256(abi.encodePacked(slot))) + (index * elementSize);}// 工具函數:用于計算映射中某個鍵的 storage 位置function getMapLocation(uint slot, uint key) public pure returns (uint) {return uint(keccak256(abi.encodePacked(key, slot)));}
}