ASLR
Podstawowe informacje
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 utrudnia się przewidywanie lokalizacji konkretnych procesów i danych przez atakującego, takich jak stos, sterta i biblioteki, co zmniejsza ryzyko pewnych rodzajów ataków, zwłaszcza przepełnień bufora.
Sprawdzanie stanu ASLR
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 losowości. Wszystko jest statyczne.
1: Konserwatywna randomizacja. Biblioteki współdzielone, stos, mmap(), strona VDSO są losowo rozmieszczane.
2: Pełna randomizacja. Oprócz elementów losowo rozmieszczanych przez konserwatywną randomizację, pamięć zarządzana przez
brk()
jest losowo rozmieszczana.
Możesz sprawdzić stan ASLR za pomocą następującej komendy:
Wyłączanie ASLR
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ą:
Włączanie ASLR
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:
Trwałość po ponownym uruchomieniu
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.
Bypassy
Brutalne narzucanie 32-bitowe
PaX dzieli przestrzeń adresową procesu na 3 grupy:
Kod i dane (zainicjowane i niezainicjowane):
.text
,.data
i.bss
—> 16 bitów entropii w zmiennejdelta_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, nazwanadelta_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 ponawianie prób wykonania, aż atak się powiedzie.
Pomysły na brutalne narzucanie:
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ć przemęczyć adres funkcji
usleep
z bibliotekilibc
, 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.
Przemęczanie stosu 64 bitów
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:
Lokalne informacje (/proc/[pid]/stat
)
/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ę 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. Dla atakującego jest możliwe uzyskanie pewnych adresów z tego pliku i skonstruowanie z nich przesunięć 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
Posiadanie wycieku
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żna wykorzystać ret2plt do wycieku adresu funkcji z biblioteki libc. Sprawdź:
pageRet2pltFormat Strings Arbitrary Read
Tak jak w przypadku ret2plt, jeśli masz arbitralne odczyt poprzez podatność na ciągi formatujące, można wyciec adres funkcji z biblioteki libc z GOT. Następujący przykład pochodzi stąd:
Możesz znaleźć więcej informacji na temat arbitralnego odczytu łańcuchów formatujących w:
pageFormat StringsRet2ret & Ret2pop
Spróbuj ominąć ASLR nadużywając adresów znajdujących się na stosie:
pageRet2ret & Reo2popvsyscall
Mechanizm 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 (losowej alokacji przestrzeni adresowej). Ta stała natura oznacza, że atakujący nie potrzebują podatności na wyciek informacji, aby określić ich adresy i wykorzystać je 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
dostarczany przez sekcję vsyscall może okazać się skuteczny. Starannie umieszczając gadżet ROP, który prowadzi wykonanie do tego adresu vsyscall, atakujący może osiągnąć wykonanie kodu bez konieczności omijania ASLR dla tej części ataku.
vDSO
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ź:
pageRet2vDSOLast updated