Stack Overflow

Reading time: 5 minutes

tip

Ucz się i ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Wsparcie HackTricks

Co to jest Stack Overflow

Stack overflow to luka, która występuje, gdy program zapisuje więcej danych na stosie, niż jest przydzielone do przechowywania. Te nadmiarowe dane nadpiszą sąsiednią przestrzeń pamięci, prowadząc do uszkodzenia ważnych danych, zakłócenia przepływu sterowania i potencjalnie do wykonania złośliwego kodu. Problem ten często pojawia się z powodu użycia niebezpiecznych funkcji, które nie wykonują sprawdzania granic na wejściu.

Głównym problemem tego nadpisania jest to, że zapisany wskaźnik instrukcji (EIP/RIP) oraz zapisany wskaźnik bazowy (EBP/RBP) do powrotu do poprzedniej funkcji są przechowywane na stosie. Dlatego atakujący będzie w stanie nadpisać je i kontrolować przepływ wykonania programu.

Luka ta zazwyczaj występuje, ponieważ funkcja kopiuje na stos więcej bajtów niż przydzielona ilość, co pozwala na nadpisanie innych części stosu.

Niektóre powszechne funkcje podatne na to to: strcpy, strcat, sprintf, gets... Ponadto funkcje takie jak fgets, read i memcpy, które przyjmują argument długości, mogą być używane w sposób podatny, jeśli określona długość jest większa niż przydzielona.

Na przykład, następujące funkcje mogą być podatne:

c
void vulnerable() {
char buffer[128];
printf("Enter some text: ");
gets(buffer); // This is where the vulnerability lies
printf("You entered: %s\n", buffer);
}

Znajdowanie przesunięć przepełnienia stosu

Najczęstszym sposobem na znalezienie przepełnień stosu jest podanie bardzo dużego wejścia z As (np. python3 -c 'print("A"*1000)') i oczekiwanie na Segmentation Fault, co wskazuje, że adres 0x41414141 próbował być dostępny.

Ponadto, gdy już znajdziesz, że istnieje luka w przepełnieniu stosu, będziesz musiał znaleźć przesunięcie, aż będzie możliwe nadpisanie adresu powrotu. W tym celu zazwyczaj używa się sekwencji De Brujna. Która dla danego alfabetu o rozmiarze k i podsekwencji o długości n jest cykliczną sekwencją, w której każda możliwa podsekwencja o długości _n_** występuje dokładnie raz** jako sąsiadująca podsekwencja.

W ten sposób, zamiast ręcznie ustalać, które przesunięcie jest potrzebne do kontrolowania EIP, można użyć jako wypełnienia jednej z tych sekwencji, a następnie znaleźć przesunięcie bajtów, które zakończyły nadpisanie.

Można użyć pwntools do tego:

python
from pwn import *

# Generate a De Bruijn sequence of length 1000 with an alphabet size of 256 (byte values)
pattern = cyclic(1000)

# This is an example value that you'd have found in the EIP/IP register upon crash
eip_value = p32(0x6161616c)
offset = cyclic_find(eip_value)  # Finds the offset of the sequence in the De Bruijn pattern
print(f"The offset is: {offset}")

lub GEF:

bash
#Patterns
pattern create 200 #Generate length 200 pattern
pattern search "avaaawaa" #Search for the offset of that substring
pattern search $rsp #Search the offset given the content of $rsp

Wykorzystywanie przepełnień stosu

Podczas przepełnienia (zakładając, że rozmiar przepełnienia jest wystarczająco duży) będziesz w stanie nadpisać wartości lokalnych zmiennych w stosie, aż do osiągnięcia zapisanych EBP/RBP i EIP/RIP (lub nawet więcej).
Najczęstszym sposobem nadużywania tego typu podatności jest modyfikacja adresu powrotu, aby po zakończeniu funkcji przepływ kontroli został przekierowany tam, gdzie użytkownik wskazał w tym wskaźniku.

Jednak w innych scenariuszach może wystarczyć tylko nadpisanie niektórych wartości zmiennych w stosie do wykorzystania podatności (jak w łatwych wyzwaniach CTF).

Ret2win

W tego typu wyzwaniach CTF, istnieje funkcja wewnątrz binarnego, która nigdy nie jest wywoływana i którą musisz wywołać, aby wygrać. W tych wyzwaniach musisz tylko znaleźć offset do nadpisania adresu powrotu i znaleźć adres funkcji, którą chcesz wywołać (zwykle ASLR będzie wyłączony), aby po powrocie z podatnej funkcji, ukryta funkcja została wywołana:

{{#ref}} ret2win/ {{#endref}}

Shellcode w stosie

W tym scenariuszu atakujący mógłby umieścić shellcode w stosie i nadużyć kontrolowanego EIP/RIP, aby skoczyć do shellcode i wykonać dowolny kod:

{{#ref}} stack-shellcode/ {{#endref}}

Techniki ROP i Ret2...

Ta technika jest podstawowym frameworkiem do obejścia głównej ochrony poprzedniej techniki: Brak wykonywalnego stosu (NX). Umożliwia to wykonanie kilku innych technik (ret2lib, ret2syscall...), które kończą się wykonaniem dowolnych poleceń poprzez nadużycie istniejących instrukcji w binarnym:

{{#ref}} ../rop-return-oriented-programing/ {{#endref}}

Przepełnienia sterty

Przepełnienie nie zawsze będzie miało miejsce w stosie, może również wystąpić w stercie, na przykład:

{{#ref}} ../libc-heap/heap-overflow.md {{#endref}}

Rodzaje ochrony

Istnieje kilka zabezpieczeń próbujących zapobiec wykorzystaniu podatności, sprawdź je w:

{{#ref}} ../common-binary-protections-and-bypasses/ {{#endref}}

tip

Ucz się i ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Wsparcie HackTricks