Skip to main content
Xcapit
Blog
·13 min di lettura·Fernando BoieroFernando Boiero·CTO & Co-Fondatore

Sicurezza degli Smart Contract: 10 Vulnerabilita Comuni e Come Prevenirle

blockchaincybersecuritysmart-contracts

Dal hack del DAO del 2016, le vulnerabilita degli smart contract sono costate all'industria blockchain oltre 8 miliardi di dollari in fondi rubati o bloccati. La natura immutabile della blockchain significa che una volta che un contratto difettoso viene deployato, non puo essere corretto -- il codice e legge, bug inclusi. Ogni vulnerabilita che raggiunge la mainnet e un potenziale exploit in attesa, e gli attaccanti sono sofisticati, ben finanziati e implacabili.

Mappa del panorama delle vulnerabilità degli smart contract
Vulnerabilità comuni degli smart contract: dagli attacchi di reentrancy alla manipolazione degli oracoli

Comprendere i pattern di vulnerabilita piu comuni e la prima linea di difesa. Questa guida copre dieci vulnerabilita critiche degli smart contract, spiega come funziona ciascuna e fornisce strategie concrete di prevenzione che i team di sviluppo dovrebbero implementare prima che qualsiasi codice raggiunga la produzione.

1. Attacchi di Reentrancy

La reentrancy e la vulnerabilita degli smart contract piu nota, responsabile dell'hack originale del DAO che porto all'hard fork di Ethereum. Si verifica quando un contratto effettua una chiamata esterna a un altro contratto prima di aggiornare il proprio stato. Il contratto chiamato puo quindi richiamare la funzione originale prima che la prima esecuzione si completi, creando un loop ricorsivo che drena fondi oltre quanto dovrebbe essere consentito.

L'esempio classico e una funzione di prelievo che invia ETH a un utente prima di azzerare il suo saldo. Un attaccante deploya un contratto con una funzione fallback che chiama nuovamente withdraw quando riceve ETH. Il risultato e che l'attaccante puo prelevare il proprio saldo piu volte prima che il contratto registri mai la deduzione.

Gli attacchi di reentrancy moderni si sono evoluti oltre il pattern a singola funzione. La reentrancy cross-function sfrutta lo stato condiviso tra diverse funzioni nello stesso contratto. La reentrancy cross-contract prende di mira lo stato condiviso tra piu contratti in un protocollo. La reentrancy read-only manipola le funzioni view su cui i contratti esterni si basano per calcoli di prezzo o collaterale.

  • Segui il pattern checks-effects-interactions: valida le condizioni, aggiorna lo stato, poi effettua le chiamate esterne -- mai il contrario
  • Usa guard di reentrancy (lock mutex) su tutte le funzioni che modificano lo stato e che effettuano chiamate esterne
  • Verifica la reentrancy cross-function e cross-contract, non solo i pattern a singola funzione
  • Considera i vettori di reentrancy read-only se il tuo contratto espone funzioni view usate da altri protocolli
  • Usa pattern pull-over-push dove gli utenti prelevano i fondi piuttosto che il contratto inviarli

2. Integer Overflow e Underflow

L'integer overflow si verifica quando un'operazione aritmetica produce un valore piu grande del massimo che un tipo di variabile puo contenere, causandone il ritorno a zero o a un numero piccolo. L'integer underflow e il contrario -- sottrarre da zero porta al valore massimo. Nei contratti finanziari, questo puo significare che un utente con zero token improvvisamente ne ha miliardi, o un saldo enorme diventa trascurabile.

Prima di Solidity 0.8.0, le operazioni aritmetiche non controllavano overflow o underflow per default, rendendo questa una delle classi di vulnerabilita piu comuni. L'exploit del token BEC nel 2018 uso un integer overflow per generare miliardi di token dal nulla, facendo crollare il valore del token a zero.

Mentre Solidity 0.8+ include controlli di overflow integrati, il pericolo non e scomparso. Il blocco unchecked disabilita esplicitamente queste protezioni per l'ottimizzazione del gas. Inoltre, il type casting tra diverse dimensioni di interi (da uint256 a uint128, ad esempio) puo troncare silenziosamente i valori. E i protocolli scritti in altri linguaggi come Vyper o Rust hanno i propri comportamenti di overflow.

  • Usa Solidity 0.8.0 o versioni successive per beneficiare dei controlli integrati di overflow e underflow
  • Verifica ogni uso della keyword unchecked per confermare che l'overflow sia realmente impossibile in quel contesto
  • Fai attenzione con il type casting -- valida esplicitamente che i valori rientrino nel tipo di destinazione prima del casting
  • Usa SafeMath o librerie equivalenti per contratti che devono supportare versioni piu vecchie di Solidity
  • Testa le condizioni limite: cosa succede a zero, ai valori massimi e ai confini dei tipi

3. Front-Running e Attacchi MEV

Il front-running si verifica quando un attaccante vede una transazione in attesa nel mempool e invia la propria transazione con un prezzo del gas piu alto per essere eseguita per prima. Sulle blockchain pubbliche, tutte le transazioni in attesa sono visibili prima di essere incluse in un blocco, creando un'asimmetria informativa che attori sofisticati sfruttano per profitto. Questo fa parte del piu ampio fenomeno del Maximal Extractable Value (MEV).

Il pattern di front-running piu comune in DeFi e il sandwich attack. Un attaccante vede uno swap di grandi dimensioni in attesa su un exchange decentralizzato, acquista prima il token target (facendo salire il prezzo), lascia che la transazione della vittima venga eseguita al prezzo gonfiato, poi vende immediatamente dopo per un profitto. La vittima ottiene meno token del previsto, e l'attaccante intasca la differenza.

Il front-running colpisce anche lanci di token, minting di NFT, liquidazioni, aggiornamenti degli oracoli e voti di governance. Qualsiasi transazione il cui esito dipende dall'ordine di esecuzione e potenzialmente vulnerabile.

  • Implementa protezione dallo slippage con impatto massimo accettabile sul prezzo definito dall'utente su tutte le funzioni di swap
  • Usa schemi commit-reveal per operazioni dove il contenuto della transazione dovrebbe essere nascosto fino all'esecuzione
  • Considera l'invio privato delle transazioni tramite Flashbots Protect o servizi simili di protezione MEV
  • Progetta meccanismi che siano indipendenti dall'ordine dove possibile -- aste a batch invece di first-come-first-served
  • Imposta scadenze ragionevoli sulle transazioni per evitare che vengano trattenute ed eseguite in momenti svantaggiosi
  • Per la governance, usa proposte con time-lock e snapshot voting per prevenire la manipolazione dei voti tramite flash loan

4. Manipolazione degli Oracoli

Gli oracoli forniscono dati esterni agli smart contract -- piu comunemente feed di prezzo per i protocolli DeFi. Se un attaccante puo manipolare i dati di prezzo su cui un contratto si basa, puo ingannare il protocollo facendogli prendere decisioni basate su informazioni false. Questo e uno dei vettori di attacco piu devastanti dal punto di vista finanziario, responsabile di centinaia di milioni in perdite.

La tecnica di manipolazione degli oracoli piu comune usa flash loan per distorcere temporaneamente i prezzi on-chain. Un attaccante prende in prestito un'enorme quantita di token, li usa per muovere il prezzo su un DEX, innesca un protocollo vulnerabile che legge quel prezzo del DEX, poi trae profitto dall'operazione a prezzo errato -- tutto in una singola transazione. Poiche i flash loan non richiedono collaterale, l'attaccante non rischia nulla.

Anche i provider di oracoli ben noti non sono immuni. I feed Chainlink possono avere dati obsoleti se le condizioni di aggiornamento non sono soddisfatte. Gli oracoli TWAP di Uniswap possono essere manipolati con capitale sostenuto su piu blocchi. Le implementazioni di oracoli personalizzati hanno spesso rischi di centralizzazione o ritardi di aggiornamento che creano finestre di sfruttamento.

  • Usa prezzi medi ponderati nel tempo (TWAP) invece di prezzi spot per resistere alla manipolazione su singolo blocco
  • Implementa controlli di deviazione del prezzo che rifiutano aggiornamenti oltre una soglia ragionevole
  • Usa piu fonti di oracoli indipendenti con un meccanismo di mediana o consenso
  • Aggiungi controlli di freschezza -- rifiuta dati di prezzo piu vecchi di una soglia definita
  • Implementa circuit breaker che sospendono le operazioni durante estrema volatilita di mercato
  • Non usare mai un singolo pool DEX come unica fonte di prezzo per operazioni finanziarie critiche

5. Difetti nel Controllo degli Accessi

Le vulnerabilita del controllo degli accessi si verificano quando funzioni critiche mancano di controlli di permesso adeguati, permettendo a utenti non autorizzati di eseguire operazioni privilegiate. Questo include funzioni di inizializzazione non protette, controlli di ruolo mancanti su operazioni admin e trasferimenti di proprieta implementati in modo errato. L'hack del wallet multi-sig Parity, che ha bloccato oltre 150 milioni di dollari in ETH, fu causato da una funzione di inizializzazione non protetta che chiunque poteva chiamare.

Il pericolo e amplificato dalla natura pubblica della blockchain. Ogni funzione in un contratto e visibile e invocabile da chiunque a meno che non sia esplicitamente ristretta. A differenza del software tradizionale dove il server controlla l'accesso, gli smart contract devono imporre i propri permessi interamente attraverso il codice. Non c'e firewall, non c'e segmentazione di rete e non c'e validazione lato server -- solo cio che il contratto stesso verifica.

I pattern proxy introducono ulteriore complessita nel controllo degli accessi. L'admin del proxy, il proprietario dell'implementazione e l'autorita di upgrade possono essere ruoli diversi, e la confusione tra di essi crea vulnerabilita. I pattern transparent proxy aiutano separando le chiamate admin da quelle utente, ma la configurazione errata rimane una fonte comune di bug.

  • Usa librerie consolidate come AccessControl o Ownable di OpenZeppelin per la gestione dei permessi
  • Implementa il principio del privilegio minimo -- ogni ruolo dovrebbe avere solo i permessi necessari
  • Usa trasferimenti di proprieta a due fasi (proposta e accettazione) per prevenire trasferimenti accidentali a indirizzi errati
  • Aggiungi time-lock alle modifiche di parametri critici cosi che la community possa revisionare e reagire prima che le modifiche abbiano effetto
  • Richiedi approvazione multi-firma per le operazioni admin -- non usare mai un singolo EOA per la governance del protocollo
  • Verifica attentamente i pattern proxy, specialmente la relazione tra admin del proxy e proprietario dell'implementazione

6. Attacchi con Flash Loan

I flash loan permettono a chiunque di prendere in prestito una quantita illimitata di token senza collaterale, a patto che il prestito venga restituito nella stessa transazione. Sebbene siano un'innovazione DeFi legittima per l'arbitraggio e il rifinanziamento, sono diventati il principale meccanismo di finanziamento per exploit sofisticati. I flash loan danno effettivamente a ogni attaccante il capitale di una whale, rimuovendo la barriera finanziaria per eseguire attacchi di manipolazione del mercato.

Un tipico attacco con flash loan combina piu vulnerabilita in una singola transazione atomica. L'attaccante prende in prestito milioni di dollari in token, li usa per manipolare un oracolo di prezzo, sfrutta un protocollo che si basa su quell'oracolo, estrae il profitto, ripaga il prestito con gli interessi e tiene la differenza. Se un qualsiasi passo fallisce, l'intera transazione viene annullata e l'attaccante perde solo il costo del gas.

Gli attacchi con flash loan sono particolarmente pericolosi perche sono privi di rischio per l'attaccante e possono essere eseguiti da chiunque abbia la conoscenza tecnica per costruire la transazione. L'exploit di Euler Finance nel 2023 uso un flash loan per manipolare il prezzo del collaterale, risultando in una perdita di 197 milioni di dollari -- il piu grande attacco con flash loan fino ad oggi.

  • Progetta i protocolli per essere resistenti ai flash loan assumendo che qualsiasi utente possa avere capitale illimitato in una singola transazione
  • Usa oracoli TWAP e medie di prezzo su piu blocchi che non possono essere manipolati in una singola transazione
  • Implementa periodi minimi di lock per i depositi prima che possano essere usati come collaterale o potere di voto
  • Aggiungi restrizioni sulle operazioni nello stesso blocco -- impedisci deposito e prestito nella stessa transazione dove appropriato
  • Stress-testa il tuo protocollo con strumenti di simulazione flash loan per identificare potenziali vettori di attacco
  • Considera se gli invarianti del tuo protocollo reggono quando un utente ha capitale temporaneo illimitato

7. Denial of Service (DoS)

Il denial of service negli smart contract si verifica quando un attaccante puo impedire agli utenti legittimi di interagire con un contratto. A differenza degli attacchi DoS web tradizionali che sovraccaricano i server con traffico, il DoS degli smart contract sfrutta difetti logici che bloccano permanentemente o temporaneamente funzioni critiche.

Il pattern piu comune e il DoS con loop illimitato. Se un contratto itera su un array che cresce senza limiti -- come una lista di detentori di token per la distribuzione di dividendi -- un attaccante puo aggiungere abbastanza voci da far superare il limite di gas del blocco al costo dell'iterazione. La funzione diventa permanentemente non invocabile, e qualsiasi fondo bloccato dietro di essa diventa inaccessibile.

Un altro vettore comune e il DoS con revert inatteso. Se un contratto invia ETH a una lista di indirizzi e uno di quegli indirizzi e un contratto che fa revert alla ricezione, l'intera operazione batch fallisce. Un attaccante puo sfruttare questo per bloccare la liquidazione di aste, il conteggio dei voti di governance o qualsiasi operazione che deve elaborare una lista di indirizzi.

  • Evita loop illimitati -- usa pattern di paginazione o imposta limiti rigidi sulle dimensioni degli array
  • Preferisci pattern pull-over-push: lascia che gli utenti prelevino piuttosto che inviare pagamenti a loro
  • Non rendere le operazioni critiche dipendenti dal successo delle chiamate esterne -- gestisci i fallimenti con grazia
  • Usa chiamate esterne con limite di gas (call con stipend) per impedire ai contratti chiamati di consumare tutto il gas
  • Implementa meccanismi di recupero di emergenza che possano bypassare le funzioni bloccate quando necessario
  • Testa con scenari avversari: cosa succede se un partecipante agisce in modo malevolo?

8. Bug Logici nella Business Logic

I bug logici sono vulnerabilita dove il codice fa esattamente cio per cui e stato scritto, ma cio per cui e stato scritto non e cio che gli sviluppatori intendevano. Questi sono i bug piu difficili da intercettare perche gli strumenti automatizzati cercano pattern di vulnerabilita noti, mentre i bug logici sono unici per le regole di business specifiche di ogni protocollo.

Esempi comuni includono calcoli errati delle commissioni che permettono agli utenti di evitare il pagamento in condizioni specifiche, formule di distribuzione delle ricompense che possono essere sfruttate depositando e prelevando in momenti strategici, e meccanismi di liquidazione che non tengono conto dei casi limite nei rapporti di collaterale. L'incidente della governance di Compound Finance, dove un bug nella logica di distribuzione delle ricompense causo la distribuzione errata di 90 milioni di dollari in token, fu un puro bug logico -- il codice venne eseguito perfettamente, ma la formula era sbagliata.

Le vulnerabilita della business logic sono amplificate dalla componibilita. Quando il tuo protocollo interagisce con altri protocolli, il comportamento combinato puo produrre risultati che nessuno dei due protocolli aveva previsto. Un protocollo di prestito e un aggregatore di rendimenti potrebbero essere ciascuno sicuro individualmente, ma la loro interazione crea un loop di feedback sfruttabile.

  • Scrivi specifiche complete prima di codificare -- documenta ogni formula, ogni caso limite e ogni assunzione
  • Implementa testing basato sulle proprieta che verifica che gli invarianti reggano attraverso migliaia di scenari casuali
  • Usa la verifica formale per proprieta matematiche critiche come la conservazione dei token e la solvibilita
  • Testa con scenari economici realistici, non solo test unitari -- simula condizioni di stress di mercato
  • Fai revisionare la business logic da esperti di dominio (non solo ricercatori di sicurezza) rispetto alle specifiche
  • Documenta tutte le assunzioni del protocollo esplicitamente e testa cosa succede quando quelle assunzioni vengono violate

9. Attacchi di Replay delle Firme

Il replay delle firme si verifica quando un messaggio firmato valido puo essere riutilizzato in un contesto dove non dovrebbe essere accettato. Se un contratto accetta un'autorizzazione firmata per trasferire token ma non tiene traccia di quali firme sono state usate, la stessa firma puo essere inviata piu volte per drenare l'intero saldo dell'utente. Il replay delle firme tra catene e un'altra variante -- una firma valida su Ethereum puo essere replicata su Polygon o BSC se il contratto non include dati specifici della catena nel messaggio firmato.

Questa vulnerabilita appare frequentemente nei sistemi di meta-transazioni, transazioni gasless, order book off-chain e qualsiasi sistema che usa la firma di dati tipizzati EIP-712. La funzione permit (EIP-2612) e un'implementazione comune che permette approvazioni di token tramite firme invece di transazioni on-chain -- ed e un bersaglio comune per attacchi di replay quando implementata in modo errato.

Il rischio e accresciuto dopo i fork delle catene. Quando Ethereum e passato al proof-of-stake e la catena proof-of-work ha continuato come ETHW, le firme create su una catena erano valide su entrambe. I protocolli che non includevano il chain ID nei loro dati firmati erano vulnerabili al replay cross-chain.

  • Includi un nonce in ogni messaggio firmato e traccia i nonce usati on-chain per prevenire il riutilizzo
  • Includi il chain ID (EIP-155) in tutti i dati firmati per prevenire il replay cross-chain
  • Includi l'indirizzo del contratto nei dati firmati per prevenire il replay tra diverse istanze del contratto
  • Segui EIP-712 per la firma di dati strutturati tipizzati -- include separatori di dominio che prevengono la maggior parte dei vettori di replay
  • Implementa la scadenza delle firme con deadline per limitare la finestra di potenziale replay
  • Dopo i fork delle catene, verifica tutte le funzioni basate su firme per la vulnerabilita al replay cross-chain

10. Storage Non Inizializzato e Insidie dei Proxy

Le vulnerabilita di storage non inizializzato si verificano quando le variabili del contratto non vengono impostate correttamente durante il deployment o l'inizializzazione, lasciandole con valori predefiniti (zero per gli interi, vuoto per gli indirizzi) che creano condizioni sfruttabili. Questo e particolarmente pericoloso con i pattern proxy, dove il costruttore del contratto di implementazione non viene mai chiamato -- il proxy chiama invece una funzione di inizializzazione, e se quella funzione puo essere chiamata da chiunque, un attaccante puo prendere la proprieta del contratto.

L'attacco a proxy non inizializzato piu noto si e verificato contro il contratto di implementazione di Wormhole nel 2022. Il team aveva lasciato il contratto di implementazione non inizializzato, permettendo a un attaccante di chiamare la funzione initialize, prendere la proprieta e aggiornare il contratto a una versione malevola -- risultando in una perdita di 320 milioni di dollari.

La collisione di storage e un rischio correlato nei pattern proxy. Se il proxy e i contratti di implementazione usano gli stessi slot di storage per variabili diverse, scrivere su uno corrompe l'altro. Lo standard EIP-1967 definisce slot di storage specifici per gli indirizzi dell'admin del proxy e dell'implementazione per evitare questo, ma le implementazioni proxy personalizzate spesso sbagliano.

  • Chiama sempre l'inizializzatore nella stessa transazione del deployment del proxy per prevenire il front-running
  • Usa il modifier initializer di OpenZeppelin per assicurare che le funzioni di inizializzazione possano essere chiamate solo una volta
  • Disabilita gli inizializzatori nel costruttore del contratto di implementazione per prevenire attacchi di inizializzazione diretta
  • Segui le convenzioni degli slot di storage EIP-1967 per i pattern proxy per evitare collisioni di storage
  • Verifica che tutte le variabili di stato abbiano valori iniziali sensati -- non assumere mai che il valore predefinito zero sia sicuro
  • Verifica attentamente i percorsi di aggiornamento: assicurati che le nuove versioni di implementazione non introducano conflitti nel layout dello storage

Costruire un Processo di Sviluppo Security-First

Prevenire le vulnerabilita non riguarda solo conoscere i pattern -- richiede una cultura di sviluppo e un processo che renda la sicurezza una preoccupazione di prima classe in ogni fase.

  • Scrivi una specifica dettagliata prima di scrivere codice, inclusi tutti i casi limite, le assunzioni economiche e le modalita di fallimento
  • Usa librerie consolidate e verificate come OpenZeppelin invece di implementare pattern standard da zero
  • Implementa suite di test complete: test unitari per singole funzioni, test di integrazione per interazioni cross-contract e fuzz test per condizioni limite
  • Esegui strumenti di analisi di sicurezza automatizzata (Slither, Mythril, Echidna) come parte della tua pipeline CI/CD -- non solo prima degli audit
  • Conduci revisioni di sicurezza interne con una checklist che copra tutte e dieci le categorie di vulnerabilita di questa guida
  • Usa la verifica formale per invarianti matematici critici come la conservazione dei token e i rapporti di collaterale
  • Deploya su testnet ed esegui periodi di test estesi con monitoraggio prima del deployment su mainnet
  • Implementa aggiornabilita o circuit breaker che ti permettano di rispondere a vulnerabilita scoperte
  • Stabilisci un programma di bug bounty con ricompense significative proporzionali al valore che i tuoi contratti proteggono
  • Monitora i tuoi contratti post-deployment con alerting automatizzato per pattern di transazione insoliti

Quando Richiedere un Audit Professionale

Un audit di sicurezza professionale dovrebbe essere considerato obbligatorio per qualsiasi contratto che gestira valore significativo. Ma non tutti gli audit sono uguali, e il timing conta. Fare l'audit troppo presto -- prima che il codice sia stabile -- spreca denaro poiche i risultati diventano obsoleti con ogni modifica. Fare l'audit troppo tardi -- appena prima del lancio -- non lascia tempo per affrontare adeguatamente i risultati.

Il timing ideale e dopo che il codebase e feature-complete, dopo che le revisioni interne e l'analisi automatizzata sono state condotte, e con abbastanza margine prima del lancio per affrontare i risultati e ottenere una ri-revisione. Prevedi almeno 4-6 settimane per l'audit iniziale e 2-3 settimane per la ri-revisione delle correzioni.

Quando valuti le societa di audit, cerca team con esperienza specifica nel dominio del tuo protocollo -- prestiti DeFi, AMM, bridge, marketplace NFT e sistemi di governance hanno ciascuno pattern di vulnerabilita unici. Le migliori societa di audit combinano strumenti automatizzati, revisione manuale del codice da parte di piu auditor indipendenti e modellazione di attacchi economici.

Considera di ingaggiare piu societa di audit per protocolli ad alto valore. Diversi auditor hanno punti di forza e punti ciechi diversi, e una vulnerabilita critica trovata dal secondo auditor che il primo ha mancato puo far risparmiare milioni.

La sicurezza degli smart contract non e un'attivita una tantum -- e una disciplina continua che copre l'intero ciclo di vita dello sviluppo. Le dieci vulnerabilita descritte in questa guida rappresentano la maggior parte dei fondi persi negli exploit blockchain, e ciascuna e prevenibile con progettazione, testing e revisione adeguati.

Smart Contract Vulnerability Layers

In Xcapit, il nostro team di cybersecurity combina profonda competenza sugli smart contract con la certificazione ISO 27001 e anni di esperienza in blockchain in produzione. Dagli audit di sicurezza e penetration testing alla costruzione di processi di sviluppo security-first, aiutiamo i progetti blockchain a proteggere i loro utenti e la loro reputazione. Scopri di piu sui nostri servizi di cybersecurity.

Share
Fernando Boiero

Fernando Boiero

CTO & Co-Fondatore

Oltre 20 anni nell'industria tecnologica. Fondatore e direttore di Blockchain Lab, professore universitario e PMP certificato. Esperto e thought leader in cybersecurity, blockchain e intelligenza artificiale.

Costruiamo qualcosa di grande

IA, blockchain e software su misura — pensato per il tuo business.

Contattaci

Stai costruendo su blockchain?

Tokenizzazione, smart contract, DeFi — li abbiamo realizzati tutti.

Articoli Correlati

·11 min

Costruire Pipeline DevSecOps per Progetti Blockchain

Come progettare e implementare una pipeline DevSecOps pensata specificamente per lo sviluppo blockchain — analisi statica di smart contract, pipeline di audit automatizzate, gestione dei segreti, automazione del deployment e monitoraggio post-deployment.