Skip to content
Last updated: December 19, 2024

SCWE-018: Use of tx.origin for Authorization

Content in BETA

This content is in beta and still under active development, so it is subject to change any time (e.g. structure, IDs, content, URLs, etc.).

Send Feedback

Relationships

Description

The use of tx.origin for authorization is a security vulnerability in which a smart contract checks the origin of the transaction to determine if a user is authorized to perform an action. This approach is flawed because tx.origin can be exploited by an attacker through a chain of transactions, allowing unauthorized users to interact with the contract. An attacker could trick the contract into performing an action on behalf of the victim by utilizing another contract in the transaction chain.

Key Issues: - Allows unauthorized transactions by using the tx.origin variable instead of msg.sender. - Vulnerable to phishing and reentrancy attacks, where attackers can use contracts to impersonate the victim. - Mismanagement of roles and improper transaction flow handling.

Remediation

  • Use msg.sender instead of tx.origin: Always rely on msg.sender for authentication and authorization, as it correctly represents the immediate sender of the current call.
  • Strict validation checks: Ensure that authorization checks are done on the direct sender of the transaction, i.e., msg.sender, and not the originator.

Samples

Vulnerable Contract (Using tx.origin for Authorization)

pragma solidity ^0.8.0;

contract Vulnerable {
    address public owner;

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

    function restrictedAction() public {
        require(tx.origin == owner, "Only the owner can perform this action");
        // Action code here
    }
}
In the vulnerable contract, the authorization check uses tx.origin to validate the caller. This is a problem because if the contract is called via another contract, tx.origin will return the original transaction sender (not the immediate caller), which opens up the contract to attacks such as phishing. The attacker can create a contract that interacts with the vulnerable contract on behalf of the victim.

Fixed Contract (Using msg.sender for Authorization)

pragma solidity ^0.8.0;

contract Secure {
    address public owner;

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

    function restrictedAction() public {
        require(msg.sender == owner, "Only the owner can perform this action");
        // Action code here
    }
}
In the fixed contract, msg.sender is used instead of tx.origin. This ensures that the contract checks the immediate sender of the call, which prevents attacks where malicious contracts impersonate the victim.