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.