Nella narrazione comune, le Blockchain vengono rappresentate come oggetti in grado di assicurare elevati livelli di integrità e disponibilità. Sembrerebbe quindi che integrare una Blockchain tra le componenti software che costituiscono un’applicazione renda queste ultime automaticamente sicure. In realtà, la storia delle Blockchain è costellata di incidenti di sicurezza che hanno determinato, in non pochi casi, perdite milionarie da parte dei suoi utilizzatori.
Indice degli argomenti
Blockchain e cyber security: gli incidenti MtGox e DAO
Raramente però è stata la stessa Blockchain a rappresentare la componente debole sfruttata dagli attaccanti. Piuttosto sono spesso le componenti che si basano sulla Blockchain ad aver dato origine agli incidenti.
Nel caso di MtGox, ad esempio, la vulnerabilità sfuttata dagli attaccanti esterni era riferita al software che implementava il meccanismo di prelievo dei fondi dai wallet Bitcoin gestiti da questo Exchange. Gli implementatori infatti non avevano considerato una caratteristica specifica del protocollo Bitcoin (la malleabilità delle transazioni) che, utilizzata nel modo scorretto, aveva determinato la realizzazione dell’attacco.
Peculiare poi è il caso degli smart contract. In letteratura è nota infatti una vastissima casistica di attacchi realmente perpetrati a danni di applicazioni che basavano le proprie funzionalità su uno smart contract.
Il più eclatante tra questi è rappresentato dall’incidente occorso nel 2016 al progetto DAO (Decentralized Autonomous Organization), una delle primissime ICO basate su Ethereum. In questo incidente, un attaccante esterno aveva individuato una vulnerabilità nello smart contract della ICO e lo aveva sfruttato per sottrarre illecitamente fondi dall’organizzazione.
Anche in questo caso, gli elementi costitutivi e strutturali della Blockchain, come i meccanismi di autenticazione delle transazioni o l’algoritmo del consenso, risultavano funzionare in modo corretto.
In entrambi gli incidenti documentati si possono fare due importanti considerazioni. In primis, l’attaccante aveva individuato il pattern di attacco a partire da un errore di programmazione di una componente basata sulla Blockchain (i.e. la funzionalità di prelievo fondi di MtGox e lo smart contract del DAO).
Così come in qualsiasi attacco informatico, l’intento di un attaccante è infatti quello di condurre il programma verso uno stato inatteso o non previsto, nella speranza che in tale stato il software consenta all’attaccante di effettuare operazioni normalmente non autorizzate, aggirando i meccanismi di sicurezza implementati.
In particolare, nel caso del DAO, l’attaccante è riuscito a indurre uno stato dello smart contract in cui l’operazione di prelievo è stata interrotta in modo inatteso tra l’effettiva operazione di trasferimento fondi e l’aggiornamento dei libri contabili interni dello smart contract.
In questo modo l’operazione poteva essere effettuata ripetutamente attingendo dai fondi comuni dello smart contract. Un problema che in programmazione è comunemente noto come “re-entrancy issue”.
La seconda considerazione è che per via dell’immutabilità della Blockchain, spesso è tecnicamente difficoltoso reagire a un incidente di sicurezza che, nel caso di questo tipo di applicazioni, può determinare perdite finanziarie immediate e ingenti. In particolare, la seconda considerazione, sta orientando il mondo della sicurezza degli smart contract e della Blockchain in generale verso un approccio di tipo preventivo.
Le direzioni sono sostanzialmente due e, in entrambe, si cerca di mitigare il problema descritto nella prima considerazione.
Nello specifico, seppur con approcci diversi, lo scopo è quello di prevenire o almeno di rilevare in fase di sviluppo la presenza di stati imprevisti (e pericolosi) tra i possibili path di esecuzione del software. In altri termini, si cerca di interrompere, sin dal principio, la catena “Bug à Vulnerabilità à Exploit”.
L’approccio con metodologie di sviluppo “dichiarative”
Il primo approccio prevede l’impiego di metodologie di sviluppo di tipo “dichiarativo”. In pratica, lo smart contract viene “costruito” integrando componenti e utilizzando modelli preconfezionati che si assume siano sicuri. Tale assunzione trova fondamento nel fatto che il codice di tali componenti è stato sottoposto a audit da parte di esperti.
Il progetto principale in quest’ambito è Open Zeppelin: sfruttando in modo intelligente caratteristiche peculiari del linguaggio di sviluppo più diffuso nella comunità di Ethereum, Solidity, è possibile implementare smart contract attraverso poche righe di codice, le quali, letteralmente, dichiarano lo scopo del contratto e lasciano al compilatore l’onere di integrare i componenti di Open Zeppelin per creare il programma finale.
In questo modo, sarà sufficiente assicurarsi che la dichiarazione sia conforme alle aspettative dell’utente per ottenere un programma che è, in effetti, sicuro in quanto non contiene stati non previsti che presentino delle vulnerabilità.
Tale approccio, seppur efficace, sconta il fatto che esso è utilizzabile solo in domini applicativi che il progetto Open Zeppelin ha esplicitamente previsto. Ad esempio, mentre è molto semplice creare uno smart contract che funga da base per un token (in effetti, bastano 4 righe di codice) in quanto si utilizzano template predefiniti, più ostica è la creazione di un contratto afferente a un dominio diverso, come ad esempio, il gambling.
L’approccio dell’analisi del codice scritto
Un altro tipo di approccio prevede l’analisi del codice scritto dal programmatore per verificare l’assenza di stati imprevisti. Tale approccio è in effetti molto comune nello sviluppo software, in particolare nelle metodologie cosiddette “test-driven”. Tuttavia, il livello di assurance che tale pratica fornisce è relativamente basso.
In tale approccio, infatti, le funzionalità interne del software vengono testate generando input dell’applicazione in modo casuale o pre-determinato. È quindi scontato che questo approccio non consente di esaminare tutti i possibili path di esecuzione di un programma, ma solo quelli effettivamente generati.
La speranza è che la positività a questi test consenta di concludere sull’adeguatezza del software in termini generali. Tuttavia, come detto, si tratta di una mera speranza.
Nel mondo degli smart contract, proprio per via delle rilevanti implicazioni finanziarie, tale approccio potrebbe non essere considerato sufficiente. All’estremo opposto del test-driven development si trovano i cosiddetti metodi formali, che consentono di dimostrare con strumenti logico-matematico che nel programma non esistono stati imprevisti che possano condurre a vulnerabilità sfruttabili da un attaccante esterno.
Sebbene molto potenti, queste metodologie risultano estremamente onerose nell’applicazione concreta e sono ben pochi gli ambiti in cui vengono utilizzati, tipicamente quelli in cui ci possono essere in gioco vite umane.
L’approccio ibrido
Nel mondo degli smart contract si sta invece andando verso un approccio ibrido. In pratica, vengono definiti delle condizioni che il programma deve soddisfare, come l’assenza di un particolare stato pericoloso. Tali condizioni vengono poi testate su una traccia di esecuzione “simbolica” dell’applicazione, rappresentata da un albero di tutti i path di esecuzione possibili fino a un livello di profondità predefinito.
Definito tale albero, si dimostra matematicamente la violazione o meno delle condizioni definite in ogni path di esecuzione possibile.
In questo modo, seppur limitatamente al livello di profondità predefinito, si uniscono i vantaggi della validazione formale del codice (grazie all’esecuzione simbolica) a quelli del testing applicativo delle metodologie test-driven.
In ambito smart contract su piattaforma Ethereum, il progetto principale che sfrutta questo approccio è Mytrhil, basato sul motore di esecuzione simbolica “Laser” e il risolutore algebrico “Z3” di Microsoft.
Il risultato è un prodotto che può essere utilizzato alla stregua di uno strumento di vulnerability assessment tradizionale: all’interno di Mytrhil infatti sono definite decine e decine di condizioni di vulnerabilità descritte nella ricca letteratura di attacchi a smart contract di Ethereum.
Basta quindi applicare Mytrhil al proprio codice sorgente per rilevare gli errori più comuni e diffusi che conducono a vulnerabilità accertate. Inoltre, per i più coraggiosi, è possibile definire condizioni ad-hoc sulla logica applicativa dello specifico smart contract.
Conclusioni
In conclusione, sebbene il mondo della sicurezza delle applicazioni basate su Blockchain è ancora nella sua infanzia, la strada appare tracciata. E nonostante gli strumenti disponibili oggi siano poco maturi sotto il profilo della stabilità, essi sono senz’altro molto promettenti e solidi dal punto di vista dei fondamenti teorici.