Web3Exploit logoWeb3Exploit
← Back to Attack Patterns
Attack pattern

Signature Verification

What is signed or verified diverges from what actually executes — via delegatecall storage overwrite, malleability, or blind signing.

Definition

Signature-verification issues occur when the payload a signer approves is not the payload that executes, or when verification can be bypassed. This includes delegatecall-based storage overwrites in multisigs, signature malleability, missing replay protection, and UIs that induce blind signing of malicious calldata.

How it works

  1. A signer approves a transaction whose surface meaning differs from its on-chain effect (e.g. a delegatecall that rewrites the multisig's own storage).
  2. Verification passes because the signatures are valid for the presented payload.
  3. Execution reinterprets or redirects the approved action — swapping the implementation, changing owners, or moving funds.

Vulnerable vs. fixed

Vulnerable: delegatecall to attacker-influenced targetsolidity
// A signed operation permits delegatecall to an arbitrary address.
// delegatecall runs foreign code in THIS contract's storage context.
(bool ok, ) = to.delegatecall(data); // 'to' can rewrite owners/implementation
require(ok, "call failed");
Fixed: constrain targets, verify effect, decode before signingsolidity
// Restrict delegatecall to a vetted allowlist and prefer plain 'call'.
require(allowlistedDelegate[to], "delegate not allowed");
(bool ok, ) = to.call(data);
require(ok, "call failed");
// Off-chain: decode and display calldata so signers approve what executes.

Detection steps

  1. Identify the sensitive value or permission the pattern can influence.
  2. Trace every path that can update or consume that value, including callbacks, routers, and privileged helpers.
  3. Reproduce the worst-case attacker flow with adversarial ordering, manipulated inputs, and maximum feasible capital.

Common signals

  • Security depends on an assumption that is not enforced by code.
  • A critical value is consumed immediately after an attacker-controlled interaction.
  • A privileged call path crosses multiple contracts without one clear authorization boundary.

False positives

  • The risky-looking operation is read-only and cannot affect settlement or authorization.
  • The value is bounded by independent checks before it moves assets.
  • All privileged entry points share the same tested guard and monitoring path.

Review questions

  • Which invariant would fail if this input or caller were attacker-controlled?
  • Can the attacker compose setup, trigger, settlement, and cleanup atomically?
  • What independent check stops the exploit if the first guard is wrong?

Defensive checklist

  • Decode and display calldata to signers; never blind-sign opaque payloads.
  • Restrict or forbid delegatecall to arbitrary targets in multisig flows.
  • Include replay protection (nonce, chainId) and reject malleable signatures.
  • Verify the executed effect matches the signed intent, not just signature validity.