ASLR
Last updated
Ucz się i praktykuj Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Ucz się i praktykuj Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Randomizacja układu przestrzeni adresowej (ASLR) to technika bezpieczeństwa stosowana w systemach operacyjnych do losowego rozmieszczania adresów pamięci używanych przez procesy systemowe i aplikacje. Dzięki temu znacznie trudniej dla atakującego jest przewidzieć lokalizację konkretnych procesów i danych, takich jak stos, sterta i biblioteki, co zmniejsza ryzyko pewnych rodzajów ataków, zwłaszcza przepełnień bufora.
Aby sprawdzić stan ASLR w systemie Linux, można odczytać wartość z pliku /proc/sys/kernel/randomize_va_space
. Wartość przechowywana w tym pliku określa rodzaj zastosowanej randomizacji ASLR:
0: Brak randomizacji. Wszystko jest statyczne.
1: Konserwatywna randomizacja. Biblioteki współdzielone, stos, mmap(), strona VDSO są randomizowane.
2: Pełna randomizacja. Oprócz elementów randomizowanych przez konserwatywną randomizację, pamięć zarządzana przez brk()
jest randomizowana.
Możesz sprawdzić stan ASLR za pomocą następującej komendy:
Aby wyłączyć ASLR, ustaw wartość /proc/sys/kernel/randomize_va_space
na 0. Wyłączenie ASLR zazwyczaj nie jest zalecane poza sytuacjami testowymi lub debugowania. Oto jak to zrobić:
Możesz również wyłączyć ASLR dla wykonania za pomocą:
Aby włączyć ASLR, można zapisać wartość 2 do pliku /proc/sys/kernel/randomize_va_space
. Zazwyczaj wymaga to uprawnień roota. Pełna losowość może być osiągnięta za pomocą następującej komendy:
Zmiany dokonane za pomocą poleceń echo
są tymczasowe i zostaną zresetowane po ponownym uruchomieniu. Aby sprawić, że zmiana będzie trwała, musisz edytować plik /etc/sysctl.conf
i dodać lub zmodyfikować następującą linijkę:
Po edycji pliku /etc/sysctl.conf
zastosuj zmiany za pomocą:
To zapewni, że ustawienia ASLR pozostaną po ponownym uruchomieniu.
PaX dzieli przestrzeń adresową procesu na 3 grupy:
Kod i dane (zainicjowane i niezainicjowane): .text
, .data
i .bss
—> 16 bitów entropii w zmiennej delta_exec
. Ta zmienna jest losowo inicjowana przy każdym procesie i dodawana do adresów początkowych.
Pamięć przydzielana przez mmap()
i biblioteki współdzielone —> 16 bitów, nazwana delta_mmap
.
Stos —> 24 bity, oznaczane jako delta_stack
. Jednakże faktycznie używa 11 bitów (od 10. do 20. bajtu włącznie), wyrównanych do 16 bajtów —> Skutkuje to w 524,288 możliwych rzeczywistych adresów stosu.
Powyzsze dane dotyczą systemów 32-bitowych, a zmniejszona końcowa entropia umożliwia obejście ASLR poprzez wielokrotne ponowne próby wykonania, aż atak się powiedzie.
Jeśli masz wystarczająco dużo miejsca na przepełnienie, aby pomieścić duży ślizg NOP przed kodem powłoki, możesz po prostu brutalnie narzucić adresy na stosie, aż przepływ przeskoczy część ślizgu NOP.
Inną opcją w przypadku, gdy przepełnienie nie jest tak duże, a atak może być uruchomiony lokalnie, jest możliwość dodania ślizgu NOP i kodu powłoki do zmiennej środowiskowej.
Jeśli atak jest lokalny, możesz spróbować brutalnie narzucić bazowy adres libc (przydatne dla systemów 32-bitowych):
Jeśli atakujesz zdalny serwer, możesz spróbować przemocować adres funkcji usleep
z biblioteki libc
, przekazując jako argument 10 (na przykład). Jeśli w pewnym momencie serwer potrzebuje dodatkowych 10 sekund na odpowiedź, znalazłeś adres tej funkcji.
W systemach 64-bitowych entropia jest znacznie wyższa i to nie powinno być możliwe.
Możliwe jest zajęcie dużej części stosu zmiennymi środowiskowymi, a następnie próba wielokrotnego nadużycia binariów setki/tysiące razy lokalnie, aby je wykorzystać. Poniższy kod pokazuje, jak można wybrać adres na stosie i co kilka setek wykonania ten adres będzie zawierał instrukcję NOP:
/proc/[pid]/stat
)Plik /proc/[pid]/stat
procesu jest zawsze czytelny dla wszystkich i zawiera interesujące informacje takie jak:
startcode & endcode: Adresy powyżej i poniżej z sekcją TEXT binariów
startstack: Adres początku stosu
start_data & end_data: Adresy powyżej i poniżej gdzie znajduje się sekcja BSS
kstkesp & kstkeip: Aktualne adresy ESP i EIP
arg_start & arg_end: Adresy powyżej i poniżej gdzie znajdują się argumenty wiersza poleceń
env_start & env_end: Adresy powyżej i poniżej gdzie znajdują się zmienne środowiskowe
Dlatego jeśli atakujący znajduje się w tym samym komputerze co binarny plik podatny na atak i ten plik nie oczekuje przepełnienia z surowych argumentów, ale z innego wejścia, które można stworzyć po odczytaniu tego pliku. Atakujący może uzyskać pewne adresy z tego pliku i skonstruować z nich przesunięcia dla exploitu.
Aby uzyskać więcej informacji na temat tego pliku, sprawdź https://man7.org/linux/man-pages/man5/proc.5.html szukając /proc/pid/stat
Wyzwaniem jest dostarczenie wycieku
Jeśli otrzymasz wyciek (łatwe wyzwania CTF), możesz obliczyć przesunięcia z niego (przyjmując na przykład, że znasz dokładną wersję biblioteki libc używaną w systemie, który jest wykorzystywany). Ten przykładowy exploit jest wyodrębniony z przykładu stąd (sprawdź tę stronę dla więcej szczegółów):
ret2plt
Wykorzystując przepełnienie bufora możliwe byłoby wykorzystanie ret2plt do wycieku adresu funkcji z biblioteki libc. Sprawdź:
Ret2pltFormat Strings Arbitrary Read
Tak jak w przypadku ret2plt, jeśli masz arbitralne odczytywanie za pomocą podatności na ciągi formatujące, możliwe jest wyciekanie adresu funkcji z biblioteki libc z GOT. Poniższy przykład pochodzi stąd:
Możesz znaleźć więcej informacji na temat arbitralnego odczytu łańcuchów formatujących w:
Format StringsSpróbuj ominąć ASLR nadużywając adresów znajdujących się na stosie:
Ret2ret & Reo2popMechanizm vsyscall
służy do poprawy wydajności, pozwalając na wykonanie pewnych wywołań systemowych w przestrzeni użytkownika, chociaż są one fundamentalnie częścią jądra. Krytyczną zaletą vsyscalls jest ich stały adres, który nie podlega ASLR (losowaniu układu przestrzeni adresowej). Ta stała natura oznacza, że atakujący nie potrzebują podatności na wyciek informacji, aby określić ich adresy i użyć ich w ataku.
Jednakże tutaj nie znajdziesz zbyt interesujących gadżetów (choć na przykład możliwe jest uzyskanie odpowiednika ret;
)
(Poniższy przykład i kod pochodzi z tego opisu)
Na przykład, atakujący może użyć adresu 0xffffffffff600800
w ataku. Podczas próby skoku bezpośrednio do instrukcji ret
może prowadzić do niestabilności lub awarii po wykonaniu kilku gadżetów, skok na początek syscall
dostarczonego przez sekcję vsyscall może okazać się skuteczny. Uważne umieszczenie gadżetu ROP, który prowadzi wykonanie do tego adresu vsyscall, pozwala atakującemu osiągnąć wykonanie kodu bez konieczności omijania ASLR dla tej części ataku.
Zauważ, jak można obejść ASLR nadużywając vdso, jeśli jądro jest skompilowane z CONFIG_COMPAT_VDSO, ponieważ adres vdso nie będzie losowy. Aby uzyskać więcej informacji, sprawdź:
Ret2vDSO