Libc Protections
Last updated
Last updated
Impara e pratica l'Hacking su AWS: HackTricks Training AWS Red Team Expert (ARTE) Impara e pratica l'Hacking su GCP: HackTricks Training GCP Red Team Expert (GRTE)
Malloc alloca memoria in gruppI di 8 byte (32-bit) o 16 byte (64-bit). Ciò significa che la fine dei chunk nei sistemi a 32-bit dovrebbe allinearsi con 0x8, e nei sistemi a 64-bit con 0x0. La funzionalità di sicurezza controlla che ogni chunk si allinei correttamente a queste posizioni specifiche prima di utilizzare un puntatore da un bin.
L'applicazione dell'allineamento dei chunk nei sistemi a 64-bit migliora significativamente la sicurezza di Malloc limitando il posizionamento dei chunk falsi a solo 1 su ogni 16 indirizzi. Ciò complica gli sforzi di exploit, specialmente in scenari in cui l'utente ha un controllo limitato sui valori di input, rendendo gli attacchi più complessi e difficili da eseguire con successo.
Attacco Fastbin su __malloc_hook
Le nuove regole di allineamento in Malloc ostacolano anche un attacco classico che coinvolge il __malloc_hook
. Precedentemente, gli attaccanti potevano manipolare le dimensioni dei chunk per sovrascrivere questo puntatore di funzione e ottenere esecuzione di codice. Ora, il rigoroso requisito di allineamento garantisce che tali manipolazioni non siano più valide, chiudendo una via comune di exploit e potenziando la sicurezza complessiva.
Il Mascheramento dei Puntatori è un potenziamento della sicurezza utilizzato per proteggere i puntatori Fd di fastbin e tcache nelle operazioni di gestione della memoria. Questa tecnica aiuta a prevenire certe tattiche di exploit di memoria, in particolare quelle che non richiedono informazioni di memoria divulgate o che manipolano direttamente le posizioni di memoria relative a posizioni conosciute (sovrascritture relative).
Il cuore di questa tecnica è una formula di oscuramento:
Nuovo_Ptr = (L >> 12) XOR P
L è la Posizione di Archiviazione del puntatore.
P è il vero puntatore Fd di fastbin/tcache.
La ragione dello spostamento bitwise della posizione di archiviazione (L) di 12 bit a destra prima dell'operazione XOR è critica. Questa manipolazione affronta una vulnerabilità intrinseca nella natura deterministica dei 12 bit meno significativi degli indirizzi di memoria, che sono tipicamente prevedibili a causa dei vincoli dell'architettura di sistema. Spostando i bit, la parte prevedibile viene esclusa dall'equazione, migliorando la casualità del nuovo puntatore mascherato e proteggendo così contro exploit che si basano sulla prevedibilità di questi bit.
Questo puntatore mascherato sfrutta la casualità esistente fornita dalla Randomizzazione dello Spazio degli Indirizzi (ASLR), che randomizza gli indirizzi utilizzati dai programmi per rendere difficile agli attaccanti prevedere la disposizione della memoria di un processo.
Demascherare il puntatore per recuperare l'indirizzo originale coinvolge l'utilizzo della stessa operazione XOR. Qui, il puntatore mascherato è trattato come P nella formula e, quando XORato con la posizione di archiviazione invariata (L), si ottiene il puntatore originale. Questa simmetria nel mascheramento e demascheramento garantisce che il sistema possa codificare e decodificare efficientemente i puntatori senza un overhead significativo, aumentando notevolmente la sicurezza contro attacchi che manipolano i puntatori di memoria.
Il mascheramento dei puntatori mira a prevenire sovrascritture parziali e complete dei puntatori nell'heap, un miglioramento significativo in termini di sicurezza. Questa funzionalità influisce sulle tecniche di exploit in diversi modi:
Prevenzione delle Sovrascritture Relative di Byte: Precedentemente, gli attaccanti potevano modificare parte di un puntatore per reindirizzare i chunk dell'heap a posizioni diverse senza conoscere gli indirizzi esatti, una tecnica evidente nell'exploit House of Roman senza leak. Con il mascheramento dei puntatori, tali sovrascritture relative senza un leak dell'heap richiedono ora un attacco di forza bruta, riducendo drasticamente la probabilità di successo.
Aumento della Difficoltà degli Attacchi ai Bin Tcache/Fastbin: Gli attacchi comuni che sovrascrivono i puntatori di funzione (come __malloc_hook
) manipolando le voci fastbin o tcache sono ostacolati. Ad esempio, un attacco potrebbe coinvolgere il leak di un indirizzo LibC, il rilascio di un chunk nel bin tcache e quindi la sovrascrittura del puntatore Fd per reindirizzarlo a __malloc_hook
per l'esecuzione di codice arbitrario. Con il mascheramento dei puntatori, questi puntatori devono essere correttamente mascherati, necessitando di un leak dell'heap per una manipolazione accurata, elevando così la barriera di exploit.
Necessità di Leak dell'Heap in Posizioni non-Heap: Creare un chunk falso in aree non-heap (come lo stack, la sezione .bss o PLT/GOT) ora richiede anche un leak dell'heap a causa della necessità di mascheramento dei puntatori. Ciò estende la complessità nell'exploit di queste aree, simile alla necessità di manipolare gli indirizzi LibC.
Rendere più Complicato il Leak degli Indirizzi dell'Heap: Il mascheramento dei puntatori limita l'utilità dei puntatori Fd nei bin fastbin e tcache come fonti di leak degli indirizzi dell'heap. Tuttavia, i puntatori nei bin non ordinati, piccoli e grandi rimangono non mascherati, quindi ancora utilizzabili per il leak degli indirizzi. Questo spinge gli attaccanti a esplorare questi bin per informazioni sfruttabili, anche se alcune tecniche potrebbero ancora consentire di demascherare i puntatori prima di un leak, sebbene con vincoli.
Per una migliore spiegazione del processo controlla il post originale da qui.
La formula utilizzata per mascherare e demascherare i puntatori è:
Nuovo_Ptr = (L >> 12) XOR P
Dove L è la posizione di archiviazione e P è il puntatore Fd. Quando L viene spostato a destra di 12 bit, si ottengono i bit più significativi di P, a causa della natura di XOR, che restituisce 0 quando i bit vengono XORati con se stessi.
Passaggi Chiave nell'Algoritmo:
Leak Iniziale dei Bit più Significativi: XORando il L spostato con P, si ottengono efficacemente i primi 12 bit di P poiché la parte spostata di L sarà zero, lasciando invariati i bit corrispondenti di P.
Recupero dei Bit del Puntatore: Poiché XOR è reversibile, conoscere il risultato e uno degli operandi consente di calcolare l'altro operando. Questa proprietà è utilizzata per dedurre l'intero set di bit per P XORando successivamente set di bit con parti del puntatore mascherato.
Demascheramento Iterativo: Il processo viene ripetuto, ogni volta utilizzando i bit di P appena scoperti dal passaggio precedente per decodificare il segmento successivo del puntatore mascherato, fino a quando tutti i bit sono recuperati.
Gestione dei Bit Deterministici: I 12 bit finali di L vengono persi a causa dello spostamento, ma sono deterministici e possono essere ricostruiti dopo il processo.
Puoi trovare un'implementazione di questo algoritmo qui: https://github.com/mdulin2/mangle
Pointer guard è una tecnica di mitigazione degli exploit utilizzata in glibc per proteggere i puntatori alle funzioni memorizzate, in particolare quelli registrati dalle chiamate di libreria come atexit()
. Questa protezione coinvolge la mescolanza dei puntatori tramite XOR con un segreto memorizzato nei dati del thread (fs:0x30
) e l'applicazione di una rotazione bit a bit. Questo meccanismo mira a impedire agli attaccanti di dirottare il flusso di controllo sovrascrivendo i puntatori alle funzioni.
Comprensione delle Operazioni di Pointer Guard: La mescolanza dei puntatori avviene utilizzando la macro PTR_MANGLE
che esegue l'XOR del puntatore con un segreto a 64 bit e poi esegue una rotazione a sinistra di 0x11 bit. L'operazione inversa per recuperare il puntatore originale è gestita da PTR_DEMANGLE
.
Strategia di Attacco: L'attacco si basa su un approccio di testo noto, dove l'attaccante deve conoscere sia la versione originale che quella mescolata di un puntatore per dedurre il segreto usato per la mescolanza.
Sfruttare i Testi Noto:
Identificare i Puntatori alle Funzioni Fissi: Esaminando il codice sorgente di glibc o le tabelle dei puntatori alle funzioni inizializzate (come __libc_pthread_functions
), un attaccante può trovare puntatori alle funzioni prevedibili.
Calcolare il Segreto: Utilizzando un puntatore alle funzioni noto come __pthread_attr_destroy
e la sua versione mescolata dalla tabella dei puntatori alle funzioni, il segreto può essere calcolato ruotando all'indietro (rotazione a destra) il puntatore mescolato e quindi facendo l'XOR con l'indirizzo della funzione.
Testi Alternativi: L'attaccante può anche sperimentare la mescolanza dei puntatori con valori noti come 0 o -1 per vedere se questi producono pattern identificabili in memoria, rivelando potenzialmente il segreto quando questi pattern vengono trovati negli snapshot di memoria.
Applicazione Pratica: Dopo aver calcolato il segreto, un attaccante può manipolare i puntatori in modo controllato, bypassando essenzialmente la protezione Pointer Guard in un'applicazione multithread con la conoscenza dell'indirizzo di base di libc e la capacità di leggere posizioni di memoria arbitrarie.