Writeups/Ethernaut/Impersonator
HardEthernaut · Ethernaut2024

Impersonator

ECDSA Signature Malleability (High-s Value Not Enforced)

The signature validation does not enforce low-s values. For every valid `(r, s)` signature, `(r, n - s)` produces a different hash but recovers the same signer. Submitting the malleable signature as a "new" signature bypasses the `usedSignatures` replay protection and allows setting `controller` to `address(0)`.

SolidityECDSASignature Malleabilitysecp256k1ecrecover

00Overview

The signature validation does not enforce low-s values. For every valid `(r, s)` signature, `(r, n - s)` produces a different hash but recovers the same signer. Submitting the malleable signature as a "new" signature bypasses the `usedSignatures` replay protection and allows setting `controller` to `address(0)`.

01Retrieve ECLocker address from transaction logs

After calling deployNewLock(), find the ECLocker address under Topic 1 of the NewLock event on Etherscan.

02Compute the malleable s value

javascript
const n = BigInt("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141")
const new_s = n - BigInt(original_s)

03Call changeController with malleable signature

javascript
locker.changeController(v, r, bytes32(new_s), address(0))

04Open the lock as any address

javascript
locker.open(v, r, bytes32(new_s))

05Level Completed

Impersonator — completion screenshot 1
Impersonator — completion screenshot 2