मुझे पता है कि एसक्यूएल इंजेक्शन तैयार करने / रोकने से पूर्व उपचार किया जाता है। इससे ऐसा कैसे होता है? क्या अंतिम रूप क्वेरी जो तैयार की गई है, का उपयोग करके तैयार की गई स्ट्रिंग एक स्ट्रिंग होगी या अन्यथा?
मुझे पता है कि एसक्यूएल इंजेक्शन तैयार करने / रोकने से पूर्व उपचार किया जाता है। इससे ऐसा कैसे होता है? क्या अंतिम रूप क्वेरी जो तैयार की गई है, का उपयोग करके तैयार की गई स्ट्रिंग एक स्ट्रिंग होगी या अन्यथा?
जवाबों:
SQL इंजेक्शन के साथ समस्या यह है, कि एक उपयोगकर्ता इनपुट SQL कथन के भाग के रूप में उपयोग किया जाता है। तैयार किए गए बयानों का उपयोग करके आप उपयोगकर्ता इनपुट को एक पैरामीटर की सामग्री के रूप में नियंत्रित करने के लिए मजबूर कर सकते हैं (और एसक्यूएल कमांड के हिस्से के रूप में नहीं)।
लेकिन अगर आप अपने तैयार किए गए विवरण के लिए एक पैरामीटर के रूप में उपयोगकर्ता इनपुट का उपयोग नहीं करते हैं, बल्कि एक साथ तार जोड़कर अपनी SQL कमांड बनाते हैं, तो आप हैं अभी भी तैयार किए गए बयानों का उपयोग करते हुए भी SQL इंजेक्शन के लिए असुरक्षित ।
एक ही काम करने के दो तरीकों पर विचार करें:
PreparedStatement stmt = conn.createStatement("INSERT INTO students VALUES('" + user + "')");
stmt.execute();
या
PreparedStatement stmt = conn.prepareStatement("INSERT INTO student VALUES(?)");
stmt.setString(1, user);
stmt.execute();
यदि "उपयोगकर्ता" उपयोगकर्ता इनपुट से आया था और उपयोगकर्ता इनपुट था
Robert'); DROP TABLE students; --
फिर पहली बार में, आप hosed किया जाएगा। दूसरे में, आप सुरक्षित होंगे और लिटिल बॉबी टेबल आपके स्कूल के लिए पंजीकृत होंगे।
यह समझने के लिए कि कैसे तैयार किया गया एसक्यूएल इंजेक्शन रोकता है, हमें SQL क्वेरी निष्पादन के चरणों को समझने की आवश्यकता है।
1. संकलन चरण। 2. निष्पादन चरण।
जब भी SQL सर्वर इंजन को एक क्वेरी मिलती है, तो उसे नीचे के चरणों से गुजरना पड़ता है,
पार्सिंग और सामान्यकरण चरण: इस चरण में, वाक्यविन्यास और शब्दार्थ के लिए क्वेरी की जाँच की जाती है। यह जाँचता है कि क्वेरी में प्रयुक्त संदर्भ तालिका और कॉलम मौजूद हैं या नहीं। इसके कई अन्य कार्य भी हैं, लेकिन चलिए विस्तार से नहीं जानते हैं।
संकलन चरण: इस चरण में, क्वेरीज़ जैसे कि सेलेक्ट, जहाँ से आदि का उपयोग किया जाता है, को मशीन द्वारा समझने योग्य प्रारूप में परिवर्तित किया जाता है। यह वह चरण है जहां क्वेरी की व्याख्या की जाती है और इसके अनुरूप कार्रवाई तय की जाती है। इसके कई अन्य कार्य भी हैं, लेकिन चलिए विस्तार से नहीं जानते हैं।
क्वेरी ऑप्टिमाइज़ेशन प्लान: इस चरण में, निर्णय ट्री को उन तरीकों को खोजने के लिए बनाया जाता है, जिनसे क्वेरी निष्पादित की जा सकती है। यह उन तरीकों की संख्या का पता लगाता है जिनसे क्वेरी को निष्पादित किया जा सकता है और क्वेरी को निष्पादित करने के प्रत्येक तरीके से जुड़ी लागत। यह किसी क्वेरी को निष्पादित करने के लिए सबसे अच्छी योजना चुनता है।
कैश: क्वेरी ऑप्टिमाइज़ेशन प्लान में चयनित सर्वश्रेष्ठ योजना को कैश में संग्रहीत किया जाता है, ताकि जब भी अगली बार समान क्वेरी आए, तो उसे चरण 1, चरण 2 और चरण 3 से फिर से गुजरना न पड़े। जब अगली बार क्वेरी आएगी, तो इसे सीधे कैश में चेक किया जाएगा और निष्पादित करने के लिए वहां से उठाया जाएगा।
निष्पादन चरण:
इस चरण में, आपूर्ति की गई क्वेरी निष्पादित हो जाती है और उपयोगकर्ता को ResultSet
ऑब्जेक्ट के रूप में डेटा वापस किया जाता है।
रेडीस्टेयमेंट एसक्यूएल प्रश्नों को पूरा नहीं करते हैं और इसमें प्लेसहोल्डर (ओं) होते हैं, जो कि समय पर वास्तविक उपयोगकर्ता द्वारा प्रदान किए गए डेटा द्वारा प्रतिस्थापित किए जाते हैं।
जब भी प्लेसहोल्डर्स वाले किसी भी रेडीमेड स्टेमेंट को SQL सर्वर इंजन में पास किया जाता है, तो यह चरणों से नीचे गुजरता है
अद्यतन उपयोगकर्ता सेट उपयोगकर्ता नाम =? और पासवर्ड = आईडी कहाँ है =
ऊपर क्वेरी को पार्स किया जाएगा, विशेष उपचार के रूप में प्लेसहोल्डर्स के साथ संकलित, अनुकूलित और कैश्ड मिलेगा। इस स्तर पर क्वेरी पहले से ही संकलित है और मशीन के समझने योग्य प्रारूप में परिवर्तित हो गई है। तो हम कह सकते हैं कि कैश में संग्रहीत क्वेरी प्री-संकलित है और केवल प्लेसहोल्डर्स को उपयोगकर्ता द्वारा प्रदान किए गए डेटा के साथ प्रतिस्थापित करने की आवश्यकता है।
अब रन-टाइम में जब उपयोगकर्ता द्वारा प्रदान किया गया डेटा आता है, प्री-संकलित क्वेरी कैश से ली जाती है और प्लेसहोल्डर को उपयोगकर्ता द्वारा प्रदान किए गए डेटा से बदल दिया जाता है।
(याद रखें, स्थान धारकों को उपयोगकर्ता डेटा के साथ बदल दिए जाने के बाद, अंतिम क्वेरी को फिर से संकलित / व्याख्या नहीं किया जाता है और SQL सर्वर इंजन उपयोगकर्ता डेटा को शुद्ध डेटा के रूप में मानता है न कि एक SQL जिसे फिर से पार्स या संकलित करने की आवश्यकता होती है; जो कि तैयार किए गए विवरण की सुंदरता है। )
यदि क्वेरी को फिर से संकलन चरण से गुजरना नहीं पड़ता है, तो प्लेसहोल्डर्स पर प्रतिस्थापित डेटा को शुद्ध डेटा माना जाता है और इसका SQL सर्वर इंजन से कोई मतलब नहीं होता है और यह सीधे क्वेरी को निष्पादित करता है।
नोट: यह चरण निर्धारण के बाद का संकलन चरण है, जो क्वेरी संरचना को समझता / व्याख्या करता है और इसे सार्थक व्यवहार देता है। तैयारी के मामले में, क्वेरी केवल एक बार संकलित की जाती है और कैश्ड संकलित क्वेरी को उपयोगकर्ता डेटा को बदलने और निष्पादित करने के लिए हर समय उठाया जाता है।
रेडीस्टेडमेंट की एक बार संकलन सुविधा के कारण, यह SQL इंजेक्शन के हमले से मुक्त है।
आप यहाँ उदाहरण के साथ विस्तृत विवरण प्राप्त कर सकते हैं: https://javabypatel.blogspot.com/2015/09/how-prepared-statement-in-java-prevents-sql-injection.html
एक रेडीस्टेडमेंट में प्रयुक्त एसक्यूएल चालक पर पूर्वनिर्धारित होता है। उस बिंदु से, मापदंडों को चालक को शाब्दिक मान के रूप में भेजा जाता है और एसक्यूएल के निष्पादन योग्य हिस्से नहीं; इस प्रकार कोई SQL एक पैरामीटर का उपयोग करके इंजेक्ट नहीं किया जा सकता है। रेडीस्टेडमेंट्स का एक अन्य लाभकारी साइड इफेक्ट (precompilation + केवल पैरामीटर भेजना) प्रदर्शन में सुधार होता है जब कई बार बयानों को पैरामीटर के लिए अलग-अलग मानों के साथ भी चलाते हैं (यह मानते हुए कि ड्राइवर रेडीमेडस्टेटमेंट्स का समर्थन करता है) क्योंकि ड्राइवर को SQL पार्स करने और प्रत्येक को संकलित करने की आवश्यकता नहीं है। समय बदल जाता है।
मुझे लगता है है यह एक स्ट्रिंग होगी। लेकिन इनपुट मापदंडों को डेटाबेस में भेजा जाएगा और वास्तविक एसक्यूएल स्टेटमेंट बनाने से पहले उपयुक्त कास्ट / रूपांतरण लागू किए जाएंगे।
आपको एक उदाहरण देने के लिए, यह कोशिश कर सकता है और देखें कि क्या कास्ट / रूपांतरण काम करता है।
यदि यह काम करता है, तो यह एक अंतिम विवरण बना सकता है।
SELECT * From MyTable WHERE param = CAST('10; DROP TABLE Other' AS varchar(30))
सांख्यिक पैरामीटर को स्वीकार करते हुए SQL कथन के साथ एक उदाहरण का प्रयास करें।
अब, एक स्ट्रिंग चर (संख्यात्मक सामग्री के साथ जो संख्यात्मक पैरामीटर के रूप में स्वीकार्य है) पास करने का प्रयास करें। क्या इसमें कोई त्रुटि है?
अब, एक स्ट्रिंग चर (ऐसी सामग्री के साथ जो सांख्यिक पैरामीटर के रूप में स्वीकार्य नहीं है) पास करने का प्रयास करें। देखते हैं क्या होता है?
तैयार कथन अधिक सुरक्षित है। यह एक पैरामीटर को निर्दिष्ट प्रकार में बदल देगा।
उदाहरण के लिए stmt.setString(1, user);
रूपांतरित होगाuser
पैरामीटर को स्ट्रिंग में ।
मान लीजिए कि पैरामीटर में एक निष्पादन योग्य कमांड युक्त SQL स्ट्रिंग है : तैयार किए गए विवरण का उपयोग करने की अनुमति नहीं होगी।
यह मेटाचैकर (उर्फ ऑटो रूपांतरण) को जोड़ता है।
इससे यह अधिक सुरक्षित है।
SQL इंजेक्शन: जब उपयोगकर्ता के पास कुछ ऐसा इनपुट करने का मौका होता है जो sql स्टेटमेंट का हिस्सा हो सकता है
उदाहरण के लिए:
स्ट्रिंग क्वेरी = "INSERT इनटू स्टूडेंट्स वैल्यूज़ ('" + उपयोगकर्ता + "')"
जब उपयोगकर्ता इनपुट "रॉबर्ट '); ड्रॉप टेबल छात्रों; - "इनपुट के रूप में, यह SQL इंजेक्शन का कारण बनता है
कैसे तैयार बयान इसे रोकता है?
स्ट्रिंग क्वेरी = "छात्रों को शामिल करें ('" + ": नाम" + "')"
पैरामीटर्स.डालव्यू ("नाम", उपयोगकर्ता);
=> जब उपयोगकर्ता इनपुट फिर से "रॉबर्ट '); ड्रॉप टेबल छात्रों; - ", इनपुट स्ट्रिंग को ड्राइवर पर शाब्दिक मूल्यों के रूप में पहले से रखा गया है और मुझे लगता है कि इसे पसंद किया जा सकता है:
कास्ट (रॉबर्ट '); ड्रॉप टेबल छात्रों; - 'एएस वर्चर (30))
इसलिए अंत में, स्ट्रिंग को शाब्दिक रूप से तालिका में नाम के रूप में डाला जाएगा।
http://blog.linguiming.com/index.php/2018/01/10/why-prepared-statement-avoids-sql-injection/
CAST(‘Robert’);
से CAST(‘Robert’); DROP TABLE students; –‘ AS varchar(30))
टूट जाएगा, तो यह तालिका ड्रॉप करने कि अगर मामला था आगे बढ़ना होगा। यह इंजेक्शन बंद कर देता है, इसलिए मेरा मानना है कि परिदृश्य को समझाने के लिए उदाहरण पर्याप्त नहीं है।
तैयार बयान:
1) SQL स्टेटमेंट का प्रीकंप्लीमेंटेशन और DB- साइड कैशिंग समग्र तेजी से निष्पादन और बैचों में समान SQL स्टेटमेंट को फिर से उपयोग करने की क्षमता की ओर जाता है।
2) एसक्यूएल इंजेक्शन हमलों की स्वत: रोकथाम बिलिन द्वारा उद्धरण और अन्य विशेष पात्रों से बचकर। ध्यान दें कि इसके लिए यह आवश्यक है कि आप मान सेट करने के लिए किसी भी रेडीमेड सेटमेंटएक्सएक्सएक्सएक्सएक्स () तरीकों का उपयोग करें।
जैसा कि इस पोस्ट में बताया गया है , PreparedStatement
यदि आप अभी भी स्ट्रैटनिंग कर रहे हैं तो अकेले आपकी मदद नहीं करते हैं।
उदाहरण के लिए, एक दुष्ट हमलावर अभी भी निम्नलिखित कर सकता है:
यदि आप बाइंड मापदंडों का उपयोग नहीं कर रहे हैं तो न केवल SQL, बल्कि JPQL या HQL से भी समझौता किया जा सकता है।
निचला रेखा, आपको एसक्यूएल स्टेटमेंट का निर्माण करते समय स्ट्रिंग कॉनट्रैक्शन का उपयोग कभी नहीं करना चाहिए। उस उद्देश्य के लिए समर्पित API का उपयोग करें:
तैयार किए गए विवरणों में उपयोगकर्ता को पैरामीटर के रूप में डेटा दर्ज करने के लिए मजबूर किया जाता है। यदि उपयोगकर्ता कुछ कमजोर बयानों जैसे DROP TABLE या SELECT * FROM USERS में प्रवेश करता है तो डेटा प्रभावित नहीं होगा क्योंकि इन्हें SQL कथन के पैरामीटर के रूप में माना जाएगा