L’Address Space Layout Randomization (ASLR) è una tecnica di difesa implementata a livello di sistema operativo che randomizza la posizione in memoria virtuale delle principali regioni di un processo ad ogni esecuzione. L’obiettivo è privare l’attaccante della conoscenza degli indirizzi necessari per costruire exploit basati su buffer overflow, heap overflow o return-oriented programming.
Motivazione
Le tecniche di exploit classiche (return-to-libc, ROP, shellcode injection) richiedono la conoscenza di indirizzi precisi: dove si trova system() in libc, dove inizia lo stack, dove sono i gadget nel binario. Senza ASLR, questi indirizzi sono deterministici e noti da una semplice analisi del binario. Con ASLR, ogni esecuzione produce un layout diverso.
Regioni randomizzate
| Regione | Descrizione |
|---|---|
| Stack | Base dello stack del thread principale e dei thread secondari. |
| Heap | Indirizzo iniziale dell’heap restituito da brk()/mmap(). |
| Librerie condivise | Base address di ogni .so / .dll caricata (libc, ld, ecc.). |
| Eseguibile | Solo se compilato come PIE (Position-Independent Executable); altrimenti fisso. |
| mmap anonime | Aree allocate con mmap(MAP_ANONYMOUS) da JIT compiler, allocatori, ecc. |
Entropia della randomizzazione
L’efficacia di ASLR dipende dal numero di bit randomizzati (entropia). Più è alta, meno è probabile indovinare un indirizzo:
| Piattaforma | Entropia stack | Entropia librerie |
|---|---|---|
| Linux x86 (32 bit) | ~16 bit | ~16 bit |
| Linux x86-64 | ~28 bit | ~28 bit |
| Windows 64 bit | ~17 bit (user) | ~17 bit |
| macOS (Apple Silicon) | ~32 bit | ~32 bit |
Su architetture a 32 bit, 16 bit di entropia sono vulnerabili a brute force: con ~65.536 tentativi, un attaccante trova l’indirizzo corretto. Su 64 bit, il brute force è computazionalmente impraticabile.
Configurazione su Linux
Linux espone il livello ASLR tramite /proc/sys/kernel/randomize_va_space:
cat /proc/sys/kernel/randomize_va_space
# 0 = disabilitato
# 1 = stack e librerie randomizzati (no heap)
# 2 = stack, heap e librerie randomizzati (raccomandato)
Limitazioni e tecniche di bypass
ASLR non è una protezione assoluta. Le principali tecniche di aggiramento sono:
Info leak
La vulnerabilità più comune per aggirare ASLR. Un attacco separato (es. format string, lettura out-of-bounds) rivela un indirizzo di memoria del processo. Dall’indirizzo letto, l’attaccante calcola il base address della regione (sottraendo l’offset noto) e costruisce la catena ROP con indirizzi corretti.
Partial overwrite
Su architetture little-endian, i byte meno significativi dell’indirizzo non sono randomizzati (allineamento di pagina). Un overflow parziale del return address (1–2 byte) non richiede la conoscenza del base address completo.
Brute force su 32 bit
Con entropia limitata, un daemon che si riavvia automaticamente può essere attaccato ripetutamente fino a indovinare il layout corretto.
Spraying
Riempire grandi aree di memoria (heap spray, JIT spray) con copie della catena di exploit aumenta la probabilità che un salto a indirizzo approssimato atterri nel codice dell’attaccante.
ASLR e PIE: una protezione combinata
ASLR da solo non randomizza il codice dell’eseguibile principale se questo è compilato senza PIE. Con un binario non-PIE, i gadget ROP nel codice principale hanno indirizzi fissi, rendendo inutile la randomizzazione delle librerie per costruire una catena che usa solo il binario stesso.
# Compilazione senza PIE (indirizzo base fisso, es. 0x400000)
gcc -no-pie -o target source.c
# Compilazione con PIE (base randomizzata da ASLR)
gcc -pie -fPIE -o target source.c
La combinazione ASLR + PIE + Stack Canary + NX costituisce la linea di base delle protezioni binarie sui sistemi moderni.
ASLR nel kernel
Il kernel stesso può beneficiare di randomizzazione tramite KASLR (Kernel ASLR): la posizione del codice kernel e dei moduli viene randomizzata al boot. Exploit di privilege escalation che puntano a funzioni kernel (es. commit_creds, prepare_kernel_cred) devono prima ottenere un info leak dal kernel — spesso tramite /proc/kallsyms, side-channel attack o vulnerabilità nel kernel stesso.