2015-05-20 11 views
6

मैं ढेर अतिप्रवाह हमलों के बारे में सीख रहा हूँ और मेरे पाठ्यपुस्तक निम्नलिखित कमजोर सी कोड प्रदान करता है:ढेर ओवरफ्लो हमला

/* record type to allocate on heap */ 
typedef struct chunk { 
    char inp[64];   /* vulnerable input buffer */ 
    void (*process)(char *); /* pointer to function to process inp */ 
} chunk_t; 

void showlen(char *buf) 
{ 
    int len; 
    len = strlen(buf); 
    printf("buffer5 read %d chars\n", len); 
} 

int main(int argc, char *argv[]) 
{ 
    chunk_t *next; 

    setbuf(stdin, NULL); 
    next = malloc(sizeof(chunk_t)); 
    next->process = showlen; 
    printf("Enter value: "); 
    gets(next->inp); 
    next->process(next->inp); 
    printf("buffer5 done\n"); 
} 

हालांकि, पाठ्यपुस्तक की व्याख्या नहीं करता कैसे एक इस कमज़ोरी को होगा। यदि कोई भी भेद्यता और एक तरीका (ओं) को ठीक करने के लिए समझा सकता है तो यह बहुत अच्छा होगा। (समस्या का एक हिस्सा यह है कि मैं जावा से आ रहा हूं, सी नहीं)

+4

आपकी 'inp' 64 बाइट्स है। इसलिए 65 बाइट इनपुट करें और आपके पास अतिप्रवाह है ... –

+4

और इसे ठीक करने के लिए, [fgets() का उपयोग करें (http://stackoverflow.com/questions/1694036/why-is-the-gets-function-so- खतरनाक -यह-इसे-इस्तेमाल नहीं किया जाना चाहिए) –

+0

@orangesoda यह पुस्तक कौन है? –

उत्तर

5

समस्या यह है कि gets() बफर में पढ़ने जब तक यह एक नई पंक्ति पढ़ता है या EOF तक पहुँच जाता है रखना होगा है। यह बफर के आकार को नहीं जानता है, इसलिए यह नहीं जानता कि इसे बंद होने पर इसे रोकना चाहिए। यदि रेखा 64 बाइट्स या उससे अधिक है, तो यह बफर के बाहर जाएगी, और process ओवरराइट करेगा। यदि इनपुट में प्रवेश करने वाला उपयोगकर्ता इस बारे में जानता है, तो वह फ़ंक्शन पॉइंटर को किसी अन्य फ़ंक्शन पर प्रतिस्थापित करने के लिए स्थिति 64 पर सही वर्ण टाइप कर सकता है, जिसे वह प्रोग्राम कॉल करना चाहता है।

फ़िक्स gets() के अलावा किसी फ़ंक्शन का उपयोग करना है, इसलिए आप पढ़े जाने वाले इनपुट की मात्रा पर एक सीमा निर्दिष्ट कर सकते हैं।

gets(next->inp); 

के बजाय आप का उपयोग कर सकते हैं:

fgets(next->inp, sizeof(next->inp), stdin); 

fgets() को दूसरा तर्क कहता है next->inp में ज्यादा से ज्यादा 64 बाइट्स लिखने के लिए। तो यह stdin से अधिकतम 63 बाइट्स पर पढ़ेगा (इसे नल स्ट्रिंग टर्मिनेटर के लिए बाइट को अनुमति देने की आवश्यकता है)।

5

कोड gets का उपयोग करता है, जो इसकी संभावित सुरक्षा समस्या के लिए कुख्यात है: आपके द्वारा पास किए गए बफर की लंबाई निर्दिष्ट करने का कोई तरीका नहीं है, यह stdin से पढ़ना जारी रखेगा जब तक कि यह \n या EOF से मुकाबला न करे। इसलिए यह आपके बफर को बहता है और इसके बाहर स्मृति को लिख सकता है, और फिर बुरी चीजें होती हैं - यह दुर्घटनाग्रस्त हो सकती है, यह चलती रह सकती है, यह अश्लील खेलना शुरू कर सकती है।

इसे ठीक करने के लिए, आपको इसके बजाय fgets का उपयोग करना चाहिए।

1

आप process के लिए पता सेट करके 64 से अधिक बाइट्स के साथ आगे भर सकते हैं। इस प्रकार कोई भी जो भी पता चाहता है उसे सम्मिलित करने में सक्षम बनाता है। पता किसी भी समारोह के लिए एक सूचक हो सकता है।

सरल ठीक करने के लिए सुनिश्चित करना है कि केवल 63 बाइट्स (शून्य के लिए एक) सरणी inp में पढ़ा जाता है - का उपयोग fgets

0

फ़ंक्शन stdin से आने वाले पाठ की मात्रा को सीमित नहीं करता है। यदि 63 से अधिक वर्ण stdin से आते हैं, तो एक ओवरफ़्लो होगा। एलएफ चार को छोड़ देता है, जो एक [एंटर] कुंजी होगा, लेकिन यह अंत में एक शून्य चार जोड़ता है, इस प्रकार 63 वर्ण सीमाएं होती हैं।

inp पर मूल्य, 64 में गैर-शून्य वर्ण से भर जाता है, तो के रूप में यह सीधे पहुँचा जा सकता, showlen समारोह के रूप में strleninp परे अशक्त-चार के लिए खोज इसका आकार निर्धारित करने के लिए होगा, एक पहुँच उल्लंघन ट्रिगर किया जाएगा।

fgets का उपयोग पहली समस्या के लिए एक अच्छा तय होगा, लेकिन यह एक एलएफ चार और शून्य भी जोड़ देगा, इसलिए पठनीय पाठ की नई सीमा 62 होगी।

दूसरे के लिए, inp पर जो लिखा गया है उसका ख्याल रखें।

संबंधित मुद्दे