Wormhole Bridge Hack: Analisi Tecnica dell’Exploito da $326M
Il 2 febbraio 2022, il bridge token Wormhole ha perso 120.000 wETH — circa 326 milioni di dollari all’epoca — in quello che rimane uno dei più grandi exploit di smart contract nella storia della DeFi. L’attacco non ha richiesto chiavi rubate, social engineering o il controllo della maggioranza della rete di validatori Guardian. È stata necessaria una sola cosa: una API deprecata del programma Solana che non verificava da quale account stesse leggendo.
Comprendere questo exploit è essenziale per ogni team che costruisce su Solana, ogni protocollo che si affida a comunicazioni cross-chain e ogni auditor che revisiona programmi Solana. La causa principale è stata una falla nella verifica dello smart contract nel programma Wormhole su Solana — non una compromissione di chiavi, né un errore della rete Guardian. Le chiavi Guardian non sono mai state toccate. È stato il codice stesso del bridge a concedere all’attaccante un’autorizzazione che non avrebbe mai dovuto concedere.
Qual era la vulnerabilità tecnica principale nell’hack di Wormhole?
La vulnerabilità risiedeva nell’istruzione verify_signatures del programma bridge Solana di Wormhole (bridge.so). Questa funzione era responsabile di verificare che un account SignatureSet — contenente firme Ed25519 o Secp256k1 dei nodi Guardian — rappresentasse un consenso autentico prima di autorizzare una Verifiable Action Approval (VAA).
La falla: verify_signatures usava la funzione deprecata solana_program::sysvar::instructions::load_instruction_at per verificare che nell’ambito della stessa transazione fosse stata eseguita un’istruzione di pre-verifica Secp256k1. La variante deprecata non convalida però che l’account passato sia effettivamente il sysvar delle istruzioni di Solana (Sysvar1nstructions1111111111111111111111111). Essa legge qualunque account si trovi all’indice nominato — inclusi account interamente controllati dal chiamante.
Un attaccante può quindi fornire un account falsificato che imita la struttura del sysvar delle istruzioni, pre-compilato con dati di firma controllati dall’attaccante su un payload scelto dall’attaccante stesso. La funzione legge i dati falsi, trova la chiamata Secp256k1 “presente” (in un contesto completamente diverso), marca il VAA come approvato dai Guardian e restituisce successo.
Con in mano un VAA approvato fraudolentemente, l’attaccante ha invocato complete_wrapped, che si fida dell’approvazione VAA del programma bridge per autorizzare la mint di asset wrapped su Solana. Il risultato: 120,000 wETH mintati senza nessun ETH corrispondente bloccato su Ethereum.
Una correzione — sostituendo load_instruction_at con load_instruction_at_checked, che impone che l’account sia effettivamente il sysvar delle istruzioni — era stata già commessa nel repository GitHub di Wormhole prima dell’exploit, ma non era ancora stata distribuita sulla mainnet.
| Fattore | Descrizione | Impatto |
|---|---|---|
API sysvar deprecata |
load_instruction_at senza variante _checked; nessuna verifica del proprietario sull’account passato all’indice nominato |
L’attaccante può fornire un account istruzione falso al posto del vero sysvar delle istruzioni |
Bypass di verify_signatures |
Funzione che accettava un SignatureSet creato dall’attaccante come prova del consenso Guardian senza validare la provenienza dell’account |
Autorizzazione a mintare concessa senza firme Guardian reali |
Mancata verifica del proprietario account |
Account SignatureSet non validato come proprietà del programma sysvar istruzioni (Sysvar1nstructions11...) |
Questa mancanza è la base stessa dell’exploit |
Autorità di minting degli asset wrapped |
Il programma bridge Solana deteneva autorità illimitata di minting sui token wrapped; era richiesta solo un’autorizzazione VAA marcata come approvata | 120,000 wETH mintati su Solana senza ETH bloccati su Ethereum; valore di circa 326M$ al momento dell’attacco |
In cosa si differenzia l’exploit Wormhole dagli altri attacchi a bridge come Ronin?
L’hack al bridge Ronin (marzo 2022, ~625M$) è spesso citato insieme a Wormhole nelle discussioni sulle falle di sicurezza nei bridge. Sono modalità di fallimento fondamentalmente differenti.
Wormhole è stato un bug di verifica dello smart contract nel programma bridge su Solana. La rete Guardian — uno schema a firme di soglia con 19 nodi — non è mai stata compromessa. L’attaccante l’ha aggirata completamente sfruttando il fatto che verify_signatures non controllava da quale account stesse leggendo. Le chiavi Guardian erano intatte, la rete era operativa, ma tutto era irrilevante: il codice non consultava mai il consenso reale dei Guardian.
Ronin è stato un furto operativo di chiavi. Sky Mavis gestiva cinque dei nove nodi validatori di Ronin. Nel novembre 2021, Axie DAO ha delegato temporaneamente a Sky Mavis l’autorità di firma per gestire il carico delle transazioni. La delega non è mai stata revocata alla sua scadenza. Un attaccante — poi attribuito al Lazarus Group — ha compromesso i sistemi interni di Sky Mavis e ottenuto l’accesso a quattro chiavi validator di Sky Mavis. Usando la delega Axie DAO tuttora attiva, ha acquisito la quinta firma tramite il nodo RPC senza gas di Sky Mavis. Con cinque firme valide su nove, hanno inviato messaggi di prelievo legittimi al contratto bridge di Ronin. Non è stato sfruttato alcun bug nello smart contract. Il bridge ha effettuato esattamente quello per cui era stato progettato, quando ha ricevuto cinque firme genuine di validatori — ha autorizzato i prelievi.
| Wormhole (Feb 2022) | Ronin (Mar 2022) | |
|---|---|---|
| Vettore d’attacco | Bypass verifica account del programma Solana | Social engineering e compromissione credenziali nodi Sky Mavis |
| Metodo exploit | Account SignatureSet falsificato via API sysvar deprecata |
Prelievi firmati legittimamente con chiavi validate rubate |
| Rete Guardian / validatori | Integra; bypassata dal codice, non dall’attaccante | Compromessa — attaccante con 5 chiavi su 9 validatori |
| Metodo impatto | Mint non autorizzato su Solana senza ETH bloccati su Ethereum | Prelievo diretto dal contratto Ronin con firme valide |
| Quantità rubata | ~$326M (120.000 wETH) | ~$625M (173.600 ETH + 25,5M USDC) |
| Lezione di sicurezza | La validazione della proprietà degli account è imprescindibile nei programmi Solana; le firme di soglia funzionano solo se il bridge legge effettivamente tali firme | Gli schemi a firma di soglia non difendono dalla compromissione di chiavi di maggioranza; la revoca della delega deve essere rigorosamente applicata |
Passo per passo: come si è svolto l’exploit Wormhole
-
Falsificazione account. L’attaccante ha creato un account Solana che imitava la struttura attesa nella posizione
SignatureSetnei dati dell’istruzione del programma bridge Wormhole. Questo account conteneva firme controllate dall’attaccante — firme Ed25519/Secp256k1 valide, ma su un payload VAA scelto dall’attaccante, che autorizzava il mint di 120.000 wETH all’indirizzo Solana dell’attaccante. -
Bypass tramite API sysvar deprecata. L’attaccante ha inviato una transazione chiamando
verify_signaturessul programma bridge Solana di Wormhole. Il programma ha invocatoload_instruction_at— la variante deprecata e non controllata — per confermare che una istruzione Secp256k1 fosse stata chiamata precedentemente nella stessa transazione.load_instruction_atlegge qualunque account si trovi all’indice nominato senza verificarne l’identità come sysvar istruzioni reale (Sysvar1nstructions1111111111111111111111111). -
Prova falsificata accettata.
verify_signaturesha esaminato le firme nell’account controllato dall’attaccante, le ha trovate validamente criptografiche (l’attaccante le aveva firmate lui stesso, sul proprio payload) e ha marcato il VAA come approvato dai Guardian. La rete Guardian non è mai stata consultata. -
Minting autorizzato. L’attaccante ha invocato
complete_wrappedcon il VAA ora approvato. Il programma bridge, fidandosi dello stato di approvazione del VAA, ha mintato 120.000 wETH su Solana all’indirizzo dell’attaccante. -
Estrazione cross-chain. L’attaccante ha bridgato i wETH mintati di nuovo su Ethereum attraverso il flusso cross-chain legittimo di Wormhole — i wETH esistevano nel wallet Solana dell’attaccante, quindi il bridge ha processato il prelievo come un trasferimento normale. I 326 milioni di dollari in wETH non garantiti sono così arrivati su Ethereum, dove l’attaccante li ha convertiti in ETH e stablecoin, per poi uscire dal sistema. Jump Crypto, società madre di Wormhole, ha rimpiazzato i 120.000 ETH rubati dai propri riserve per risarcire gli utenti del bridge.
Lezioni tecniche più critiche per programmi Solana e bridge cross-chain
1. Ogni AccountInfo passato a un programma Solana è potenzialmente controllato dall’attaccante finché non si dimostra il contrario.
Questa è la regola fondamentale per la sicurezza dei programmi Solana. Un programma deve validare i campi owner, key e — dove applicabile — executable e is_signer di ogni account che riceve. La funzione deprecata load_instruction_at accettava qualunque account piazzasse all’indice nominato. La sostituzione moderna, load_instruction_at_checked, impone che l’account sia effettivamente il sysvar delle istruzioni prima di leggerlo. La metodologia di audit di Soken per Solana segnala qualunque uso di API sysvar non-_checked come finding Critico, indipendentemente dal contesto.
2. Separazione dei privilegi tra verifica della firma e minting degli asset.
L’autorità di minting di un bridge deve essere separata dietro un modulo di verifica che ricalcola la prova da uno stato canonico di proprietà del programma — non da account forniti dal chiamante. Quando verify_signatures accettava un account controllato dall’attaccante come fonte di verità, la separazione fra “il network ha approvato?” e “possiamo mintare?” crollava completamente. L’istruzione di mint dovrebbe derivare l’autorizzazione da uno stato che il programma stesso ha scritto dopo aver verificato input reali dei Guardian.
3. La protezione da replay delle VAA deve essere enforced on-chain.
Anche se il SignatureSet fosse stato autentico, complete_wrapped dovrebbe rifiutare VAAs il cui hash è già stato consumato. Wormhole ha aggiunto la protezione replay nelle versioni successive, ma la sua assenza nella versione sfruttata permetteva di riutilizzare ripetutamente un VAA approvato fraudolentemente. Ogni azione del bridge dovrebbe essere soggetta a una mappatura processed_vaas: mapping[bytes32, bool] aggiornata in modo atomico all’inizio dell’esecuzione.
4. L’uso di API deprecate è un finding critico in audit.
La vulnerabilità di Wormhole era causata da una deprecazione nota. Il SDK Solana aveva segnalato load_instruction_at come deprecata e fornito la sostituzione _checked prima dell’exploit. La mancata migrazione da un’API deprecata non è una semplice questione di qualità del codice — è una lacuna critica di sicurezza che gli attaccanti cercano attivamente leggendo changelog e confrontando commit non deployati con bytecode in produzione. Gli audit Solana devono controllare a fondo solana_program::sysvar::instructions::* per varianti non-_checked e segnalare qualsiasi corrispondenza come fallimento critico. Questa è prassi standard nei audit Solana post-2022, fra cui Ottersec, Halborn e Soken.
5. Le correzioni di sicurezza non deployate diventano mappe d’attacco pubbliche.
La fix load_instruction_at_checked era stata commessa nel repository pubblico di Wormhole prima dell’exploit. Un attaccante sofisticato che monitora i repository di protocolli target per commit di sicurezza — specialmente quelli che sostituiscono API deprecate con equivalenti checked — può ricostruire la vulnerabilità semplicemente dal diff. Le pipeline di distribuzione per programmi critici in sicurezza devono trattare il divario tra “merged in main” e “deployato su mainnet” come una finestra di esposizione attiva. Le procedure di deploy di emergenza dovrebbero chiudere questa finestra in poche ore, non giorni.
6. Le multisig a soglia non compensano i fallimenti nella validazione degli account.
La rete Guardian di Wormhole consisteva di 19 nodi indipendenti con uno schema a firme di soglia. Era robusta. Era completamente irrilevante per questo attacco. L’exploit ha aggirato l’intero livello di consenso manipolando l’account da cui verify_signatures leggeva. Le firme di soglia proteggono contro la compromissione delle chiavi Guardian; non offrono alcuna protezione contro un bug che non chiede mai input ai Guardian. La difesa a strati richiede che ogni livello del modello di sicurezza venga effettivamente attivato — un controllo bypassato non è un controllo.
Cosa significa tutto ciò per audit di bridge e sicurezza dei programmi Solana
L’exploit Wormhole dimostra che la sicurezza dei bridge cross-chain è un problema multilivello. La rete Guardian può essere crittograficamente solida, gli incentivi economici correttamente allineati e l’architettura del protocollo ben progettata — e una singola chiamata a funzione deprecata nel programma on-chain può annullare tutto.
Per i team che costruiscono su Solana, la lezione sulla validazione degli account si generalizza: trattate ogni parametro passato al vostro programma come input ostile. Validare owner, key, discriminator e lunghezza dati prima di operare su qualsiasi account. Usate il wrapper Account<T> del framework anchor o equivalenti per applicare questi controlli a livello di tipo invece di affidarsi ad assert manuali.
Per gli architetti di bridge, la lezione è la separazione dei privilegi e l’ancoraggio allo stato canonico. L’autorità di minting deve risalire allo stato di proprietà del programma che esso stesso ha validato — non a prove fornite dal chiamante che il programma ha accettato senza verifica.
Soken controlla ogni programma Solana per l’uso di API sysvar deprecate, mancate verifiche di ownership degli account e lacune nella protezione replay delle VAA come problemi di priorità Critica. Il pattern Wormhole — bypassare una multisig a soglia manipolando l’account da cui una funzione di verifica legge — è ora una famiglia di attacchi riconosciuta nella nostra metodologia di audit Solana. Se il vostro protocollo utilizza messaggistica cross-chain o minting di asset wrapped, contattateci su soken.dev/services-it.html per discutere una revisione di sicurezza prima del deploy.