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

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

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

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

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

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

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

आंतरिक डेटा वैधता पर भरोसा
अत्यधिक रक्षात्मक प्रोग्रामिंग <वाक्यविन्यास प्रकाश लैंग = सी> const char* trafficlight_colorname(enum traffic_light_color c) { स्विच (सी) { मामला TRAFFICLIGHT_RED: वापसी लाल; मामला TRAFFICLIGHT_YELLOW: पीला लौटें; केस TRAFFICLIGHT_GREEN: रिटर्न ग्रीन; }   काला लौटें; // एक मृत ट्रैफिक लाइट के रूप में संभाला जाना। // चेतावनी: यह अंतिम 'वापसी' कथन एक अनुकूलन द्वारा हटा दिया जाएगा // कंपाइलर यदि 'traffic_light_color' के सभी संभावित मान सूचीबद्ध हैं // पिछला 'स्विच' स्टेटमेंट ... } 

आक्रामक प्रोग्रामिंग <वाक्यविन्यास प्रकाश लैंग = सी> const char* trafficlight_colorname(enum traffic_light_color c) { स्विच (सी) { मामला TRAFFICLIGHT_RED: वापसी लाल; मामला TRAFFICLIGHT_YELLOW: पीला लौटें; केस TRAFFICLIGHT_GREEN: रिटर्न ग्रीन; }   मुखर (0); // जोर दें कि यह खंड पहुंच योग्य नहीं है। // चेतावनी: यह 'जोर' फ़ंक्शन कॉल एक अनुकूलन द्वारा हटा दी जाएगी // कंपाइलर यदि 'traffic_light_color' के सभी संभावित मान सूचीबद्ध हैं // पिछला 'स्विच' स्टेटमेंट ... } 

सॉफ्टवेयर घटकों पर भरोसा करना
अत्यधिक रक्षात्मक प्रोग्रामिंग <वाक्यविन्यास प्रकाश लैंग = सी> अगर (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