Attacco di divulgazione di informazioni, utilizzando un overflow di heap

6

Una tipica strategia per sconfiggere ASLR consiste nel trovare sia un bug di overflow del buffer che un bug di divulgazione delle informazioni. Ma quando si attaccano server che vengono riavviati automaticamente ogni volta che si arrestano / muoiono, è sufficiente un bug di overflow del buffer? Possiamo usare quel bug di overflow del buffer per darci anche la capacità di divulgazione delle informazioni?

Permettimi di arricchire lo scenario. Supponiamo che abbia un programma server che elabora una richiesta dalla rete e che verrà automaticamente riavviato in caso di arresto anomalo e supponiamo di aver trovato una vulnerabilità di sovraccarico del buffer (di un buffer allocata nell'heap B ) nel server che posso sfruttare in modo affidabile inviando una richiesta appropriatamente predisposta al server. Supponiamo anche di poter rilevare quando il server si arresta in modo anomalo (ad esempio, potrebbe bloccarsi perché gli ho inviato una richiesta che ha danneggiato la memoria e causato la segfault; in ogni caso, suppongo di poter inviare una richiesta di mia scelta e determinare se si è bloccato o meno durante il tentativo di gestire tale richiesta). Il server sta usando ASLR e voglio derandomizzare ASLR in modo da poter montare un attacco per l'iniezione di codice, ma non conosco un bug di divulgazione delle informazioni separato - la vulnerabilità di sovraccarico del buffer è tutto ciò con cui devo lavorare.

Posso utilizzare questa vulnerabilità di sovraccarico del buffer per la divulgazione di informazioni, per apprendere il contenuto della memoria dopo B ?

Ecco un esempio del tipo di attacco che sto immaginando:

Suppose that the overflowable buffer B is 512 bytes long, and suppose there is a secret 8-byte pointer P stored immediately after B. Suppose field F of the request is copied byte-for-byte over B without any length check.

If I send a request with a 513-byte value for F, that'll be copied over B. If the 513th byte of my value differs from the first byte of P, then the value of P will be corrupted, and (assuming the program later dereferences P) then program will probably crash during processing of this request. On the other hand, if the 513 byte of my value matches the first byte of P, then P will remain unchanged, and the program will probably not crash.

So, I can imagine sending 256 requests, each with a different value for the 513th byte of field F; if 255 of them cause the server to crash and one does not, then I immediately know the value of the first byte of P. Now I can continue until I learn each of the bytes of P. This might be useful if the program is using ASLR: by learning the value of the pointer P, I can derandomize part of memory.

Questo è solo un semplice esempio. In pratica, immagino che ci possa essere spazio inutilizzato dopo la fine di B e prima del prossimo oggetto archiviato nell'heap, ma puoi immaginare modi per adattare queste tecniche per gestire anche quella situazione (ad esempio, se il byte dopo che B non è stato utilizzato, puoi sovrascriverlo con qualsiasi cosa e il server non si arresta in modo anomalo, quindi è facile rilevare posizioni non utilizzate e continuare l'attacco fino a trovare l'oggetto successivo dopo B ).

Questo attacco funziona in pratica? Fornisce un modo efficace per sconfiggere ASLR, quando si verifica un overflow dell'heap in un server che viene riavviato automaticamente e quando si ha un modo per rilevare gli arresti anomali?

Ci sono degli ostacoli che ho trascurato che impediscono il corretto funzionamento? Per esempio, posso immaginare che se l'allocazione di memoria per gli oggetti nell'heap fosse non deterministica e casuale, l'attacco fallirebbe; ma le piattaforme lo fanno? Gli offset relativi tra gli oggetti nell'heap deterministico in pratica, se si esegue lo stesso programma due volte sugli stessi ingressi?

Suppongo che l'overflow del buffer consenta di sovrascrivere B con dati binari arbitrari totalmente sotto il controllo dell'attaccante. (L'attacco non funzionerà con un strcpy() o un overflow legato alla stringa, dal momento che i dati sono forzati ad essere nul-terminati.) Inoltre, supponiamo che il server sia riavviato usando fork (), o per qualche altra ragione, parte del layout della memoria è la stessa ogni volta che il server viene riavviato. (Ad esempio, questo si mantiene automaticamente su Windows e Mac, dal momento che le librerie si trovano allo stesso indirizzo di base ogni volta che si riavvia il server, e mantiene i processi non PIE su Linux.)

Credito: mi ispiro a un metodo di cui ho letto di recente per sfruttare un bug di overflow del buffer di un buffer allocato allo stack ai fini della divulgazione di informazioni. Questo è stato descritto nel documento Blind ROP pubblicato di recente su IEEE Security & Privacy 2014. Mostrano come farlo quando il buffer B è allocato nello stack. In questa domanda, sto chiedendo se la loro tecnica può essere generalizzata al caso in cui il buffer B è nell'heap.

    
posta D.W. 29.05.2014 - 00:13
fonte

1 risposta

5

Come si nota, dopo ogni tentativo fallito, il programma si blocca. A seconda del sistema operativo / robustezza dell'implementazione ASLR e di come il programma viene riavviato, ciò potrebbe comportare:

  1. lo stesso layout (ad esempio se fork per exec viene utilizzato per riavviare il programma);
  2. un layout parzialmente diverso (ad esempio indirizzi di codice non librerie per eseguibili non-PIE su Linux, o per indirizzi di codici libreria su alcune (forse tutte?) versioni di Windows e Mac OS X);
  3. un layout completamente casuale (ad esempio per un eseguibile PIE Linux).

Pertanto, se il valore che stai cercando di indovinare non è statico tra i riavvii del programma, puoi determinare se hai indovinato correttamente, ma non appena indovini in modo errato, il programma si riavvia e non hai più alcuna informazione; quindi, non guadagni nulla indovinando in modo incrementale.

Chiaramente ASLR non fornisce alcuna protezione assoluta, e la sua efficacia è particolarmente limitata quando solo alcune aree sono randomizzate o lo stesso layout è usato in più esecuzioni di programmi, ma sembra che fare un attacco generico con un overflow dell'heap che non dipendere da dettagli molto specifici del programma in questione, come fatto con gli overflow dello stack nel documento Blind ROP, sarebbe piuttosto difficile.

    
risposta data 29.05.2014 - 04:44
fonte

Leggi altre domande sui tag