रक्षात्मक प्रोग्रामिंग

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

रक्षात्मक प्रोग्रामिंग सॉफ़्टवेयर और स्रोत कोड को बेहतर बनाने के लिए एक दृष्टिकोण है, के संदर्भ में:


 * सामान्य गुणवत्ता - सॉफ्टवेयर बग और समस्याओं की संख्या को कम करना है।
 * स्रोत कोड को समझ में आता है - स्रोत कोड पठनीय और समझ में आता है इसलिए इसे कोड ऑडिट में अनुमोदित किया जाता है।
 * अप्रत्याशित इनपुट या उपयोगकर्ता कार्यों के बावजूद सॉफ़्टवेयर को एक अनुमानित तरीके से व्यवहार करना है।

अत्यधिक रक्षात्मक प्रोग्रामिंग, हालांकि, उन त्रुटियों के खिलाफ सुरक्षा कर सकते हैं जो कभी भी सामना नहीं करेंगे, इस प्रकार रन-टाइम और रखरखाव की लागत को बढ़ाते हैं। एक जोखिम यह भी है कि कोड ट्रैप बहुत अधिक अपवाद हैंडलिंग को रोकता है, जिसके परिणामस्वरूप संभावित रूप से अनजान, गलत परिणाम होते हैं।

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

फ़ंक्शन को अपरिभाषित व्यवहार में परिणाम होगा जब इनपुट 1000 से अधिक वर्णों का है। कुछ प्रोग्रामर यह महसूस नहीं कर सकते हैं कि यह एक समस्या है, यह मानते हुए कि कोई भी उपयोगकर्ता इतने लंबे इनपुट में प्रवेश नहीं करेगा। यह विशेष बग एक भेद्यता को प्रदर्शित करता है जो बफर ओवरफ्लो एक्सप्लॉइट्स को सक्षम करता है।  यहाँ इस उदाहरण का समाधान है:

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

आंतरिक डेटा वैधता पर विश्वास करना
अत्यधिक रक्षात्मक प्रोग्रामिंग

const char* trafficlight_colorname(enum traffic_light_color c) {

switch (c) {

case TRAFFICLIGHT_RED:    return "red";

case TRAFFICLIGHT_YELLOW: return "yellow";

case TRAFFICLIGHT_GREEN:  return "green";

}

return "black"; // To be handled as a dead traffic light.

// Warning: This last 'return' statement will be dropped by an optimizing

// compiler if all possible values of 'traffic_light_color' are listed in

// the previous 'switch' statement...

}

ओफ्फेंसिव प्रोग्रामिंग

const char* trafficlight_colorname(enum traffic_light_color c) {

switch (c) {

case TRAFFICLIGHT_RED:    return "red";

case TRAFFICLIGHT_YELLOW: return "yellow";

case TRAFFICLIGHT_GREEN:  return "green";

}

assert(0); // Assert that this section is unreachable.

// Warning: This 'assert' function call will be dropped by an optimizing

// compiler if all possible values of 'traffic_light_color' are listed in

// the previous 'switch' statement...

}

सॉफ्टवेयर घटकों पर भरोसा करना
अत्यधिक रक्षात्मक प्रोग्रामिंग <वाक्यविन्यास प्रकाश लैंग = सी> अगर (is_legacy_संगत (user_config)) { // रणनीति: विश्वास न करें कि नया कोड वही व्यवहार करता है पुराना_कोड (user_config); } अन्य { // फ़ॉलबैक: विश्वास न करें कि नया कोड समान मामलों को संभालता है अगर (new_code (user_config)! = ठीक है) { पुराना_कोड (user_config); } } 

आक्रामक प्रोग्रामिंग <वाक्यविन्यास प्रकाश लैंग = सी> // अपेक्षा करें कि नए कोड में कोई नई बग नहीं है अगर (new_code (user_config)! = ठीक है) { // जोर से रिपोर्ट करें और उचित ध्यान पाने के लिए कार्यक्रम को अचानक समाप्त कर दें रिपोर्ट_त्रुटि (कुछ बहुत गलत हो गया); बाहर निकलें (-1); } 

तकनीक
यहाँ कुछ रक्षात्मक प्रोग्रामिंग तकनीकें हैं:

बुद्धिमान स्रोत कोड पुन: उपयोग
यदि मौजूदा कोड का परीक्षण किया गया है और काम करने के लिए जाना जाता है, तो इसका पुन: उपयोग करने से बग्स के पेश होने की संभावना कम हो सकती है।

हालाँकि, कोड का पुन: उपयोग करना हमेशा अच्छा अभ्यास नहीं होता है। मौजूदा कोड का पुन: उपयोग, विशेष रूप से जब व्यापक रूप से वितरित किया जाता है, ऐसे शोषण के लिए अनुमति दे सकता है जो अन्यथा संभव से अधिक व्यापक दर्शकों को लक्षित करता है और पुन: उपयोग किए गए कोड की सभी सुरक्षा और कमजोरियों को अपने साथ लाता है।

मौजूदा स्रोत कोड का उपयोग करने पर विचार करते समय, मॉड्यूल की त्वरित समीक्षा (वर्ग या कार्यों जैसे उप-वर्ग) डेवलपर को किसी भी संभावित कमजोरियों से अवगत कराने या जागरूक करने में मदद करेगा और यह सुनिश्चित करेगा कि यह परियोजना में उपयोग करने के लिए उपयुक्त है।

विरासत की समस्याएं
पुराने स्रोत कोड, पुस्तकालयों, एपीआई, कॉन्फ़िगरेशन आदि का पुन: उपयोग करने से पहले, यह विचार किया जाना चाहिए कि क्या पुराना कार्य पुन: उपयोग के लिए मान्य है, या यदि यह विरासत प्रणाली की समस्याओं से ग्रस्त होने की संभावना है।

विरासत की समस्याएं अंतर्निहित समस्याएं हैं जब पुराने डिजाइनों से आज की आवश्यकताओं के साथ काम करने की उम्मीद की जाती है, खासकर जब पुराने डिजाइनों को उन आवश्यकताओं को ध्यान में रखते हुए विकसित या परीक्षण नहीं किया गया था।

कई सॉफ्टवेयर उत्पादों में पुराने विरासत स्रोत कोड के साथ समस्याओं का अनुभव हुआ है; उदाहरण के लिए:
 * लीगेसी कोड एक रक्षात्मक प्रोग्रामिंग पहल के तहत डिज़ाइन नहीं किया गया हो सकता है, और इसलिए नए डिज़ाइन किए गए स्रोत कोड की तुलना में बहुत कम गुणवत्ता वाला हो सकता है।
 * लीगेसी कोड को उन शर्तों के तहत लिखा और परखा जा सकता है जो अब लागू नहीं होती हैं। पुराने गुणवत्ता आश्वासन परीक्षणों की अब कोई वैधता नहीं हो सकती है।
 * उदाहरण 1: पुराने कोड को ASCII इनपुट के लिए डिज़ाइन किया गया हो सकता है लेकिन अब इनपुट UTF-8 है।
 * उदाहरण 2: 32-बिट आर्किटेक्चर पर लीगेसी कोड संकलित और परीक्षण किया जा सकता है, लेकिन जब 64-बिट आर्किटेक्चर पर संकलित किया जाता है, तो नई अंकगणितीय समस्याएं हो सकती हैं (जैसे, अमान्य हस्ताक्षर परीक्षण, अमान्य टाइप कास्ट, आदि)।
 * उदाहरण 3: लीगेसी कोड को ऑफ़लाइन मशीनों के लिए लक्षित किया जा सकता है, लेकिन नेटवर्क कनेक्टिविटी जुड़ जाने के बाद यह असुरक्षित हो जाता है।
 * लिगेसी कोड नई समस्याओं को ध्यान में रखकर नहीं लिखा गया है। उदाहरण के लिए, 1990 में लिखे गए स्रोत कोड में कई कोड इंजेक्शन भेद्यता होने की संभावना है, क्योंकि उस समय ऐसी अधिकांश समस्याओं को व्यापक रूप से समझा नहीं गया था।

विरासत की समस्या के उल्लेखनीय उदाहरण:
 * BIND, पॉल विक्सी और डेविड कॉनराड द्वारा BINDv9 के रूप में प्रस्तुत किया गया एक पुनर्लेखन (प्रोग्रामिंग) है, डिजाइन में सुरक्षा एक महत्वपूर्ण विचार था, पुरानी विरासत कोड को फिर से लिखने के लिए प्रमुख चिंताओं के रूप में नामकरण सुरक्षा, मजबूती, मापनीयता और नए प्रोटोकॉल।
 * Microsoft Windows को Windows मेटाफ़ाइल भेद्यता और WMF प्रारूप से संबंधित अन्य कारनामों का सामना करना पड़ा। Microsoft सुरक्षा प्रतिक्रिया केंद्र WMF-सुविधाओं का वर्णन इस प्रकार करता है 1990 के आसपास, WMF समर्थन जोड़ा गया था... सुरक्षा परिदृश्य में यह एक अलग समय था... सभी पूरी तरह से विश्वसनीय थे, Microsoft में सुरक्षा पहल के तहत विकसित नहीं किया जा रहा है।
 * Oracle Corporation पुरानी समस्याओं का मुकाबला कर रहा है, जैसे SQL इंजेक्शन और विशेषाधिकार वृद्धि की चिंताओं को संबोधित किए बिना लिखा गया पुराना स्रोत कोड, जिसके परिणामस्वरूप कई सुरक्षा भेद्यताएँ हैं जिन्हें ठीक करने में समय लगा है और अधूरे सुधार भी उत्पन्न हुए हैं। इसने डेविड लीचफील्ड, अलेक्जेंडर कोर्नब्रस्ट, सीज़र सेरुडो जैसे सुरक्षा विशेषज्ञों की भारी आलोचना को जन्म दिया है।  एक अतिरिक्त आलोचना यह है कि डिफ़ॉल्ट इंस्टॉलेशन (ज्यादातर पुराने संस्करणों की विरासत) उनकी अपनी सुरक्षा अनुशंसाओं के अनुरूप नहीं हैं, जैसे कि .pdf Oracle डेटाबेस सुरक्षा चेकलिस्ट, जिसमें संशोधन करना कठिन है क्योंकि कई अनुप्रयोगों को ठीक से काम करने के लिए कम सुरक्षित लीगेसी सेटिंग्स की आवश्यकता होती है।

कैननिकलाइज़ेशन
दुर्भावनापूर्ण उपयोगकर्ता गलत डेटा के नए प्रकार के प्रतिनिधित्व का आविष्कार कर सकते हैं। उदाहरण के लिए, यदि कोई प्रोग्राम /etc/Passwd (फ़ाइल) फ़ाइल तक पहुँचने को अस्वीकार करने का प्रयास करता है, तो एक क्रैकर इस फ़ाइल नाम का दूसरा संस्करण पास कर सकता है, जैसे /etc/./passwd। गैर-कानूनी फॉर्म इनपुट के कारण बग से बचने के लिए कैनॉनिकलाइज़ेशन लाइब्रेरी को नियोजित किया जा सकता है।

संभावित बग के खिलाफ कम सहनशीलता
मान लें कि कोड निर्माण जो समस्या प्रवण प्रतीत होते हैं (ज्ञात कमजोरियों के समान, आदि) बग और संभावित सुरक्षा दोष हैं। बुनियादी नियम यह है: मुझे सभी प्रकार के सुरक्षा कारनामों की जानकारी नहीं है। मुझे उन लोगों से बचाव करना चाहिए जिनके बारे में मैं जानता हूं और फिर मुझे सक्रिय होना चाहिए! .

अपना कोड सुरक्षित करने के लिए अन्य टिप्स

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

आंकड़े सुरक्षा के 3 नियम
* अन्यथा सिद्ध होने तक सभी डेटा महत्वपूर्ण हैं। * अन्यथा सिद्ध होने तक सभी डेटा दूषित हैं। * अन्यथा साबित होने तक सभी कोड असुरक्षित हैं।

डेटा सुरक्षा के बारे में ये तीन नियम बताते हैं कि आंतरिक या बाह्य रूप से किसी भी डेटा को कैसे संभालना है:
 * आप यूजरलैंड (कंप्यूटिंग) में किसी भी कोड की सुरक्षा को साबित नहीं कर सकते हैं, या, जिसे आमतौर पर क्लाइंट पर कभी भरोसा नहीं किया जाता है।

'अन्यथा सिद्ध होने तक सभी डेटा महत्वपूर्ण हैं' - इसका अर्थ है कि नष्ट होने से पहले सभी डेटा को कचरा के रूप में सत्यापित किया जाना चाहिए।

'अन्यथा सिद्ध होने तक सभी डेटा दागी हैं' - इसका मतलब है कि सभी डेटा को इस तरह से संभाला जाना चाहिए जो अखंडता को सत्यापित किए बिना शेष रनटाइम वातावरण को उजागर न करे।

'अन्यथा सिद्ध होने तक सभी कोड असुरक्षित हैं' - जबकि एक मामूली मिथ्या नाम, एक अच्छा काम करता है जो हमें यह याद दिलाता है कि हमारा कोड कभी सुरक्षित नहीं है क्योंकि बग या अपरिभाषित व्यवहार प्रोजेक्ट या सिस्टम को सामान्य SQL इंजेक्शन हमलों जैसे हमलों के लिए उजागर कर सकते हैं।

अधिक जानकारी

 * यदि डेटा की शुद्धता की जाँच करनी है, तो सत्यापित करें कि यह सही है, यह नहीं कि यह गलत है।
 * अनुबंध द्वारा डिजाइन
 * अभिकथन (कंप्यूटिंग) (जिसे मुखर प्रोग्रामिंग भी कहा जाता है)
 * कोड वापस करने के लिए एक्सेप्शन हैंडलिंग को प्राथमिकता दें
 * सामान्यतया, अपवाद संदेशों को फेंकना बेहतर होता है जो आपके अप्लिकेशन प्रोग्रामिंग अंतरफलक के हिस्से को अनुबंध द्वारा डिज़ाइन करते हैं और त्रुटि कोड मानों को वापस करने के बजाय डेवलपर को मार्गदर्शन करते हैं जो यह इंगित नहीं करते हैं कि अपवाद कहाँ हुआ या प्रोग्राम स्टैक क्या पसंद आया, डेवलपर तनाव को कम करते हुए बेहतर लॉगिंग और अपवाद हैंडलिंग आपके सॉफ़्टवेयर की मजबूती और सुरक्षा को बढ़ाएगी।

यह भी देखें

 * कंप्यूटर सुरक्षा
 * प्रतिरक्षा-जागरूक प्रोग्रामिंग

बाहरी संबंध

 * CERT Secure Coding Standards