Breaking Down Web3 Vulnerabilities: A Proof of Concept Series for Ethical Hackers
Greetings, hackers!
Have you recently started delving into the world of reviewing smart contracts?
Are you among those who have just begun participating in the Code4rena challenges?
Do you find yourself struggling to develop a proof of concept for your findings?
If you answered yes to any of these questions, then this post is for you. In this POC series, we will be replicating some of the earlier discoveries made in Code4rena, which we hope will be of great assistance to you.
Let's start now.
What is reentrancy?
According to Alchemy “Reentrancy attacks occur when a smart contract function temporarily gives up control flow of the transaction by making an external call to a contract that is sometimes written by unknown or possibly hostile actors. This permits the latter contract to make a recursive call back to the primary smart contract function to drain its funds.”
Proof of concept:
Today, in this series we will look into the vulnerability which is found in the stake house contest.
You can check the project from here: https://code4rena.com/contests/2022-11-lsd-network-stakehouse-contest
Step 1: clone the repository and enter into the directory
Step 2: forge build — hh
Since this project is using hardhat, if we try to compile it with foundry it will throw an error. But the foundry has an option for “hardhat compatible” projects. That is the — hh flag. Usually, the foundry will look for contracts in /src folder. But if you use this — hh flag then it will look on /contracts folder.
Note:- Before running the above command run the “npm install @openzeppelin/contracts@<version>” cmd once, if it throws any import errors.
Now let's take a look at the vulnerable function
The function withdrawETHForKnot() allows node runners to withdraw ETH from their smart wallet and then it will ban the public key, to prevent the user from withdrawing again.
Here the marked lines are vulnerable to reentrancy. Because the code has not followed the “check effects interaction pattern”.
So, the vulnerability is, The attacker can reenter again and again before his public key is getting banned using the above line of code. We understood the vulnerability, so now it's time to write the exploit.
Step 3: Write the exploit!!!
This is the most interesting part for you all as a hacker!!!
create an exploit based on your understanding and your need. Here in the above code first, we have initialized all the required values. Then attacker will call the attack() function, which will start the attack by calling the vulnerable withdrawETHForKnot() function, then the funds will be transferred to the attacker’s contract and received using the receive() function, but then again from that “if condition” present in the receive() function, the attack() function will be called again. This is how the above exploit works.
Step 4: Verify your exploit
Before submitting any proof of concept(POC) you need to verify that it is working. To verify that write a test case in the test folder.
Run the test using the below command
forge test -vv — match-test testName
Congratulations on reproducing the issue and creating your proof of concept!
Now, it's time to take the next step and submit your discovery to the vulnerability disclosure program. By doing so, you'll be contributing to a more secure blockchain environment and enhancing the security of smart contracts. So, don't hesitate – to take action right away, and the community will appreciate your efforts.
That's all for now, but stay tuned for another excellent piece coming soon.