Come è possibile l'exploit di Heartbleed?

122

Ho letto la vulnerabilità di Heartbleed OpenSSL e capisco il concetto. Tuttavia ciò che non capisco è la parte in cui passiamo 64k come lunghezza e il server restituisce 64kb di dati casuali perché non controlla se abbiamo davvero passato 64kb di echo o 1 byte.

Ma come è possibile che un processo su un server restituisca 64kb di dati casuali dalla RAM?

Il sistema operativo non dovrebbe impedire l'accesso alla RAM reale e consentire solo l'accesso alla memoria virtuale in cui un processo non può accedere ai contenuti di memoria di altri processi?

OpenSSL funziona in modalità kernel e quindi ha accesso a tutta la RAM?

Mi aspetterei un errore di segmentazione se un processo tentasse di accedere a qualsiasi memoria che non allocava esplicitamente. Posso capire di ottenere 64kb di dati casuali dal processo che sta eseguendo il programma OpenSSL stesso, ma non vedo come possa persino vedere la RAM completa del server per poterla inviare al client.

UPDATE: @ commento di paj28, sì, era proprio la falsa informazione che mi ha portato a chiedermi questo. Come hai detto tu, anche l'advisory ufficiale di heartbleed.com lo esprime in modo fuorviante (anche se direi che lo hanno fatto perché è destinato a un pubblico molto più ampio di noi tecnici e volevano mantenerlo semplice)

Per riferimento, ecco come lo dice heartbleed.com (enfasi mia):

The Heartbleed bug allows anyone on the Internet to read the memory of the systems protected by the vulnerable versions of the OpenSSL software.

Per qualsiasi persona tecnica che implichi la RAM completa della macchina virtuale / fisica.

    
posta Talha Sayed 10.10.2016 - 22:03
fonte

2 risposte

207
Il commento di

@ paj28 copre il punto principale. OpenSSL è una libreria condivisa, quindi viene eseguita nello stesso spazio di indirizzamento in modalità utente del processo che la utilizza. Non può vedere la memoria di altri processi; tutto ciò che suggeriva il contrario era sbagliato.

Tuttavia, la memoria utilizzata da OpenSSL, il materiale che probabilmente si trova vicino al buffer di cui Heartbleed ha superato la lettura, è pieno di dati sensibili. In particolare, è probabile che contenga sia il testo cifrato sia il testo in chiaro di tutte le trasmissioni recenti o imminenti. Se attacchi un server, questo significa che vedrai i messaggi inviati al server da altri e le risposte del server a quei messaggi. Questo è un buon modo per rubare i token di sessione e le informazioni private e probabilmente catturerai anche le credenziali di accesso di qualcuno. Altri dati memorizzati da OpenSSL includono chiavi di crittografia simmetriche (utilizzate per la crittografia e integrità dei dati di massa tramite TLS) e chiavi private (utilizzate per dimostrare l'identità del server). Un utente malintenzionato che ruba chi può origliare (e persino modificare) la comunicazione TLS compromessa in tempo reale o impersonare con successo il server, rispettivamente (assumendo una posizione man-in-the-middle sulla rete).

Ora, c'è una cosa strana su Heartbleed che lo rende peggiore di quanto ci si potrebbe aspettare. Normalmente, ci sarebbero buone probabilità che se provi a leggere 64k di dati a partire da un indirizzo heap arbitrario all'interno di un processo, ti imbatterai in un indirizzo di memoria non allocato (memoria virtuale non supportata da nulla e quindi inutilizzabile) piuttosto velocemente. Questi buchi in uno spazio di indirizzamento del processo sono piuttosto comuni, perché quando un processo libera memoria che non ha più bisogno, il sistema operativo recupera quella memoria in modo che altri processi possano utilizzarla. A meno che il tuo programma non stia perdendo memoria come un setaccio, di solito non ci sono molti dati in memoria oltre a quelli attualmente in uso. Il tentativo di leggere la memoria non allocata (ad esempio, il tentativo di accedere alla memoria che è stata liberata) causa una violazione di accesso in lettura (su Windows) / errore di segmentazione (su * nix), che causerà un arresto anomalo del programma (e si blocca prima di poterlo fare) qualsiasi cosa come inviare i dati indietro). È ancora sfruttabile (come un attacco denial-of-service), ma non è così male come lasciare che l'autore dell'attacco ottenga tutti quei dati.

Con Heartbleed, il processo non si arrestava quasi mai. Si scopre che OpenSSL, apparentemente decidendo che le librerie di gestione della memoria della piattaforma erano troppo lente (o qualcosa del genere, non ho intenzione di provare a giustificare questa decisione), pre-alloca una grande quantità di memoria e quindi usa le proprie funzioni di gestione della memoria al suo interno. Questo significa alcune cose:

  • Quando OpenSSL "libera" la memoria, in realtà non viene liberato per quanto riguarda il sistema operativo, in modo che la memoria rimanga utilizzabile dal processo. Il gestore di memoria interno di OpenSSL potrebbe pensare che la memoria non sia allocata, ma per quanto riguarda il sistema operativo, il processo di utilizzo di OpenSSL conserva ancora quella memoria.
  • Quando OpenSSL "libera" la memoria, a meno che non cancelli esplicitamente i dati prima di chiamare la sua funzione free , quella memoria conserva i valori che aveva prima di essere "liberata". Ciò significa che molti dati che non sono ancora in uso possono essere letti.
  • L'heap di memoria utilizzato da OpenSSL è contiguo; non ci sono lacune al suo interno per quanto riguarda il sistema operativo. È quindi molto improbabile che la sovrascrittura del buffer venga eseguita in una pagina non allocata, quindi è improbabile che si verifichi un arresto anomalo.
  • L'uso della memoria di OpenSSL ha una localizzazione molto alta - cioè, è concentrato all'interno di un intervallo relativamente piccolo di indirizzi (il blocco pre-allocato) - piuttosto che essere diffuso nello spazio degli indirizzi in base al capriccio dell'alloggiamento di memoria del sistema operativo. Pertanto, la lettura di 64 KB di memoria (che non è molto, anche accanto a un processo tipico da 2 GB a 32 bit, molto meno l'enorme intervallo di un processo a 64 bit) è probabile che ottenga molti dati che sono attualmente (o era di recente) in uso, anche se i dati risiedono nel risultato di una serie di allocazioni presumibilmente separate.
risposta data 10.10.2016 - 22:44
fonte
6

I would expect a segmentation fault if a process tried to access any memory that it didn't explicitly allocate

Questo è dove si trova l'equivoco.

Qualsiasi accesso alla memoria spezzato potrebbe causare un errore di segmentazione, ma in realtà se l'indirizzo di memoria richiesto si trova nello spazio di indirizzamento del processo corrente (ad esempio, una variabile appena liberata), questo è altamente improbabile.

Ecco perché non dovresti fare affidamento sugli errori di segmentazione per trovare bug di accesso alla memoria!

    
risposta data 13.10.2016 - 11:05
fonte

Leggi altre domande sui tag