c - लेखन सुरक्षित सी और सुरक्षित सी Idioms




security buffer-overflow (5)

"औसत आदमी स्वतंत्र नहीं होना चाहता। वह बस सुरक्षित होना चाहता है।" - एचएल मेनकेन

मैं बहुत सुरक्षित लिखने का प्रयास कर रहा हूं। नीचे मैं उन तकनीकों की सूची देता हूं जो मैं उपयोग करता हूं और पूछता हूं कि वे सुरक्षित हैं क्योंकि मुझे लगता है कि वे हैं। कृपया मेरे कोड / preconceptions को shreds फाड़ने में संकोच नहीं करते हैं। कोई भी जवाब जो सबसे छोटी भेद्यता को भी पाता है या मुझे एक नया विचार सिखाता है, उसका अत्यधिक महत्व होगा

एक धारा से पढ़ना:

जीएनयू सी प्रोग्रामिंग ट्यूटोरियल getline के अनुसार:

गेटलाइन फ़ंक्शन स्वचालित रूप से रीयलॉक फ़ंक्शन के माध्यम से आवश्यक स्मृति के ब्लॉक को बड़ा कर देगा, इसलिए अंतरिक्ष की कमी कभी नहीं होती - एक कारण है कि गेटलाइन इतनी सुरक्षित है। [..] ध्यान दें कि गेटलाइन आपके इनपुट की लाइन को सुरक्षित रूप से संभाल सकती है, चाहे कितनी देर हो।

मुझे लगता है कि सभी इनपुट के तहत , गेटलाइन को स्ट्रीम से पढ़ने पर होने वाले बफर ओवरफ़्लो को रोकना चाहिए।

  • क्या मेरी धारणा सही है? क्या वहां इनपुट और / या आवंटन योजनाएं हैं जिसके अंतर्गत इसका शोषण हो सकता है? उदाहरण के लिए यदि स्ट्रीम से पहला अक्षर कुछ विचित्र नियंत्रण चरित्र है , तो शायद 0x08 बैकस्पेस (सीटीएल-एच) हो सकता है।
  • क्या गेटलाइन को सुरक्षित रूप से साबित करने के लिए कोई काम किया गया है?

विफलता पर मॉलोक रिटर्न शून्य

यदि मॉलोक एक त्रुटि मालोक का सामना करता है तो एक नल पॉइंटर देता है। यह एक सुरक्षा जोखिम प्रस्तुत करता है क्योंकि कोई भी अभी भी एक पूर्ण (0x0) सूचक में पॉइंटर अंकगणित लागू कर सकता है, इस प्रकार विकिपीडिया recommends

/* Allocate space for an array with ten elements of type int. */
int *ptr = (int*)malloc(10 * sizeof (int));
if (ptr == NULL) {
    /* Memory could not be allocated, the program should handle 
       the error here as appropriate. */
} 

सुरक्षित sscanf:

sscanf का उपयोग करते समय मुझे इनपुट स्ट्रिंग के आकार के आकार को निकालने के लिए आकार को आवंटित करने की आदत में प्राप्त हुआ है, उम्मीद है कि ओवरराउन की संभावना से बचें। उदाहरण के लिए:

const char *inputStr = "a01234b4567c";
const char *formatStr = "a%[0-9]b%[0-9]c":
char *str1[strlen(inputStr)];
char *str2[strlen(inputStr)];

sscanf(inputStr, formatStr, str1, str2);

चूंकि str1 और str2 inputStr का आकार हैं और इनपुट एसआरटी से स्ट्रेलन (इनपुटएसआरआर) से अधिक वर्ण नहीं पढ़े जा सकते हैं, यह इनपुट एसआरटी के लिए सभी संभावित मानों को बफर ओवरफ्लो के कारण असंभव लगता है?

  • क्या मैं सही हूँ? क्या अजीब कोने के मामले मैंने सोचा नहीं है?
  • क्या इसे लिखने के बेहतर तरीके हैं? पुस्तकालय जो पहले से ही हल कर चुके हैं?

सामान्य सवाल:

जबकि मैंने बड़ी संख्या में प्रश्न पोस्ट किए हैं, मैं उम्मीद नहीं करता कि कोई भी उन सभी का जवाब दे। प्रश्न मैं जिन उत्तरों की तलाश में हूं, उनके लिए दिशानिर्देश अधिक हैं। मैं वास्तव में सुरक्षित सी मानसिकता सीखना चाहता हूं।

  • वहां अन्य सुरक्षित सी मुहावरे क्या हैं?
  • मुझे हमेशा किन जांचने की आवश्यकता है?
  • इन नियमों को लागू करने के लिए मैं यूनिट परीक्षण कैसे लिख सकता हूं?
  • मैं एक टेस्टेबिलिटी या सिद्ध रूप से सही तरीके से बाधाओं को कैसे लागू कर सकता हूं?
  • सी के लिए कोई भी सिफारिश की स्थिर / गतिशील विश्लेषण तकनीकों या उपकरण?
  • आप कौन सी सुरक्षित सी प्रथाओं का पालन करते हैं और आप उन्हें अपने और दूसरों को कैसे औचित्य देते हैं?

संसाधन:

कई संसाधनों को उत्तर से उधार लिया गया था।


  1. एक धारा से पढ़ना

तथ्य यह है कि getline() "स्वचालित रूप से आवश्यकतानुसार स्मृति के ब्लॉक को बड़ा कर देगा" का अर्थ है कि इसका उपयोग इनकार करने वाले सेवा के हमले के रूप में किया जा सकता है, क्योंकि यह इनपुट उत्पन्न करने के लिए तुच्छ होगा जो इतनी देर तक उपलब्ध होगा प्रक्रिया के लिए स्मृति (या बदतर, सिस्टम!)। एक बार स्मृति की स्थिति होने के बाद, अन्य भेद्यता भी खेल में आ सकती हैं। कम / कोई स्मृति में कोड का व्यवहार शायद ही कभी अच्छा है, और भविष्यवाणी करना बहुत मुश्किल है। IMHO विशेष रूप से सुरक्षा-संवेदनशील अनुप्रयोगों में, सब कुछ पर उचित ऊपरी सीमा निर्धारित करना सुरक्षित है।

इसके अलावा (जैसा कि आप विशेष पात्रों का उल्लेख करके अनुमान लगाते हैं), getline() केवल आपको एक बफर देता है; यह बफर की सामग्री के बारे में कोई गारंटी नहीं देता है (क्योंकि सुरक्षा पूरी तरह से आवेदन-निर्भर है)। इसलिए इनपुट को संचरित करना अभी भी उपयोगकर्ता डेटा को संसाधित करने और मान्य करने का एक अनिवार्य हिस्सा है।

  1. sscanf

मैं नियमित अभिव्यक्ति लाइब्रेरी का उपयोग करना पसंद करता हूं, और sscanf उपयोग करने के बजाय, उपयोगकर्ता डेटा के लिए बहुत कम परिभाषित sscanf । इस तरह आप इनपुट के समय सत्यापन का एक अच्छा सौदा कर सकते हैं।

  1. सामान्य टिप्पणियाँ

    • फ़ज़िंग टूल उपलब्ध हैं जो यादृच्छिक इनपुट (वैध और अमान्य दोनों) उत्पन्न करते हैं जिनका उपयोग आपके इनपुट हैंडलिंग का परीक्षण करने के लिए किया जा सकता है
    • बफर प्रबंधन महत्वपूर्ण है: बफर ओवरफ्लो, अंडरफ्लो, आउट-ऑफ-मेमोरी
    • अन्यथा सुरक्षित कोड में रेस स्थितियों का शोषण किया जा सकता है
    • बाइनरी फ़ाइलों को अमान्य मानों या oversized मानों को हेडर में इंजेक्ट करने के लिए छेड़छाड़ की जा सकती है, इसलिए फ़ाइल प्रारूप कोड रॉक-ठोस होना चाहिए और यह नहीं मानना ​​कि बाइनरी डेटा मान्य है
    • अस्थायी फ़ाइलें अक्सर सुरक्षा समस्याओं का स्रोत हो सकती हैं, और सावधानीपूर्वक प्रबंधित की जानी चाहिए
    • कोड इंजेक्शन का उपयोग दुर्भावनापूर्ण संस्करणों के साथ सिस्टम या रनटाइम लाइब्रेरी कॉल को प्रतिस्थापित करने के लिए किया जा सकता है
    • प्लगइन्स हमले के लिए एक विशाल वेक्टर प्रदान करते हैं
    • एक सामान्य सिद्धांत के रूप में, मैं स्पष्ट रूप से परिभाषित इंटरफेस रखने का सुझाव दूंगा जहां उपयोगकर्ता डेटा (या एप्लिकेशन के बाहर से किसी भी डेटा) को अमान्य और शत्रुतापूर्ण माना जाता है जब तक कि इसे संसाधित, स्वच्छता और मान्य नहीं किया जाता है, और उपयोगकर्ता डेटा को एप्लिकेशन में प्रवेश करने का एकमात्र तरीका

अच्छा दिन,

डेविड व्हीलर की उत्कृष्ट सुरक्षित कोडिंग साइट पर यह देखने के लिए एक अच्छी जगह है।

उनकी मुफ्त ऑनलाइन पुस्तक " लिनक्स और यूनिक्स हाउटो के लिए सुरक्षित प्रोग्रामिंग " एक उत्कृष्ट संसाधन है जिसे नियमित रूप से अपडेट किया जाता है।

आप कुछ और संकेत प्राप्त करने के लिए अपने उत्कृष्ट स्थिर विश्लेषक flawfinder को भी देखना चाहेंगे। लेकिन याद रखें, कोई स्वचालित उपकरण अनुभवी आंखों की अच्छी जोड़ी के प्रतिस्थापन नहीं है, या जैसे डेविड रंगीन रूप से इसे रखता है ..

फ्लॉफाइंडर जैसे किसी भी स्थिर विश्लेषण उपकरण, केवल एक उपकरण है। मानव विचार के लिए कोई उपकरण प्रतिस्थापित नहीं कर सकता! संक्षेप में, "एक उपकरण के साथ एक मूर्ख अभी भी मूर्ख है" । यह सोचने की गलती है कि विश्लेषण उपकरण (जैसे फ्लॉफाइंडर) सुरक्षा प्रशिक्षण और ज्ञान के लिए एक विकल्प हैं

मैंने कई वर्षों से व्यक्तिगत रूप से डेविड के संसाधनों का उपयोग किया है और उन्हें उत्कृष्ट होने के लिए खोजा है।

HTH

चियर्स,


इनपुट के लिए fgets() उपयोग न करें, fgets() उपयोग करें। fgets() उपयोग करने के लिए, यदि आपका बफर स्वचालित रूप से आवंटित किया जाता है (यानी, "स्टैक पर"), तो इस मुहावरे का उपयोग करें:

char buf[N];
...
if (fgets(buf, sizeof buf, fp) != NULL)

अगर आप buf के आकार को बदलने का फैसला करते हैं तो यह काम करेगा। मैं इस फॉर्म को पसंद करता हूं:

#define N whatever
char buf[N];
if (fgets(buf, N, fp) != NULL)

क्योंकि पहला फॉर्म दूसरा तर्क निर्धारित करने के लिए buf का उपयोग करता है, और स्पष्ट है।

fclose() के वापसी मूल्य की जांच करें।


मुझे लगता है कि आपका एसएसकेएनएफ उदाहरण गलत है। इस तरह इस्तेमाल होने पर यह अभी भी बहती जा सकती है।

इसे आज़माएं, जो पढ़ने के लिए बाइट्स की अधिकतम संख्या निर्दिष्ट करता है:

void main(int argc, char **argv)
{
  char buf[256];
  sscanf(argv[0], "%255s", &buf);
}

बफर ओवरफ्लो के खिलाफ सुरक्षा के बारे में इस आईबीएम देव लेख पर एक नज़र डालें।

परीक्षण के मामले में, मैं एक ऐसा प्रोग्राम लिखूंगा जो यादृच्छिक लंबाई के यादृच्छिक तार उत्पन्न करता है और उन्हें अपने कार्यक्रम में खिलाता है, और सुनिश्चित करें कि उन्हें उचित तरीके से संभाला जा सके।








exploit