giovedì 12 giugno 2014

A proposito di TrueCrypt su Windows

Lo so che il nome del blog è GNUrants e che Windows dovrebbe essere bandito da queste pagine, non per questo non si deve cercare di migliorare l'esperienza di utilizzo del Sistema Operativo di Redmond ricorrendo al Software Libero. Tra cui c'è anche il pacchetto di crittazione di partizioni e dischi rigidi TrueCrypt.

Recentemente TrueCrypt è stato al centro di una vicenda alquanto curiosa: la notizia non è proprio nuova (ma se leggete questo blog lo sapete che gli GNUrants si prendono il tempo necessario per scrivere bene i loro articoli) però, per chi vive sotto ad una roccia, sappiate che gli sviluppatori di TrueCrypt hanno deciso di interrompere lo sviluppo e lo hanno comunicato nella Home Page del progetto con tanto di guida su come si attiva BitLocker su Windows Vista/Windows 7.

La cosa buffa è che l'annuncio cita la fine del supporto a Windows XP come ragione della fine dello sviluppo di TrueCrypt ma è stato pubblicato quasi due mesi dopo la data dell'8 aprile 2014. La cosa ancora più buffa è che il 14 febbraio (San Valentino) è uscito il primo report dell'Open Crypto Audit Project: un progetto che, tramite il crowfunding, ha finanziato un audit completo del codice di TrueCrypt.

Siccome non sono molto bravo a speculare sulle ragioni politiche dietro le scelte operate dagli sviluppatori (lascio volentieri ad altri il compito di indossare cappelli di stagnola e puntare il dito verso i Tagliapietre di turno) mi limiterò a fare quello che mi riesce meglio: un'analisi tecnica di quello che hanno trovato gli ingegneri che hanno compiuto l'audit.

Questo primo report si è concentrato sul bootloader (il componente che permette l'avvio del computer da un volume criptato, essenziale per la FDE - Full Disk Encryption - ovvero la crittazione dell'intero disco, Sistema Operativo e Programmi inclusi).

Il report in questione è protetto da Copyright e non si può riprodurre in tutto o in parte senza l'esplicito consenso scritto di iSEC Partners Inc. Il progetto Open Crypto Audit però, in qualità di committente, ha deciso di rendere pubblico il PDF del report all'indirizzo seguente:

https://opencryptoaudit.org/reports/iSec_Final_Open_Crypto_Audit_Project_TrueCrypt_Security_Assessment.pdf

Chi non avesse tempo/voglia di leggere le 32 pagine del documento (e di studiare diversi libri su programmazione in C, crittografia, API di Windows ecc. ecc.) può leggere le righe seguenti per avere sott'occhio la versione TL:DR.

Il PDF chiarisce fin da subito che non ci sono vulnerabilità critiche in TrueCrypt, ma ci sono delle vulnerabilità nel bootloader che potrebbero essere sfruttate da un attaccante seriamente motivato a carpire i segreti gelosamente custoditi sul disco criptato.

Fine del TL:DR, ora si fa sul serio.

I due ingegneri che hanno preso visione del codice hanno trovato 8 vulnerabilità di grado medio e basso e 3 problemi che, pur non essendo delle vere e proprie vulnerabilità potrebbero essere fonti di vulnerabilità in futuro. Le vulnerabilità trovate sembrerebbero essere non intenzionali e frutto di errori nella scrittura del codice anziché di un deliberato atto di sabotaggio volto all'inserimento di backdoor (pagina 7 del report, ultimo paragrafo).

Gli 11 problemi rilevati sono poi stati classificati e ordinati in base a gravità e quindi presentati dal più grave al meno grave. Vediamo ora i quattro più gravi nell'ordine presentato dai relatori.

Algoritmo di derivazione della chiave per il Volume Header debole

Cominciamo col dire cosa si intende per "algoritmo di derivazione della chiave". In crittografia si definisce chiave una porzione di informazione (quasi sempre una sequenza di bit) che, opportunamente utilizzata, consente di passare da un messaggio in chiaro (leggibile) ad uno criptato (non leggibile). Gli algoritmi di derivazione della chiave prendono in input una porzione di informazione nota all'utente (la password), un sale (un'altra porzione di informazione nota ma che solitamente varia ad ogni utilizzo) e li utilizzano per ricavare una chiave crittografica in modo tale che sia difficile risalire alla password se si conosce solo il messaggio criptato.

TrueCrypt utilizza PBKDF2 come algoritmo di derivazione delle chiavi, lo stesso usato dal protocollo WPA2 per la criptazione delle comunicazioni WiFi. Affinché questo algoritmo sia sicuro occorre che il numero di iterazioni (ovvero il numero di volte in cui si ripete l'operazione di derivazione della chiave) sia piuttosto alto. Quanto alto? Difficile a dirsi: gli attacchi di tipo bruteforce sono tanto più efficaci quanto è più facile parallelizzare l'operazione di generazione e test delle chiavi. Con le potenze di calcolo delle attuali GPU ricavare una password da un singolo giro di MD5 può richiedere da pochi secondi a un minuto: due ATI radeon HD4870 in CrossFire hanno la capacità di generare 4 miliardi e 600 milioni di hash MD5 al secondo (fonte: http://www.golubev.com/about_cpu_and_gpu_2_en.htm ). Per contrastare una simile potenza di calcolo (che richiede un investimento inferiore ad un migliaio di Euro al momento in cui scrivo) sarebbero necessarie svariate centinaia di migliaia di iterazioni di PBKDF2. TrueCrypt usa un numero di iterazioni che va da 1000 a 2000 a seconda dei parametri scelti dall'utente.

La soluzione proposta nel breve termine è consentire all'utente di impostare manualmente il numero di iterazioni, quella a lungo termine di cambiare l'algoritmo di derivazione della chiave con un algoritmo che sia più ostile nei confronti delle GPU.

Informazioni sensibili potrebbero essere salvate nello swap

Nel caso in cui l'utente non abbia optato per la FDE ma solo per la criptazione di una porzione del disco sussiste il problema dei file di paging (o file di swap): quando la memoria RAM per i programmi in esecuzione si esaurisce il Sistema Operativo sposta alcune porzioni di memoria non utilizzate dalla RAM al disco rigido.

Un malintenzionato può causare una situazione in cui la vittima esaurisca la memoria RAM e, in un secondo tempo, ricavare informazioni sensibili (compresa la password per sbloccare i dati) dal file di paging.

TrueCrypt attua diversi meccanismi per prevenire questo, ma ci sono comunque dei casi in cui è possibile che ciò avvenga. Gli stessi sviluppatori sconsigliano di utilizzare TrueCrypt in questa configurazione e dicono chiaramente che l'utente dovrebbe optare per la criptazione dell'intero disco, compreso il file di paging.

A mio avviso questo è un non-problema: se uno è abbastanza paranoico da decidere di aver bisogno di TrueCrypt lo sarà anche abbastanza da usare la FDE e chiudere quindi la possibilità ad un malintenzionato di sfruttare lo swap.

Problemi multipli nello scompattatore del bootloader

Questo è un punto interessante, non per la vulnerabilità che espone ma per gli indizi che porta sulla qualità del codice del bootloader di TrueCrypt (tanto che i relatori hanno dedicato un'intera appendice a commentare i problemi che hanno rilevato nel modo in cui è scritto il compressore del bootloader e un'altra appendice alle problematiche che hanno riscontrato nel qualità con cui è scritto il resto del software).

In sintesi il codice che si occupa di decomprimere la porzione principale del codice del bootloader (quella che chiede all'utente la password e decripta il contenuto del disco) soffre di diversi problemi di programmazione:

  • Mescolanza di tipi signed e unsigned.
  • Accesso ad array senza controllare se ci si trova entro i limiti dell'array (con accesso a porzioni di memoria che non fanno parte dell'array stesso e relativi problemi).
  • Mancanza di controlli sui valori di ritorno per la presenza di codici di errore.
Questo genere di errori non ci dovrebbero essere in un software che si presume orientato alla sicurezza (e quindi al rigore del codice).

Uso di memset() per la pulizia di dati sensibili

Questo è un meta-problema nel senso che non è un problema di sicurezza esplicitamente dovuto al codice ma si presenta quando i compilatori fanno i furbi ed eliminano codice che loro considerano inutile.

Supponiamo di avere un codice simile:

char* roba_importante = calloc(sizeof(char), LUNGHEZZA_ROBA_IMPORTANTE);

/*Fai qualcosa con roba_importante*/

memset(roba_importante, 0, sizeof(roba_importante));

free(roba_importante);

La chiamata a memset ha lo scopo di pulire lo spazio di memoria di roba_importante prima di rilasciare la memoria con free(roba_importante);. Non vogliamo che altre porzioni del programma (o peggio ALTRI programmi) accedano a quelle informazioni e quindi le cancelliamo.

Il problema è che i compilatori di adesso sono tarati per produrre codice che giri velocemente e quindi effettuano tutta una serie di ottimizzazioni tra cui l'eliminazione di codice ritenuto inutile. Quando il compilatore vede che noi liberiamo roba_importante e non la utilizziamo più lui elimina la chiamata a memset perché così il programma girerà più velocemente. Peccato che quella chiamata noi non la vogliamo eliminare perché ci serve a proteggere delle informazioni importanti.

La soluzione a questo problema consiste nel utilizzare altre funzioni scritte ad hoc per la pulizia della memoria (come explicit_bzero() di OpenBSD). Gli sviluppatori di TrueCrypt hanno scritto la funzione burn() a tale scopo ma ci sono porzioni di codice che non ne fanno uso (probabilmente rimasugli di vecchio codice oppure contributi di codice da altre fonti che non sono stati adeguatamente adattati prima dell'inserimento nella base di codice principale).

Conclusioni

Il codice di TrueCrypt non sembrerebbe contenere vulnerabilità critiche, ma questo non è una ragione per festeggiare: il codice andrebbe ripulito e ricontrollato per eliminare diversi problemi dovuti probabilmente a distrazioni degli sviluppatori. Inoltre il codice per essere compilato sotto Windows dipende da un mix di vecchi compilatori Microsoft (VC++ 1.52 rilasciato nel 1993!) e tools di GNU portati sull'OS di Redmond. Una simile toolchain, oltre ad essere difficile da installare e configurare, richiede di accedere a risorse online che potrebbero scomparire (quanti di voi sanno da dove scaricare una versione così vetusta di Visual C++?).

Forse gli sviluppatori di TrueCrypt sapevano che non avrebbero passato l'audit e si sono ritirati dalla competizione. Ma molto probabilmente non lo sapremo mai perché hanno fatto di tutto per restare anonimi.