H4t4way's Blog

Penetration Tester | OSCP | eWPT | Brupsuite Certified | CNSS

Web3

Fallout Ethernaut Challenge

Introduction

The Ethernaut is a Web3/Solidity based wargame inspired by overthewire.org, and played in the Ethereum Virtual Machine. Each level is a smart contract that needs to be 'hacked'.


The goal of this challenge is analyze the code and to claim ownership of the contract to complete the level. We will see how to do that by interacting with a contract's ABI (Application Binary Interface).

The Challenge

The first thing we can do is to get a new istance of the smart contract. It is important to know that when we press the Get New Istance button, we are not the principal of the contract. Openzeppelin will deploy the contract and thus is the owner of the contract.

error

Analyze The Code

Now Let's jump to analyze the code and try to understand it.

Every smart contract start with the pragma directive that specify the version of the compiler that will execute the code.

After that, we can see that a Solidity library called SafeMath.sol has been imported .
In the following code, the SafeMath.sol library is used for the state variable for unisgned integer(uint256).
Open Zeppelin provides a whole set of smart contract libraries like SafeMath that allow us to safely perform mathematical operations in smart contracts.
If we look at it, there is a function that is used as constructor of the contract (very bad :( ). The constructor is executed only once and the person who uses the contract becomes the owner of the contract.

The Vulnerability

If we read the code, we see the constructor function, seems that to has the same name as the contract (very bad practise) but is not.
The constructor is named Fal1out with a 1 instead of an l. So Falloutis misspelled Fal1out, which causes the constructor function to become a public function that you can call at any time.

Bug:
If we check with the dev console, we can see that the contructor function is accessible through the ABI of the smart contracts. This is absolutely wrong, as the constructor should not be public and executable through the ABI. (Typo error of the function contructor.)
Since is a typo the constructor is a public function and anyone can call it and become the owner of the contract bacause inside the function owner == msg.sender is set , where msg.sender is the one that performs the transaction error

Since the constructor is a publicly accessible function, the vulnerability is that whoever performs a transaction and calls this function become the owner of the contract.

How can we become the owner of the contract?

As we can see, at the moment we are not the owner of the contract. To become the owner we can use the dev console, use the ABI of the smart contract and call the function Fal1out(), which assigns the owner to msg.sender.

error

After the transaction has been mined, we can see by calling the await contract.owner() function again that the address is now our account address.

error

Conslusion

KEY TAKEAWAY FROM CHALLENGE:
Always use the constructor() function when defining a constructor in your contract. The constructor is a function that gets executed only once when your contract is first deployed.
DO NOT declare a constructor function using the same name as your contract.

error