Toutes les vulnérabilités
CRITICALWeb3exploited in the wildcurated

WEB3-WORMHOLE-2022

Web3 · Solana · Wormhole

Résumé

On 2 February 2022, an attacker exploited the Wormhole bridge connecting Solana and Ethereum and minted about $326 million of wrapped Ether out of thin air, one of the largest DeFi hacks ever. Unlike the Ronin theft weeks later, this was a pure code bug, not a stolen key. Wormhole's Solana contract failed to properly verify the signatures that are supposed to prove a deposit really happened, so the attacker forged a deposit that never existed and told the bridge to release 120,000 ETH against it. The bridge's backer, Jump Crypto, replaced the entire $326 million the next day to keep it solvent. It is the textbook example of a [cross-chain bridge](/glossary#bridge) undone by a single missing validation check.

How it happened

A bridge like Wormhole works by locking an asset on one chain and minting a matching "wrapped" token on the other, with a set of trusted signers (Wormhole calls them guardians) attesting that the deposit is real. To mint wrapped ETH on Solana, Wormhole's contract had to confirm those guardian signatures had genuinely been verified.

The flaw was in how it confirmed that. On Solana, the program checked that the signature-verification step had run by reading a special system account (the Instructions "sysvar"), but it accepted that account as one supplied by the caller and never checked that the account's address was actually the real sysvar. The attacker simply handed it a spoofed account crafted to look like a successful verification of fabricated guardian signatures. The contract believed it, accepted a forged proof-of-deposit, and minted 120,000 wrapped ETH backed by nothing, then bridged roughly 93,750 of it back to Ethereum, draining real Ether from the reserves that backed everyone else's wrapped tokens. The fix was a single added line: reject any instruction account whose address does not match the genuine sysvar.

The aftermath

Wormhole was developed by Certus One, owned by the trading giant Jump Crypto, and Jump made the unusual decision to replace all 120,000 ETH (about $326 million) within a day to keep the bridge solvent and wrapped-asset holders whole; an on-chain message offering the attacker a $10 million whitehat bounty went unanswered. About $225 million was recovered a year later: on a February 2023 order from the High Court of England and Wales, Jump Crypto counter-exploited a flaw in Oasis, the MakerDAO front-end where the attacker had parked the funds in automated vaults, to seize them back. One uncomfortable detail: the fix had been merged to Wormhole's public code repository about 53 minutes before the attack but not yet deployed to the live network, so a public, undeployed security patch may have served as the attacker's roadmap.

Why Wormhole still matters

Wormhole reinforces that bridges are the richest honeypots in crypto and that the bug is rarely exotic, here it was forgetting to check that an account was who it claimed to be. It also teaches the deploy-gap lesson: a security fix sitting in a public repo before it reaches mainnet is an open invitation. The durable defences are specific to this class of code: validate every account and sysvar against its canonical id before trusting it, never rely on an account's position in the list, use checked loaders and declarative constraints (such as Anchor's address constraints) that fail closed, and push security patches to mainnet the moment they merge. It is a sibling of the Ronin hack, the other nine-figure bridge theft of 2022.

Comment le corriger

  • Deploy the address-validation fix to mainnet immediately and pause minting until every guardian-signature path verifies the genuine sysvar.
  • Restore solvency transparently (Wormhole was backstopped within a day) so wrapped-asset holders are not left unbacked, and trace the minted funds on-chain.
  • Audit every other place the program trusts a caller-supplied account, because this class of bug usually appears more than once.

Comment l’éviter

  • Validate every sysvar account by comparing its key to the canonical id before reading from it.
  • Verify the address and owner program of all caller-supplied accounts; never trust position in the accounts array.
  • Use checked sysvar loaders (load_instruction_at_checked, load_current_index_checked) so unverified accounts fail closed.
  • Adopt declarative account constraints (e.g. Anchor address constraints) instead of manual, omittable checks.
  • Deploy security patches to mainnet immediately on merge; a public unpatched fix is an exploit roadmap.

Références

Vulnérabilités liées

Tout Web3 →