4. Side Entrance

https://www.damnvulnerabledefi.xyz/challenges/side-entrance/

Objective

  • A surprisingly simple pool allows anyone to deposit ETH, and withdraw it at any point in time.

  • It has 1000 ETH in balance already, and is offering free flash loans using the deposited ETH to promote their system.

  • Starting with 1 ETH in balance, pass the challenge by taking all ETH from the pool.

Approach

  • flashLoan function checks the ETH balance of the contract via address(this).balance;

  • however, the balances could be accorded to different addresses as per the mapping balances

  • This means that ownership of the balances, as per balances is not taken into account.

  • This can be achieved by nested a call to deposit() within the external execute() call

Solution

Since the lendingPool contract calls .execute we need to create an attacker contract with such a function. The flash loan will be initiated from such a contract.

  • flashLoan is initiated with attack()

  • within the flash loan, execute is called on the caller contract (Attacker)

  • execute calls deposit -> this updates the balances mapping, incorrectly reflecting that the attacker has ETH balances of the flash loan amount

  • On returning the flashloan, the balances mapping remains incorrectly updated.

  • Attacker is able to withdraw ETH that did not originally belong to him, draining the contract

    • the fallback function is required to collect the ETH balances on withdrawal

    • without the fallback function, the sending of ether would revert

The tests in the foundry version checks that the attacker's wallet have received the ETH. Therefore we need to modify the attack contract to push out the ether recieved to msg.sender. Like so:

So we will add a call to transfer ether to msg.sender("attacker") within the attack() fn in Attacker Contract:

Please note that this is unsafe for production use as anyone can then call attack as it is an unguarded external function.

Proper process would dictate usinga onlyOwner modifier at least.

Last updated