Sicurezza seria: GnuTLS segue OpenSSL, corregge il bug di attacco temporale

Sicurezza seria: GnuTLS segue OpenSSL, corregge il bug di attacco temporale

Nodo di origine: 1956368

La scorsa settimana, abbiamo scritto di un mucchio di bug di gestione della memoria che sono stati corretti nell'ultimo aggiornamento di sicurezza della popolare libreria di crittografia OpenSSL.

Insieme a quei bug di memoria, abbiamo anche segnalato un bug soprannominato CVE-2022-4304: Timing Oracle nella decrittazione RSA.

In questo bug, sparare lo stesso messaggio crittografato più e più volte su un server, ma modificando il riempimento alla fine dei dati per rendere i dati non validi, provocando così una sorta di comportamento imprevedibile...

…non richiederebbe una quantità di tempo consistente, supponendo che tu fossi vicino all'obiettivo sulla rete da poter indovinare in modo affidabile quanto tempo impiegherebbe la parte del processo di trasferimento dei dati.

Non tutti i dati vengono elaborati allo stesso modo

Se si attiva una richiesta, si calcola quanto tempo impiega la risposta e si sottrae il tempo impiegato nell'invio e nella ricezione di basso livello dei dati di rete, si sa quanto tempo ha impiegato il server per eseguire il calcolo interno per elaborare la richiesta .

Anche se non sei sicuro di quanto tempo viene utilizzato nella rete, puoi cercare variazioni nei tempi di andata e ritorno inviando molte richieste e raccogliendo un sacco di campioni.

Se la rete è abbastanza affidabile da presumere che l'overhead di rete sia in gran parte costante, potresti essere in grado di utilizzare metodi statistici per dedurre quale tipo di modifica dei dati causa quale tipo di ritardo di elaborazione aggiuntivo.

Da questo, molti possono dedurre qualcosa sulla struttura, o anche sul contenuto, dei dati originali non crittografati che dovrebbero essere tenuti segreti all'interno di ogni richiesta ripetuta.

Anche se puoi estrarre solo un byte di testo in chiaro, beh, non dovrebbe succedere.

Cosiddetto attacchi a tempo di questo tipo sono sempre fastidiosi, anche se potresti dover inviare milioni di pacchetti fasulli e calcolarli tutti per avere qualche possibilità di recuperare anche solo un byte di dati in chiaro...

…perché le reti sono più veloci, più prevedibili e in grado di gestire molto più carico rispetto a pochi anni fa.

Potresti pensare che milioni di pacchetti infidi ti abbiano inviato spam, diciamo, l'ora successiva risalterebbero come una specie di pollice.

Ma "un milione di pacchetti all'ora in più o in meno rispetto al solito" semplicemente non è più una variazione particolarmente ampia.

Bug "oracolo" simile in GnuTLS

Bene, la stessa persona che ha segnalato il bug di temporizzazione del bug risolto all'ultimo in OpenSSL ha riportato anche a bug simile in GnuTLS all'incirca nello stesso momento.

Questo ha l'identificatore del bug CVE-2023-0361.

Sebbene GnuTLS non sia così popolare o ampiamente utilizzato come OpenSSL, probabilmente hai una serie di programmi nel tuo patrimonio IT, o anche sul tuo computer, che lo utilizzano o lo includono, possibilmente inclusi FFmpeg, GnuPG, Mplayer, QEMU , Rdesktop, Samba, Wget e Wireshark.

Ironia della sorte, il difetto di temporizzazione in GnuTLS è apparso nel codice che avrebbe dovuto registrare gli errori di attacco di temporizzazione in primo luogo.

Come puoi vedere dalla differenza di codice (diff) di seguito, il programmatore era a conoscenza del fatto che qualsiasi condizionale (if ... then) utilizzata per controllare e gestire un errore di decrittazione potrebbe produrre variazioni di temporizzazione, poiché le CPU generalmente impiegano una quantità di tempo diversa a seconda del modo in cui il codice va dopo un'istruzione "ramo".

(Ciò è particolarmente vero per un ramo che spesso va in una direzione e raramente nell'altra, perché le CPU tendono a ricordare, o memorizzare nella cache, il codice che viene eseguito ripetutamente per migliorare le prestazioni, rendendo così il codice preso di rado eseguito in modo rilevabilmente più lento.)

Codice diff di gnutls-3.7.8/lib/auth/rsa.c rispetto a 3.7.9

Ma il programmatore voleva comunque registrare che potrebbe essere in corso un attacco, cosa che accade se il file if (ok) il test precedente fallisce e si dirama nel file else { ... } .

A questo punto, il codice chiama il _gnutls_debug_log() funzione, che potrebbe richiedere un po' di tempo per fare il suo lavoro.

Pertanto il codificatore ha inserito una chiamata deliberata a _gnutls_no_log() nel then { ... } parte del codice, che finge di registrare un "attacco" quando non ce n'è uno, per cercare di pareggiare il tempo che il codice trascorre in entrambe le direzioni che il if (ok) l'istruzione di ramo può richiedere.

Apparentemente, tuttavia, i due percorsi di codice non erano sufficientemente simili nel tempo in cui si esaurirono (o forse il _gnutls_debug_log() funzione da sola non era sufficientemente coerente nel gestire diversi tipi di errore) e un utente malintenzionato potrebbe iniziare a distinguere le spie di decrittazione dopo circa un milione di tentativi.

Cosa fare?

Se sei un programmatore: la correzione del bug qui era semplice e seguiva il principio "less is more".

Il codice in rosa sopra, che si riteneva comunque non fornisse dati di rilevamento degli attacchi terribilmente utili, è stato semplicemente cancellato, sulla base del fatto che il codice che non c'è non può essere compilato per errore, indipendentemente dalle impostazioni di compilazione...

…e il codice che non è compilato non può mai essere eseguito, sia per caso che per progetto.

Se sei un utente GnuTLS: la versione recentemente rilasciata 3.7.9 e il “nuovo gusto del prodotto” 3.8.0 includere questa correzione, insieme a varie altre.

Se stai eseguendo una distribuzione Linux, verifica la presenza di aggiornamenti per qualsiasi versione di libreria condivisa gestita centralmente di GnuTLS che possiedi, nonché per le app che portano con sé la propria versione.

Su Linux, cerca i file con il nome libgnutls*.so per trovare eventuali librerie condivise in giro e cercare gnutls-cli per trovare qualsiasi copia dell'utilità della riga di comando che è spesso inclusa nella libreria.

Puoi correre gnutls-cli -vv per scoprire quale versione di libgnutls è dinamicamente collegato a:

 $ gnutls-cli -vv gnutls-cli 3.7.9 <-- la mia distribuzione Linux ha ricevuto l'aggiornamento venerdì scorso (2023-02-10)

Timestamp:

Di più da Sicurezza nuda