
CVE-2026-39259
परियोजना: https://github.com/alexfru/SmallerC
SmallerC का scanf कार्यान्वयन स्ट्रिंग रीड पर ऊपरी सीमा लागू नहीं करता है जब %s या %[ का उपयोग फ़ॉर्मेट स्ट्रिंग में स्पष्ट फ़ील्ड चौड़ाई के बिना किया जाता है। रनटाइम डेस्टिनेशन बफर में तब तक लिखना जारी रखेगा जब तक उसे व्हाइटस्पेस या EOF नहीं मिलता, भले ही बफर का वास्तविक आवंटित आकार कुछ भी हो। सीमा से परे कोई भी बाइट सीधे स्टैक पर उतरती है और उन सब को ओवरराइट करती है जो कंपाइलर ने बफर के ऊपर रखा है - लोकल्स, सेव्ड रजिस्टर, रिटर्न एड्रेस।
यह कोई नई भेद्यता श्रेणी नहीं है। असीमित scanf स्ट्रिंग रीड को C के शुरुआती दिनों से प्रलेखित किया गया है और कोई भी सक्षम स्थैतिक विश्लेषण उपकरण उन्हें फ़्लैग करेगा। जो चीज़ इसे विशेष रूप से SmallerC के संदर्भ में रिपोर्ट करने लायक बनाती है, वह है लक्ष्य वातावरण। SmallerC को DOS और बेयर-मेटल एम्बेडेड लक्ष्यों के लिए डिज़ाइन किया गया है - ऐसे प्लेटफ़ॉर्म जो परिभाषा के अनुसार स्टैक कैनेरी, ASLR, NX बिट्स या आधुनिक प्रणालियों पर शोषण को कठिन बनाने वाली कोई भी शमन तकनीक प्रदान नहीं करते हैं। वही प्रिमिटिव जो एक हार्डन्ड Linux बाइनरी पर काम करने योग्य शोषण में बदलने के लिए महत्वपूर्ण अनुसंधान प्रयास की आवश्यकता होगी, एक फ्लैट पूर्वानुमानित स्टैक पर चलने वाले DOS प्रोग्राम पर काफी अधिक सुलभ हो जाता है।
बफर 16 बाइट का है। इनपुट 20 नॉन-व्हाइटस्पेस बाइट है। %s रूपांतरण में कोई चौड़ाई निर्दिष्टक नहीं है, इसलिए sscanf सभी 20 बाइट्स और एक नल टर्मिनेटर - कुल 21 बाइट्स - को 16-बाइट आवंटन में पढ़ता है। सीमा से परे के 5 बाइट आसन्न स्टैक मेमोरी को दूषित करते हैं। वास्तव में क्या दूषित होता है यह उस विशेष फ़ंक्शन के लिए कंपाइलर के स्टैक लेआउट निर्णयों पर निर्भर करता है, लेकिन ओवरराइट स्वयं नियतात्मक और बिना शर्त है - हर बार जब यह कोड पथ इस इनपुट के साथ चलता है।
प्रूफ ऑफ कॉन्सेप्ट
#include <stdioh>
#include <stringh>
/*
* Build with SmallerC targeting DOS or bare-metal
* Demonstrates unbounded %s write past a fixed stack buffer
*
* buffer is 16 bytes payload is 20 non-whitespace bytes
* sscanf writes 21 bytes (20 + null terminator) into buffer
* corrupting 5 bytes of adjacent stack memory
*
* To observe the corruption inspect stack memory after the call:
* the 5 bytes immediately above buffer will contain 'A' (0x41)
*/
int main() {
char buffer[16];
char canary[8];
memset(buffer 0x00 sizeof(buffer));
memset(canary 0xCC sizeof(canary)); /* marker to detect overwrite */
printf("[*] canary before: ");
for (int i = 0; i < 8; i++) printf("%02x " (unsigned char)canary[i]);
printf("\n");
sscanf("AAAAAAAAAAAAAAAAAAAA" "%s" buffer); /* 20 bytes into 16-byte buffer */
printf("[*] canary after: ");
for (int i = 0; i < 8; i++) printf("%02x " (unsigned char)canary[i]);
printf("\n");
if (memcmp(canary "\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC" 8) != 0)
printf("[!] stack corruption confirmed canary overwritten\n");
else
printf("[-] canary intact (stack layout placed it elsewhere)\n");
return 0;
}
प्रभावित बिल्ड पर अपेक्षित आउटपुट:
[*] canary before: cc cc cc cc cc cc cc cc
[*] canary after: 41 41 41 41 41 cc cc cc
[!] stack corruption confirmed canary overwritten
बफर के सापेक्ष कैनेरी का स्थान कंपाइलर के स्टैक लेआउट पर निर्भर करता है। यदि आउटपुट कैनेरी को अक्षुण्ण दिखाता है, तो ओवरराइट अभी भी हो रहा है - यह बफर के ऊपर किसी और चीज़ पर पड़ रहा है। डीबगर के साथ वास्तविक स्टैक फ्रेम का निरीक्षण करके रिप्रोड्यूसर को समायोजित करें ताकि पता लगाया जा सके कि 5 दूषित बाइट कहाँ उतरते हैं।
एक सुधार जो स्पष्ट रूप से करने योग्य है: इस भेद्यता वर्ग में कुछ रिपोर्टें "AAAAAAAAAAAAAAAAAAA\x00\x90\x04\x08" जैसे पेलोड में नल बाइट के बाद लक्ष्य पता जोड़कर रिटर्न एड्रेस नियंत्रण प्रदर्शित करने का प्रयास करती हैं। यह काम नहीं करता है। sscanf में %s रूपांतरण \x00 को एक स्ट्रिंग टर्मिनेटर के रूप में मानता है और जैसे ही इसका सामना होता है, पढ़ना तुरंत बंद कर देता है। नल बाइट के बाद के बाइट्स कभी संसाधित नहीं होते हैं। वास्तविक रिटर्न एड्रेस नियंत्रण प्रदर्शित करने के लिए पेलोड के महत्वपूर्ण भाग में नल बाइट के बिना ओवरराइट प्रदान करना आवश्यक है, जिसके लिए लक्ष्य बाइनरी के सटीक स्टैक लेआउट की जानकारी की आवश्यकता होती है - बफर से सेव्ड रिटर्न एड्रेस की दूरी, क्या कंपाइलर ने कोई पैडिंग डाली, और कौन से संरेखण बाधाएं लागू होती हैं। इनमें से कोई भी इस रिप्रोड्यूसर से स्वचालित रूप से नहीं मिलता है।
रिप्रोड्यूसर स्पष्ट रूप से जो स्थापित करता है वह स्वयं भ्रष्टाचार प्रिमिटिव है। सीमा से बाहर लेखन वास्तविक, पुनरुत्पादनीय है और किसी दौड़ की स्थिति या समय पर निर्भर नहीं करता है। DOS या एम्बेडेड लक्ष्य पर जहां स्टैक लेआउट स्थिर और बिल्डों में पूर्वानुमानित है, इस प्रिमिटिव से एक काम करने योग्य शोषण तक पहुंचना एक यथार्थवादी अनुसंधान प्रयास है न कि एक सैद्धांतिक अभ्यास।
प्रभावित परिदृश्य संकीर्ण है लेकिन काल्पनिक नहीं है। एक प्रोग्राम को SmallerC के साथ बनाया जाना चाहिए, scanf-परिवार पार्सिंग का उपयोग करना चाहिए जिसमें असीमित %s या %[ निर्दिष्टकर्ता हो, एक निश्चित आकार के स्टैक बफर में लिखना चाहिए, और उस स्रोत से इनपुट स्वीकार करना चाहिए जिसे हमलावर प्रभावित कर सकता है। सभी चार शर्तों को एक साथ पूरा होना चाहिए। जो प्रोग्राम सही फ़ील्ड चौड़ाई का उपयोग करते हैं - char[16] के लिए %15s - वे प्रभावित नहीं होते हैं। जो प्रोग्राम हमलावर-नियंत्रित इनपुट को पार्स नहीं करते हैं वे प्रभावित नहीं होते हैं। समस्या यह है कि SmallerC का रनटाइम लापता चौड़ाई बाधा को कैसे संभालता है, लेकिन यह तभी सुरक्षा चिंता बनता है जब एप्लिकेशन कोड उस दोष को अविश्वसनीय इनपुट के लिए उजागर करता है।
एप्लिकेशन पक्ष पर समाधान सीधा है: एक फ़ील्ड चौड़ाई निर्दिष्ट करें जो नल टर्मिनेटर के लिए जगह छोड़े - 16-बाइट बफर के लिए %15s, 64-बाइट बफर के लिए %63s। यह मानक C अभ्यास है और फ़ॉर्मेट स्ट्रिंग सिंटैक्स द्वारा पूरी तरह से समर्थित है। SmallerC प्रोजेक्ट पक्ष पर, अधिक टिकाऊ कार्य बाध्य और असीमित दोनों %s और %[ व्यवहार को scanf, sscanf और fscanf में कवर करने वाले रिग्रेशन परीक्षण जोड़ना है, यह सत्यापित करना कि स्पष्ट फ़ील्ड चौड़ाई वास्तव में कार्यान्वयन में सम्मानित की जाती है, और असुरक्षित पैटर्न को प्रमुखता से प्रलेखित करना है। एक कंपाइलर-स्तरीय डायग्नोस्टिक जो चेतावनी देता है जब %s या %[ फ़ॉर्मेट स्ट्रिंग लिटरल में फ़ील्ड चौड़ाई के बिना दिखाई देता है, तो इस प्रकार की गलती को सक्रिय रूप से रोकेगा और टूलचेन में एक सार्थक जोड़ होगा।
गंभीरता मध्यम है जब बाहरी इनपुट भेद्य कोड पथ तक पहुँचता है। यह निम्न हो जाता है जब इनपुट स्थानीय या गैर-विशेषाधिकार प्राप्त होता है। लक्ष्य वातावरण - विशेष रूप से SmallerC के इच्छित प्लेटफार्मों पर आधुनिक शोषण शमन की अनुपस्थिति - यही चीज़ इसे एक सामान्य "असीमित scanf का उपयोग न करें" सलाह से अलग करती है और इसे प्रोजेक्ट स्तर पर रिपोर्ट करने लायक बनाती है, बजाय इसे विशुद्ध रूप से एप्लिकेशन-परत दुरुपयोग के रूप में मानने के।
श्रेय: Yousif Wazni