Un attacco di reentrancy è una classe di vulnerabilità degli smart contract in cui un contratto malevolo sfrutta una chiamata di funzione esterna per rientrare nel contratto chiamante prima che l'esecuzione originale sia completata, consentendo all'attaccante di prelevare ripetutamente fondi o manipolare le variabili di stato. L'attacco si verifica quando un contratto invia Ether o token a un indirizzo esterno, in genere utilizzando il livello basso call metodo, prima di aggiornare il proprio stato interno, creando una finestra temporale durante la quale la funzione di fallback o di ricezione del destinatario può richiamare ricorsivamente il contratto vulnerabile.
Il meccanismo canonico funziona nel seguente modo: un contratto vittima contiene una mappatura del saldo e una funzione di prelievo. Quando un utente chiama la funzione di prelievo, il contratto invia Ether all'indirizzo del chiamante prima di azzerare il suo saldo. Se il chiamante è un contratto malevolo con una funzione di fallback che chiama immediatamente di nuovo la funzione di prelievo, il controllo del saldo del contratto vittima mostra ancora l'importo originale perché l'aggiornamento dello stato non è ancora avvenuto. Questa riattivazione ricorsiva continua a prelevare fondi fino a quando il saldo di Ether del contratto vittima non si esaurisce o non viene raggiunto il limite dello stack di chiamate.
Gli attacchi di reentrancy sfruttano la proprietà fondamentale della Ethereum Virtual Machine (EVM) secondo cui le chiamate esterne trasferiscono il controllo dell'esecuzione al chiamato prima che le istruzioni successive del chiamante vengano eseguite. Questo rende la reentrancy una delle vulnerabilità più pericolose e studiate nello sviluppo di smart contract. Questo schema è stato responsabile di alcune delle maggiori perdite finanziarie nella storia della finanza decentralizzata, tra cui il famigerato attacco hacker alla DAO del 2016 che ha causato perdite per circa 60 milioni di dollari e ha portato all'hard fork di Ethereum che ha dato origine a Ethereum Classic.
Le varianti moderne della reentrancy si estendono oltre il semplice schema a funzione singola per includere la reentrancy tra funzioni (in cui la callback rientra in una funzione diversa che legge lo stato obsoleto), la reentrancy tra contratti (in cui la callback prende di mira un contratto diverso che condivide lo stato con quello vulnerabile) e la reentrancy di sola lettura (in cui la callback sfrutta lo stato obsoleto nelle funzioni di vista utilizzate da altri protocolli per il calcolo dei prezzi o delle garanzie).
Origine e storia
2015: Ethereum è stato lanciato con Solidity come linguaggio principale per gli smart contract. La progettazione dell'EVM, in cui le chiamate esterne trasferiscono il controllo dell'esecuzione e consentono l'esecuzione di codice arbitrario da parte del chiamato, ha creato le condizioni di base per le vulnerabilità di reentrancy. La documentazione iniziale di Solidity non avvertiva in modo evidente dei rischi derivanti dall'effettuare chiamate esterne prima degli aggiornamenti di stato.
Giugno 2016: La DAO, un'organizzazione autonoma decentralizzata che aveva raccolto circa 150 milioni di dollari in ETH tramite una vendita di token, è stata sfruttata attraverso una vulnerabilità di reentrancy nel suo splitDAO funzione. Un attaccante ha implementato un contratto dannoso con una funzione di fallback appositamente creata che richiamava The DAO splitDAO La funzione si è attivata in modo ricorsivo, prosciugando circa 3.6 milioni di ETH (equivalenti a circa 60 milioni di dollari all'epoca). Questo rimane l'attacco di reentrancy più grave nella storia della blockchain.
Luglio 2016: La comunità di Ethereum si trovò ad affrontare una crisi di governance riguardo all'opportunità di effettuare un hard fork della blockchain per annullare l'attacco hacker alla DAO. Questo evento mise alla prova il principio "il codice è legge", premessa fondante della DAO. La maggioranza della comunità, supportata da Vitalik Buterin, si schierò a favore di un'interpretazione condizionale del principio, eseguendo un hard fork al blocco 1,920,000 per recuperare i fondi. Gli oppositori, sostenendo che il principio "il codice è legge" dovesse essere assoluto e immutabile, continuarono a utilizzare la blockchain originale come Ethereum Classic (ETC).
2017-2018: L'attacco hacker alla DAO ha catalizzato un approccio incentrato sulla sicurezza nello sviluppo di smart contract. OpenZeppelin ha rilasciato il suo ReentrancyGuard contratto, fornendo una protezione standardizzata basata su mutex contro la reentranza. Strumenti di verifica formale e società di audit di sicurezza come Trail of Bits e ConsenSys Diligence sono emersi per rispondere alla crescente esigenza di sicurezza dei contratti intelligenti.
2020: L'esplosione della DeFi Summer ha portato miliardi di dollari negli smart contract , aumentando drasticamente la posta in gioco per le vulnerabilità di reentrancy. La componibilità dei protocolli DeFi ("money lego") ha introdotto rischi di reentrancy tra contratti, più difficili da rilevare e verificare rispetto alle vulnerabilità dei singoli contratti.
Aprile 2020: L'incidente Uniswap/Lendf.me ha visto circa 25 milioni di dollari sottratti da entrambe le piattaforme tramite un attacco di reentrancy che sfruttava i callback dei token ERC-777, con Lendf.me (il protocollo di prestito di dForce) che ha subito la maggior parte delle perdite, pari a circa 24.5 milioni di dollari. Ciò ha dimostrato che l'attacco di reentrancy non si limitava ai trasferimenti diretti di ETH, ma poteva essere attivato anche tramite meccanismi di callback standard dei token.
Luglio 2023: Curve Finance ha subito un devastante attacco di reentrancy a causa di un bug del compilatore Vyper (versioni 0.2.15, 0.2.16 e 0.3.0) che ha causato il malfunzionamento del meccanismo di blocco di reentrancy. Diversi pool di Curve sono stati svuotati per circa 70 milioni di dollari, dimostrando che le difese contro gli attacchi di reentrancy possono fallire a livello del compilatore del linguaggio, e non solo a livello della logica contrattuale.
2024-2026: La reentrancy in sola lettura è emersa come una nuova frontiera di preoccupazione, in particolare nei protocolli che si basano sulle funzioni di visualizzazione di altri contratti per la determinazione dei prezzi. I rischi di reentrancy cross-chain si sono inoltre concretizzati con la creazione, da parte dei protocolli bridge e delle architetture DeFi multi-chain, di nuove superfici di attacco in cui è possibile sfruttare le incoerenze di stato tra le blockchain.
"L'attacco hacker alla DAO è stato il momento in cui la comunità di Ethereum ha capito che il codice è legge, ma anche le leggi possono avere dei bug. Ha cambiato radicalmente e per sempre il nostro modo di pensare alla sicurezza degli smart contract."
In parole semplici
Immaginate di avere un impiegato di banca che controlla il saldo del vostro conto, vi consegna i contanti e poi aggiorna il registro contabile per registrare il prelievo. Un attacco di reentrancy è come tornare dallo stesso impiegato prima che aggiorni il registro e chiedere un altro prelievo. L'impiegato vede ancora il vostro saldo originale e vi consegna altri contanti. Voi continuate a tornare finché la cassaforte non è vuota.
Immaginate un distributore automatico che eroga una bevanda e poi preleva il denaro dalla vostra carta prepagata. Se poteste premere nuovamente il pulsante nell'istante in cui la bevanda inizia a uscire, ma prima che la carta venga addebitata, potreste ottenere più bevande al prezzo di una. L'attacco di reentrancy sfrutta proprio questo intervallo tra "dare l'oggetto" e "registrare che ho dato l'oggetto".
Immaginate una porta girevole in un hotel. Normalmente, si entra, il portiere registra l'accesso e si può proseguire. In un attacco di reingresso, si entra nella porta girevole e, prima che il portiere possa registrare l'accesso, si torna indietro e si rientra, ancora e ancora, apparendo ogni volta come un "nuovo" visitatore perché il portiere non ha mai avuto il tempo di aggiornare la sua lista.
È come una cassa al supermercato, dove il cassiere ti consegna la spesa prima di scansionarla. Se potessi tornare immediatamente in testa alla fila con lo stesso carrello, il cassiere continuerebbe a darti altra spesa perché il registratore di cassa mostrerebbe ancora l'intero importo pagato. Alla fine, il negozio esaurisce le scorte.
Importante: gli attacchi di reentrancy prendono di mira il codice del contratto stesso, non il meccanismo di consenso della blockchain. La blockchain registra fedelmente ogni transazione, comprese quelle dannose. Per questo motivo, la prevenzione deve avvenire a livello di sviluppo degli smart contract attraverso modelli di codifica sicuri, audit e verifiche formali. La blockchain non è in grado di distinguere tra un prelievo legittimo e un attacco di reentrancy.
Principali caratteristiche tecniche
Il meccanismo di rientranza in dettaglio
L'attaccante distribuisce un contratto malevolo con una funzione di fallback (o di ricezione) appositamente creata.
L'attaccante chiama la funzione di ritiro del contratto vulnerabile dal contratto malevolo
Il contratto vulnerabile controlla il saldo dell'attaccante. Ha esito positivo perché l'attaccante ha depositato fondi
Il contratto vulnerabile invia ETH all'indirizzo del contratto dell'attaccante utilizzando un livello basso call con valore
Prima che l'esecuzione ritorni alla riga successiva del contratto vulnerabile (l'aggiornamento del saldo), l'EVM trasferisce il controllo al contratto dell'attaccante.
La funzione di fallback dell'attaccante si esegue automaticamente al ricevimento di ETH e chiama immediatamente di nuovo il prelievo
Il contratto vulnerabile riesegue la funzione di prelievo. Poiché il saldo non è stato aggiornato, il controllo va a buon fine di nuovo.
I passaggi da 4 a 7 si ripetono ricorsivamente finché il saldo ETH del contratto non si esaurisce o non viene raggiunto il limite del gas.
Solo dopo il completamento dell'ultima chiamata ricorsiva, lo stack delle chiamate si srotola e l'aggiornamento del saldo della prima chiamata viene finalmente eseguito. Ma i fondi sono già spariti.
Il modello Controlli-Effetti-Interazioni
Controlli: Convalidare tutte le condizioni e i requisiti (ad esempio, require(balances[msg.sender] >= amount))
Effetti: Aggiorna tutte le variabili di stato interne (ad esempio, balances[msg.sender] -= amount)
Interazioni: Eseguire chiamate esterne (ad esempio, msg.sender.call{value: amount}("")) solo dopo tutti i cambiamenti di stato
Questo ordinamento garantisce che, anche se si verifica una chiamata rientrante durante la fase di interazione, lo stato sia già stato aggiornato e i successivi controlli di bilanciamento falliranno. Questo schema rappresenta la difesa più importante contro le chiamate rientranti ed è richiesto da tutte le principali guide di stile Solidity e dalle società di revisione.
OpenZeppelin ReentrancyGuard
Fornisce un file nonReentrant modificatore che utilizza una variabile mutex (mutua esclusione) per impedire il rientro
Il modificatore imposta un blocco di stato prima dell'esecuzione della funzione e lo reimposta al termine dell'esecuzione.
Se una chiamata rientrante tenta di eseguire la funzione protetta mentre il blocco è attivo, la transazione viene annullata
L'implementazione utilizza una variabile di stato uint256 (1 = non entrato, 2 = entrato) anziché un valore booleano per l'ottimizzazione del gas.
Ampiamente adottato nel mondo DeFi: Aave, Compound, Uniswap V3 e centinaia di altri protocolli utilizzano ReentrancyGuard o modelli equivalenti.
Varianti di rientranza
Rientro monofunzione: L'attacco classico in cui la funzione di fallback richiama la stessa funzione vulnerabile. Questo era lo schema di attacco DAO.
Rientro interfunzionale: La funzione di fallback chiama una funzione diversa nello stesso contratto che legge la variabile di stato obsoleta, consentendo lo sfruttamento attraverso un percorso secondario
Rientranza transfrontaliera: La callback si rivolge a un contratto diverso che condivide lo stato o le relazioni di fiducia con il contratto vulnerabile, sfruttando la componibilità nella DeFi.
Rientranza in sola lettura: La funzione di callback richiama una funzione di visualizzazione che restituisce uno stato obsoleto, il quale viene poi utilizzato da un protocollo di terze parti per la determinazione del prezzo, la valutazione delle garanzie o l'accesso ai dati tramite oracoli. Non si verifica alcun prelievo diretto di fondi, ma è consentito uno sfruttamento indiretto.
Rientranza ERC-777: Lo standard dei token ERC-777 include hook di callback (tokensReceived) che eseguono codice sul destinatario, creando vettori di rientranza nei protocolli che gestiscono token ERC-777 senza protezione
Strumenti di rilevamento e prevenzione
Analisi statica: Strumenti come Slither (di Trail of Bits) rilevano automaticamente i pattern di rientranza nel codice Solidity tramite l'analisi del flusso di controllo.
Verifica formale: Strumenti come Certora Prover verificano matematicamente che la reentrancy è impossibile in base alle specifiche di un contratto.
Fuzzing: Echidna e Foundry forgiano contratti di fuzz test con input casuali per scoprire rientranze e altre vulnerabilità
Audit di sicurezza: Le società di revisione professionali (Trail of Bits, OpenZeppelin, Consensys Diligence, Halborn) esaminano manualmente il codice dei contratti per individuare vulnerabilità di reentrancy e altre vulnerabilità.
Premi per la ricerca di bug: Piattaforme come Immunefi incentivano gli hacker etici a scoprire le vulnerabilità di reentrancy prima che i malintenzionati le sfruttino.
Vantaggi e svantaggi
Vantaggi (della comprensione della rientranza)
Svantaggi (Rischi di rientro)
Consapevolezza della sicurezza: Comprendere la reentrancy è fondamentale per scrivere smart contract sicuri. È la prima vulnerabilità insegnata in ogni corso di sicurezza Solidity.
Perdita finanziaria catastrofica: Un singolo exploit di reentrancy può prosciugare i fondi di un intero protocollo in una singola transazione, come dimostrato dall'hack di DAO da 60 milioni di dollari e dall'exploit di Curve da 70 milioni di dollari.
Difese consolidate: Modelli di mitigazione ben documentati (controlli-effetti-interazioni, ReentrancyGuard) rendono possibile prevenire la reentrancy quando gli sviluppatori seguono le migliori pratiche
Vettori di attacco in evoluzione: Continuano a emergere nuove varianti come la reentrancy in sola lettura e la reentrancy tra contratti, superando la consapevolezza degli sviluppatori e gli strumenti di rilevamento esistenti.
Ecosistema degli strumenti: Un solido ecosistema di analizzatori statici, fuzzer e strumenti di verifica formale può rilevare automaticamente la maggior parte dei pattern di rientranza prima della distribuzione.
Rischi a livello di compilatore: L'exploit di Curve Finance del 2023 ha dimostrato che le difese contro la reentrancy possono fallire a causa di bug nel compilatore stesso, creando un livello di rischio al di fuori del controllo dello sviluppatore.
Crescita del settore della revisione contabile: La diffusione del fenomeno della reentrancy ha favorito la crescita di un settore professionale di audit dei contratti intelligenti, migliorando la sicurezza complessiva dell'ecosistema.
Amplificazione della componibilità: L'architettura componibile "a mattoncini Lego" della DeFi implica che una vulnerabilità di reentrancy in un protocollo possa propagarsi a cascata attraverso più protocolli interconnessi.
Condivisione delle conoscenze all'interno della comunità: Le vulnerabilità di reentrancy di alto profilo hanno generato approfondite analisi post-mortem, risorse didattiche open-source e miglioramenti della sicurezza a livello di settore.
Falso senso di sicurezza: Gli sviluppatori che applicano ReentrancyGuard ad alcune funzioni potrebbero non rilevare i percorsi di rientranza tra funzioni o tra contratti, creando una protezione incompleta.
Incentivi per la segnalazione di bug: La gravità del fenomeno della reentranza ha spinto i protocolli a offrire cospicue ricompense per la segnalazione di bug (spesso superiori a 1 milione di dollari), incentivando la scoperta etica (white-hat) rispetto allo sfruttamento illecito (black-hat).
Gas sopraelevato: Le protezioni di rientranza aggiungono costi di gas a ogni chiamata di funzione protetta, che si accumulano nelle operazioni DeFi ad alta frequenza e possono avere un impatto sulla competitività del protocollo.
Lezioni di governance: L'attacco hacker alla DAO ha insegnato alla comunità blockchain lezioni fondamentali sulla governance, l'immutabilità e il ruolo del livello sociale nella risposta ai guasti a livello di codice.
Irreversibilità degli exploit: A differenza della finanza tradizionale, dove le transazioni fraudolente possono essere annullate, gli exploit di reentrancy sulle blockchain immutabili sono permanenti, a meno che la comunità non acconsenta a un hard fork controverso.
Risk Management
Pratiche di sviluppo di contratti intelligenti
Segui sempre il modello controlli-effetti-interazioni: aggiorna tutte le variabili di stato prima di effettuare qualsiasi chiamata esterna.
Applica OpenZeppelin nonReentrant modificatore per ogni funzione che esegue chiamate esterne o trasferisce valore
Evitare di utilizzare transfer() and send() per i trasferimenti di ETH nei nuovi contratti. Sebbene limitino il gas a 2,300 (impedendo alcune reentrancy), possono interrompersi con modifiche all'EIP e al ricalcolo del prezzo del gas.
Utilizza modelli di pagamento pull-over-push: invece di inviare fondi direttamente, consenti agli utenti di prelevare i propri fondi, riducendo la superficie di attacco.
Protocolli di audit e di collaudo
Richiedi almeno due audit di sicurezza indipendenti da parte di aziende affidabili prima di implementare contratti che gestiscono valori significativi
Esegui l'analisi statica di Slither e Mythril su ogni contratto prima della distribuzione. Questi strumenti segnalano automaticamente i modelli di rientranza più comuni.
Implementare suite di test fuzz dettagliate utilizzando Echidna o Foundry che si concentrino specificamente sugli scenari di rientranza
Eseguire un'analisi di rientranza tra contratti quando si integra con protocolli esterni, in particolare quelli che utilizzano standard di token con un elevato numero di callback come ERC-777.
Sicurezza operativa
Distribuisci i contratti dietro modelli proxy aggiornabili o con meccanismi di pausa di emergenza in grado di bloccare i prelievi in caso di rilevamento di reingresso.
Monitora l'attività on-chain per individuare schemi di prelievo insoliti (ad esempio, chiamate ricorsive rapide alla stessa funzione all'interno di una singola transazione) utilizzando strumenti come Forta o OpenZeppelin Defender.
Definire procedure di risposta agli incidenti, tra cui la sospensione dei contratti, i canali di comunicazione e le strategie di recupero dei fondi.
Mantenere programmi di ricompensa per la segnalazione di bug con pagamenti proporzionali al valore totale bloccato (TVL) nel protocollo.
Rischi di integrazione DeFi
Quando si compone con protocolli esterni, verificare le protezioni di rientranza del contratto esterno prima dell'integrazione
Non dare per scontato che le funzioni di vista esterne restituiscano uno stato coerente durante l'esecuzione del callback. Questo è il vettore di rientranza di sola lettura.
Implementare meccanismi di protezione contro la rientranza a livello di confine del protocollo, e non solo a livello di singola funzione, per prevenire catene di rientranza tra contratti.
Rilevanza culturale
L'attacco di reentrancy occupa una posizione unica nella cultura blockchain, in quanto evento che ha infranto l'ingenua filosofia del "il codice è legge" e ha costretto la comunità di Ethereum a confrontarsi con la tensione tra immutabilità e pragmatismo. L'attacco hacker alla DAO del 2016 non è stato semplicemente un'azione tecnica. È stato un momento esistenziale per Ethereum, che ha diviso la comunità in due fazioni filosofiche, una delle quali ha dato origine a Ethereum Classic.
"La DAO avrebbe dovuto dimostrare che la governance decentralizzata poteva funzionare. Invece, ha dimostrato che scrivere codice sicuro è più difficile di quanto chiunque avesse immaginato."
Nella cultura degli sviluppatori, la reentrancy è diventata un rito di passaggio. La formazione di ogni sviluppatore Solidity inizia con lo studio dell'hack DAO, e "hai verificato la reentrancy?" è la domanda più frequente nelle revisioni del codice degli smart contract. Le sfide di cattura della flag di Damn Vulnerable DeFi ed Ethernaut includono entrambe i livelli di reentrancy come esercizi fondamentali.
L'exploit di Curve Finance del luglio 2023 ha riacceso il dibattito culturale sulla reentrancy, questa volta incentrato sulla possibilità che bug a livello di compilatore potessero minare le difese implementate correttamente dagli sviluppatori. Il bug del compilatore Vyper che disabilitava i blocchi di reentrancy ha dimostrato che la sicurezza nello sviluppo di smart contract richiede fiducia non solo nel proprio codice, ma nell'intera catena di strumenti. Questa lezione ha trovato piena risonanza nella comunità blockchain, che si basa su presupposti di fiducia minimi.
Su Twitter e nei forum DeFi dedicati alle criptovalute, gli exploit di reentrancy vengono analizzati in tempo reale con la stessa intensità delle notizie dell'ultima ora. Gli hacker etici che scoprono e divulgano responsabilmente le vulnerabilità di reentrancy vengono celebrati come eroi della comunità, mentre le analisi post-mortem degli exploit diventano alcuni dei contenuti tecnici più condivisi nell'ecosistema. L'espressione "reentrancy" ha trasceso la sua definizione tecnica per diventare una sorta di abbreviazione culturale della tensione sempre presente tra velocità di innovazione e rigore della sicurezza nella finanza decentralizzata.
Esempi del mondo reale
L'attacco hacker alla DAO (giugno 2016)
Scenario: La DAO, un fondo di venture capital decentralizzato, deteneva circa 150 milioni di dollari in ETH conferiti da migliaia di investitori. splitDAO Questa funzionalità permetteva agli investitori di ritirare la propria quota proporzionale di fondi in una "DAO secondaria".
Implementazione Un attaccante ha implementato un contratto esterno dannoso con una funzione di fallback progettata per richiamare ricorsivamente il DAO splitDAO funzione. Tale funzione inviava ETH al contratto dell'attaccante prima di aggiornare il saldo interno. Poiché il saldo non veniva mai azzerato tra le chiamate ricorsive, l'attaccante ha continuato a prelevare fondi per diverse ore, estraendo circa 3.6 milioni di ETH (circa 60 milioni di dollari).
Esito: La comunità di Ethereum ha eseguito un hard fork al blocco 1,920,000 per ripristinare i fondi rubati, creando la scissione tra Ethereum (ETH) ed Ethereum Classic (ETC). Questo evento ha consacrato la reentrancy come la vulnerabilità più famigerata nella storia degli smart contract e ha dato impulso all'intero settore della sicurezza degli smart contract.
Sfruttamento della vulnerabilità Vyper di Curve Finance (30 luglio 2023)
Scenario: Sono stati creati diversi pool di liquidità di Curve Finance (alETH/ETH, msETH/ETH, pETH/ETH e CRV/ETH) con contratti intelligenti Vyper che includevano @nonreentrant decoratori, l'equivalente Vyper di ReentrancyGuard di Solidity.
Implementazione Un bug nelle versioni 0.2.15, 0.2.16 e 0.3.0 del compilatore Vyper ha causato il @nonreentrant il blocco è stato compilato in modo errato, disabilitando di fatto la protezione dalla reentrancy in fase di esecuzione, nonostante appaia correttamente nel codice sorgente. Gli aggressori hanno sfruttato questa vulnerabilità per rientrare nelle funzioni del pool durante la rimozione della liquidità, manipolando i prezzi e prosciugando i fondi. L'exploit ha preso di mira il remove_liquidity funzione che inviava i token al chiamante prima di aggiornare completamente lo stato del pool.
Esito: Circa 70 milioni di dollari sono stati sottratti da diversi pool. Diversi hacker etici e bot MEV hanno anticipato alcuni degli attacchi, recuperando una parte dei fondi. L'incidente ha messo in luce il rischio critico che i bug a livello di compilatore possano compromettere le misure di sicurezza a livello di applicazione e ha portato a un audit dettagliato del compilatore Vyper.
Attacco ERC-777 a Uniswap/Lendf.me (aprile 2020)
Scenario: Il protocollo Lendf.me di dForce, una piattaforma di prestito, supportava imBTC, un token ERC-777 con hook di callback integrati. Quando un utente riceveva token imBTC, l'ERC-777 tokensReceived Il codice hook è stato eseguito sul contratto del destinatario. Anche Uniswap è stata bersaglio di un attacco correlato, con perdite complessive su entrambe le piattaforme pari a circa 25 milioni di dollari, la stragrande maggioranza delle quali provenienti da Lendf.me.
Implementazione L'attaccante ha sfruttato la tokensReceived Callback durante la funzione di fornitura: quando Lendf.me ha inviato imBTC al contratto dell'attaccante nell'ambito di un'operazione di fornitura/prestito, il callback è rientrato nella funzione di fornitura di Lendf.me, gonfiando artificialmente il saldo di garanzia dell'attaccante. Con la garanzia gonfiata, l'attaccante ha preso in prestito tutte le risorse disponibili dal protocollo.
Esito: Circa 24.5 milioni di dollari sono stati sottratti specificamente da Lendf.me, con perdite minori da Uniswap. L'autore dell'attacco ha infine restituito i fondi dopo essere stato parzialmente identificato. Questo incidente ha evidenziato i rischi di reentrancy specifici dei callback dei token ERC-777 e ha portato molti protocolli DeFi a inserire esplicitamente nella blacklist o ad aggiungere protezioni per gli standard di token che abilitano i callback.
Exploit del protocollo Rari Capital / Fei (aprile 2022)
Scenario: I pool di prestito Fuse di Rari Capital permettevano agli utenti di fornire e prendere in prestito diversi token. Diversi pool Fuse accettavano token con meccanismi di callback che consentivano la re-entrabilità durante il flusso di prestito.
Implementazione L'attaccante ha utilizzato una vulnerabilità di reentrancy nel borrow Interazione della funzione con i token abilitati al callback. Rientrando durante il callback di prestito, l'attaccante ha manipolato la contabilità del pool per prendere in prestito più di quanto consentito dalla propria garanzia, ripetendo il processo su più pool Fuse.
Esito: Circa 80 milioni di dollari sono stati rubati attraverso diverse pool di Fuse. Rari Capital e Fei Protocol, che si erano fuse di recente, non sono riuscite a recuperare i fondi, portando infine alla chiusura del protocollo. L'attacco ha evidenziato i rischi di reentrancy nei protocolli di prestito componibili con whitelisting permissivo dei token.
Tavola di comparazione
Caratteristica
Attacco di rientro
Attacco di prestito lampo
Attacco di manipolazione dell'oracolo
Vettore di attacco
Chiamate esterne ricorsive prima degli aggiornamenti di stato
Prestiti non garantiti che sfruttano la logica del protocollo all'interno di un'unica transazione
Fornire dati di prezzo falsi ai contratti intelligenti tramite oracoli manipolati o obsoleti
Causa ultima
Violazione dello schema controlli-effetti-interazioni
Logica del protocollo che presuppone che i mutuatari abbiano capitale reale a rischio
Dipendenza da fonti di prezzo uniche o facilmente manipolabili
Capitale richiesto
Minimo (quanto basta per innescare il primo prelievo)
Zero (i prestiti flash sono per definizione non garantiti)
Variabile (da zero nel caso di prestiti flash a significativo nel caso di manipolazione diretta del mercato)
Difesa primaria
ReentrancyGuard, controlli-effetti-interazioni, modelli di pagamento pull
TWAP multi-blocco, periodi di blocco minimi, separazione tra prestito e offerta
Oracoli decentralizzati (Chainlink), TWAP, feed di prezzo multi-sorgente, interruttori di circuito
danni storici
60 milioni di dollari (DAO, 2016), 70 milioni di dollari (Curve, 2023), 80 milioni di dollari (Rari, 2022)
Oltre 130 milioni di dollari (Cream Finance, 2021), 182 milioni di dollari (Beanstalk, 2022)
Oltre 100 milioni di dollari (Mango Markets, 2022), 130 milioni di dollari (Cream Finance, 2021)
Difficoltà di rilevamento
Moderato: gli strumenti di analisi statica individuano la maggior parte degli schemi, ma le varianti di tipo cross-contract e read-only sono più difficili da rilevare.
Livello elevato: richiede la comprensione di complesse logiche di transazione a più fasi.
Elevato: distinguere la manipolazione dalla legittima attività di mercato è intrinsecamente difficile
Impatto della blockchain
Ha causato l'hard fork di Ethereum (divisione ETH/ETC)
Ha promosso l'innovazione nella protezione dei veicoli elettrici e nell'ordinamento delle transazioni.
Ciò ha portato a una diffusa adozione di Chainlink e agli standard oracolo TWAP.
Termini correlati
Smart Contract: Programmi autoeseguibili distribuiti su una blockchain che applicano automaticamente i termini di un accordo. Gli exploit di reentrancy prendono di mira le vulnerabilità nella logica degli smart contract.
The DAO: Un'organizzazione autonoma decentralizzata su Ethereum che ha subito il più famoso attacco di reentrancy nel 2016, che ha portato all'hard fork ETH/ETC.
Funzione di fallback: Una speciale funzione Solidity che viene eseguita quando un contratto riceve ETH o una chiamata di funzione non riconosciuta. Il meccanismo attraverso il quale vengono attivati i callback di rientranza.
Schema Controlli-Effetti-Interazioni: Un modello di codifica sicuro che impone di eseguire tutti gli aggiornamenti di stato prima delle chiamate esterne, prevenendo la rientranza per impostazione predefinita.
OpenZeppelin: La principale libreria open-source per smart contract che fornisce primitive di sicurezza collaudate, tra cui ReentrancyGuard, utilizzate dalla maggior parte dei principali protocolli DeFi.
Prestito Flash: Un prestito non garantito che deve essere contratto e rimborsato in un'unica transazione. Spesso combinato con tecniche di reentrancy o altre tecniche di sfruttamento per massimizzare l'impatto.
Ethereum Classic (ETC): La continuazione della catena Ethereum originale che si è rifiutata di biforcarsi dopo l'attacco hacker alla DAO, preservando la catena in cui l'exploit di reentrancy non è stato annullato.
Verifica formale: Dimostrazione matematica che uno smart contract si comporta in conformità alle sue specifiche. Può dimostrare in modo definitivo l'assenza di vulnerabilità di reentrancy.
CKD-777: Uno standard di token avanzato con hook di callback integrati che ha introdotto nuove superfici di attacco di reentrancy nei protocolli DeFi.
Mutex (Mutua esclusione): Un meccanismo di controllo della concorrenza adattato ai contratti intelligenti sotto forma di guardie di rientranza che impediscono l'esecuzione simultanea di funzioni protette.
Vyper: Un linguaggio per smart contract simile a Python per l'EVM. Un bug del compilatore Vyper ha causato la vulnerabilità di reentrancy di Curve Finance nel 2023, nonostante le corrette protezioni a livello di applicazione.
MEV (Massimo Valore Estraibile): Il valore che i produttori di blocchi possono estrarre riordinando le transazioni. I bot MEV a volte anticipano gli exploit di reentrancy per catturare o restituire i fondi rubati.
FAQ
D: Cos'è esattamente un attacco di reentrancy in termini semplici?
Un attacco di reentrancy si verifica quando uno smart contract invia denaro a un indirizzo esterno prima di aver registrato l'avvenuto invio. Il destinatario può essere un contratto malevolo che richiede immediatamente altro denaro e, poiché il record non è ancora stato aggiornato, il contratto vulnerabile pensa che l'attaccante disponga ancora del saldo originale. Questo ciclo si ripete, prosciugando i fondi del contratto.
D: Come ha funzionato l'attacco hacker alla DAO e perché è stato così importante?
La DAO era un fondo di investimento da 150 milioni di dollari su Ethereum. Il suo splitDAO La funzione di prelievo ha inviato ETH agli utenti prima di aggiornare il loro saldo a zero. Un attaccante ha distribuito un contratto dannoso la cui funzione di fallback ha richiamato splitDAO Ogni volta che riceveva ETH, sottraeva ricorsivamente circa 60 milioni di dollari. L'attacco fu così significativo che la comunità di Ethereum eseguì un hard fork dell'intera blockchain per annullarlo, dividendo Ethereum in ETH ed Ethereum Classic: un momento cruciale nella storia della governance blockchain.
D: Gli attacchi di reentrancy possono verificarsi anche su blockchain diverse da Ethereum?
Sì. La reentrancy è possibile su qualsiasi blockchain che supporti smart contract con chiamate esterne che trasferiscono il controllo dell'esecuzione. Ciò include blockchain compatibili con EVM come BNB Chain, Polygon, Avalanche e Arbitrum. Le blockchain non EVM, come Solana, hanno modelli di esecuzione diversi che rendono la reentrancy tradizionale più difficile, ma non impossibile. Il runtime di Solana impedisce chiamate CPI (cross-program invocation) ricorsive allo stesso programma all'interno di una singola istruzione, ma possono comunque verificarsi schemi simili alla reentrancy tra programmi.
D: Cos'è il modello controlli-effetti-interazioni e come previene la rientranza?
Il pattern checks-effects-interactions è una disciplina di programmazione che richiede tre passaggi in ordine rigoroso: primo, verificare tutte le condizioni (ad esempio, l'utente ha un saldo sufficiente?); secondo, aggiornare tutte le variabili di stato (ad esempio, ridurre a zero il saldo dell'utente); terzo, interagire con contratti esterni (ad esempio, inviare ETH). Aggiornando lo stato prima della chiamata esterna, qualsiasi callback rientrante incontrerà lo stato già aggiornato e fallirà il controllo, impedendo l'exploit.
D: Cos'è la rientranza in sola lettura e perché è pericolosa?
La reentrancy in sola lettura si verifica quando una callback durante una chiamata esterna consente a un attaccante di leggere lo stato obsoleto dalle funzioni di vista. Anche se nessun fondo viene prelevato direttamente dal contratto vulnerabile, altri protocolli che si basano su tali funzioni di vista per la determinazione dei prezzi, il calcolo delle garanzie o i dati dell'oracolo riceveranno valori errati. Questo può essere sfruttato per ottenere prestiti sottocollateralizzati o manipolare i prezzi nei protocolli DeFi connessi, rendendolo un vettore di attacco subdolo ma potenzialmente devastante.
D: Come è stato possibile che la vulnerabilità di Curve Finance del 2023 si sia verificata nonostante la presenza di sistemi di protezione contro il reentrancy?
I pool di Curve Finance sono stati scritti in Vyper e hanno utilizzato correttamente @nonreentrant decoratore per prevenire la rientranza. Tuttavia, un bug nelle versioni 0.2.15, 0.2.16 e 0.3.0 del compilatore Vyper ha causato una compilazione errata del blocco di rientranza: il blocco non veniva mai effettivamente impostato durante l'esecuzione, sebbene apparisse correttamente nel codice sorgente. Ciò significava che la protezione contro la rientranza esisteva sulla carta, ma veniva rimossa silenziosamente durante la compilazione. L'exploit ha dimostrato che la sicurezza degli smart contract dipende non solo dalla correttezza del codice applicativo, ma anche dalla correttezza dell'intera toolchain, incluso il compilatore.
D: Quali strumenti possono utilizzare gli sviluppatori per rilevare le vulnerabilità di reentrancy prima del deployment?
Gli sviluppatori dovrebbero adottare un approccio a più livelli: (1) strumenti di analisi statica come Slither e Mythril che scansionano automaticamente il codice alla ricerca di pattern di rientranza, (2) test di fuzzing con Echidna o Foundry Forge che testano i contratti con input casuali, (3) verifica formale con strumenti come Certora Prover che dimostrano matematicamente l'assenza di rientranza e (4) audit di sicurezza professionali da parte di aziende come Trail of Bits, OpenZeppelin o Halborn. Nessuno strumento singolo rileva tutte le varianti, quindi una strategia di difesa multilivello è essenziale.