ASLR (Address Space Layout Randomization)

Indice dei contenuti

    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

    RegioneDescrizione
    StackBase dello stack del thread principale e dei thread secondari.
    HeapIndirizzo iniziale dell’heap restituito da brk()/mmap().
    Librerie condiviseBase address di ogni .so / .dll caricata (libc, ld, ecc.).
    EseguibileSolo se compilato come PIE (Position-Independent Executable); altrimenti fisso.
    mmap anonimeAree 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:

    PiattaformaEntropia stackEntropia 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.

    Ultimo aggiornamento: