SQLed इंजेक्शन की तैयारी या रोकथाम कैसे करता है?


122

मुझे पता है कि एसक्यूएल इंजेक्शन तैयार करने / रोकने से पूर्व उपचार किया जाता है। इससे ऐसा कैसे होता है? क्या अंतिम रूप क्वेरी जो तैयार की गई है, का उपयोग करके तैयार की गई स्ट्रिंग एक स्ट्रिंग होगी या अन्यथा?


3
तकनीकी रूप से JDBC युक्ति जोर नहीं देती है कि SQL इंजेक्शन दोष नहीं हैं। मुझे किसी भी ड्राइव का पता नहीं है जो प्रभावित हैं।
टॉम हॉन्टिन -

3
@ जयेश मैं यहाँ एक उत्तर के रूप में आपके ब्लॉग की सामग्री जोड़ने का सुझाव देता हूँ। अधिकांश उत्तर केवल अंतर b / w डायनामिक SQL क्वेरी पीढ़ी और तैयार stmt बता रहे हैं। वे इस मुद्दे को संबोधित नहीं कर रहे हैं कि क्यों तैयार किए गए वक्तव्य बेहतर काम करते हैं जो आपका ब्लॉग करता है।
पवन मंजूनाथ

1
उत्तर के रूप में जोड़ा गया, मुझे आशा है कि यह मदद करता है।
जयेश

जवाबों:


78

SQL इंजेक्शन के साथ समस्या यह है, कि एक उपयोगकर्ता इनपुट SQL कथन के भाग के रूप में उपयोग किया जाता है। तैयार किए गए बयानों का उपयोग करके आप उपयोगकर्ता इनपुट को एक पैरामीटर की सामग्री के रूप में नियंत्रित करने के लिए मजबूर कर सकते हैं (और एसक्यूएल कमांड के हिस्से के रूप में नहीं)।

लेकिन अगर आप अपने तैयार किए गए विवरण के लिए एक पैरामीटर के रूप में उपयोगकर्ता इनपुट का उपयोग नहीं करते हैं, बल्कि एक साथ तार जोड़कर अपनी SQL कमांड बनाते हैं, तो आप हैं अभी भी तैयार किए गए बयानों का उपयोग करते हुए भी SQL इंजेक्शन के लिए असुरक्षित


1
ज़रूर, लेकिन आप अभी भी अपने कुछ या सभी मापदंडों को हार्डकोड कर सकते हैं।
स्पर्श

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

4
FWIW तैयार बयान एक JDBC बात नहीं है - वे एक SQL चीज हैं। आप SQL कन्सोल के भीतर से तैयार कथनों को तैयार और निष्पादित कर सकते हैं। रेडीस्टेडमेंट सिर्फ जेडीबीसी के भीतर से उनका समर्थन करता है।
बेलाज

198

एक ही काम करने के दो तरीकों पर विचार करें:

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 किया जाएगा। दूसरे में, आप सुरक्षित होंगे और लिटिल बॉबी टेबल आपके स्कूल के लिए पंजीकृत होंगे।


8
इसलिए, अगर मुझे यह सही लगता है, तो दूसरे उदाहरण में क्वेरी जो निष्पादित की जाएगी, वास्तव में होगी: INSERT INTO स्टूडेंट VALUES ("रॉबर्ट '); DROP टेबल स्टूडेंट्स; -") - या कम से कम ऐसा कुछ। क्या ये सच है?
अधिकतम

18
नहीं, FIRST उदाहरण में, आपको वह कथन मिलेगा। दूसरे में, यह "रॉबर्ट ') सम्मिलित करेगा; DROP टेबल छात्रों; -" उपयोगकर्ता तालिका में।
पॉल टॉम्बलिन

3
Thats जो मेरा मतलब था, दूसरे उदाहरण में ("सुरक्षित" एक), स्ट्रिंग रॉबर्ट '); ड्रॉप टेबल छात्रों; - छात्र तालिका में क्षेत्र में सहेजा जाएगा। क्या मैंने कुछ और लिखा? ;)
मैक्स

7
क्षमा करें, घोंसले के शिकार कुछ ऐसा है जो मैं इस तरह के भ्रम की वजह से बचने की कोशिश करता हूं। यही कारण है कि मुझे मापदंडों के साथ रेडीस्टेडमेंट्स पसंद हैं।
पॉल टॉमब्लिन

59
छोटे बॉबी टेबल्स। XD महान संदर्भ
Amalgovinus

128

यह समझने के लिए कि कैसे तैयार किया गया एसक्यूएल इंजेक्शन रोकता है, हमें SQL क्वेरी निष्पादन के चरणों को समझने की आवश्यकता है।

1. संकलन चरण। 2. निष्पादन चरण।

जब भी SQL सर्वर इंजन को एक क्वेरी मिलती है, तो उसे नीचे के चरणों से गुजरना पड़ता है,

क्वेरी निष्पादन चरण

  1. पार्सिंग और सामान्यकरण चरण: इस चरण में, वाक्यविन्यास और शब्दार्थ के लिए क्वेरी की जाँच की जाती है। यह जाँचता है कि क्वेरी में प्रयुक्त संदर्भ तालिका और कॉलम मौजूद हैं या नहीं। इसके कई अन्य कार्य भी हैं, लेकिन चलिए विस्तार से नहीं जानते हैं।

  2. संकलन चरण: इस चरण में, क्वेरीज़ जैसे कि सेलेक्ट, जहाँ से आदि का उपयोग किया जाता है, को मशीन द्वारा समझने योग्य प्रारूप में परिवर्तित किया जाता है। यह वह चरण है जहां क्वेरी की व्याख्या की जाती है और इसके अनुरूप कार्रवाई तय की जाती है। इसके कई अन्य कार्य भी हैं, लेकिन चलिए विस्तार से नहीं जानते हैं।

  3. क्वेरी ऑप्टिमाइज़ेशन प्लान: इस चरण में, निर्णय ट्री को उन तरीकों को खोजने के लिए बनाया जाता है, जिनसे क्वेरी निष्पादित की जा सकती है। यह उन तरीकों की संख्या का पता लगाता है जिनसे क्वेरी को निष्पादित किया जा सकता है और क्वेरी को निष्पादित करने के प्रत्येक तरीके से जुड़ी लागत। यह किसी क्वेरी को निष्पादित करने के लिए सबसे अच्छी योजना चुनता है।

  4. कैश: क्वेरी ऑप्टिमाइज़ेशन प्लान में चयनित सर्वश्रेष्ठ योजना को कैश में संग्रहीत किया जाता है, ताकि जब भी अगली बार समान क्वेरी आए, तो उसे चरण 1, चरण 2 और चरण 3 से फिर से गुजरना न पड़े। जब अगली बार क्वेरी आएगी, तो इसे सीधे कैश में चेक किया जाएगा और निष्पादित करने के लिए वहां से उठाया जाएगा।

  5. निष्पादन चरण: इस चरण में, आपूर्ति की गई क्वेरी निष्पादित हो जाती है और उपयोगकर्ता को ResultSetऑब्जेक्ट के रूप में डेटा वापस किया जाता है।

उपर्युक्त चरणों पर तैयार किए गए एपीआई के व्यवहार

  1. रेडीस्टेयमेंट एसक्यूएल प्रश्नों को पूरा नहीं करते हैं और इसमें प्लेसहोल्डर (ओं) होते हैं, जो कि समय पर वास्तविक उपयोगकर्ता द्वारा प्रदान किए गए डेटा द्वारा प्रतिस्थापित किए जाते हैं।

  2. जब भी प्लेसहोल्डर्स वाले किसी भी रेडीमेड स्टेमेंट को SQL सर्वर इंजन में पास किया जाता है, तो यह चरणों से नीचे गुजरता है

    1. पार्सिंग और सामान्यकरण चरण
    2. संकलन चरण
    3. क्वेरी ऑप्टिमाइज़ेशन प्लान
    4. कैश (प्लेसहोल्डर्स के साथ संकलित क्वेरी कैश में संग्रहीत की जाती है)

अद्यतन उपयोगकर्ता सेट उपयोगकर्ता नाम =? और पासवर्ड = आईडी कहाँ है =

  1. ऊपर क्वेरी को पार्स किया जाएगा, विशेष उपचार के रूप में प्लेसहोल्डर्स के साथ संकलित, अनुकूलित और कैश्ड मिलेगा। इस स्तर पर क्वेरी पहले से ही संकलित है और मशीन के समझने योग्य प्रारूप में परिवर्तित हो गई है। तो हम कह सकते हैं कि कैश में संग्रहीत क्वेरी प्री-संकलित है और केवल प्लेसहोल्डर्स को उपयोगकर्ता द्वारा प्रदान किए गए डेटा के साथ प्रतिस्थापित करने की आवश्यकता है।

  2. अब रन-टाइम में जब उपयोगकर्ता द्वारा प्रदान किया गया डेटा आता है, प्री-संकलित क्वेरी कैश से ली जाती है और प्लेसहोल्डर को उपयोगकर्ता द्वारा प्रदान किए गए डेटा से बदल दिया जाता है।

PrepareStatementWorking

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

यदि क्वेरी को फिर से संकलन चरण से गुजरना नहीं पड़ता है, तो प्लेसहोल्डर्स पर प्रतिस्थापित डेटा को शुद्ध डेटा माना जाता है और इसका SQL सर्वर इंजन से कोई मतलब नहीं होता है और यह सीधे क्वेरी को निष्पादित करता है।

नोट: यह चरण निर्धारण के बाद का संकलन चरण है, जो क्वेरी संरचना को समझता / व्याख्या करता है और इसे सार्थक व्यवहार देता है। तैयारी के मामले में, क्वेरी केवल एक बार संकलित की जाती है और कैश्ड संकलित क्वेरी को उपयोगकर्ता डेटा को बदलने और निष्पादित करने के लिए हर समय उठाया जाता है।

रेडीस्टेडमेंट की एक बार संकलन सुविधा के कारण, यह SQL इंजेक्शन के हमले से मुक्त है।

आप यहाँ उदाहरण के साथ विस्तृत विवरण प्राप्त कर सकते हैं: https://javabypatel.blogspot.com/2015/09/how-prepared-statement-in-java-prevents-sql-injection.html


3
अच्छी व्याख्या
धीरज जोशी

4
शाब्दिक रूप से HOW पर सबसे पूर्ण उत्तर यह टुकड़ा काम करता है
जौएल

यह बहुत मददगार था। विस्तृत विवरण के लिए धन्यवाद।
अज्ञात

26

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


इसे उस तरह लागू नहीं किया जाना चाहिए, और मेरा मानना ​​है कि यह अक्सर नहीं होता है।
टॉम हैटिन -

4
दरअसल एसक्यूएल आमतौर पर डेटाबेस पर पूर्वनिर्धारित होता है। यही है, डेटाबेस पर एक निष्पादन योजना तैयार की जाती है। जब आप क्वेरी को निष्पादित करते हैं तो योजना उन मापदंडों के साथ निष्पादित होती है। अतिरिक्त लाभ यह है कि एक ही कथन को हर बार एक नई योजना संकलित किए बिना क्वेरी प्रोसेसर के बिना विभिन्न मापदंडों के साथ निष्पादित किया जा सकता है।
बेलाज

3

मुझे लगता है है यह एक स्ट्रिंग होगी। लेकिन इनपुट मापदंडों को डेटाबेस में भेजा जाएगा और वास्तविक एसक्यूएल स्टेटमेंट बनाने से पहले उपयुक्त कास्ट / रूपांतरण लागू किए जाएंगे।

आपको एक उदाहरण देने के लिए, यह कोशिश कर सकता है और देखें कि क्या कास्ट / रूपांतरण काम करता है।
यदि यह काम करता है, तो यह एक अंतिम विवरण बना सकता है।

   SELECT * From MyTable WHERE param = CAST('10; DROP TABLE Other' AS varchar(30))

सांख्यिक पैरामीटर को स्वीकार करते हुए SQL कथन के साथ एक उदाहरण का प्रयास करें।
अब, एक स्ट्रिंग चर (संख्यात्मक सामग्री के साथ जो संख्यात्मक पैरामीटर के रूप में स्वीकार्य है) पास करने का प्रयास करें। क्या इसमें कोई त्रुटि है?

अब, एक स्ट्रिंग चर (ऐसी सामग्री के साथ जो सांख्यिक पैरामीटर के रूप में स्वीकार्य नहीं है) पास करने का प्रयास करें। देखते हैं क्या होता है?


3

तैयार कथन अधिक सुरक्षित है। यह एक पैरामीटर को निर्दिष्ट प्रकार में बदल देगा।

उदाहरण के लिए stmt.setString(1, user);रूपांतरित होगाuser पैरामीटर को स्ट्रिंग में ।

मान लीजिए कि पैरामीटर में एक निष्पादन योग्य कमांड युक्त SQL स्ट्रिंग है : तैयार किए गए विवरण का उपयोग करने की अनुमति नहीं होगी।

यह मेटाचैकर (उर्फ ऑटो रूपांतरण) को जोड़ता है।

इससे यह अधिक सुरक्षित है।


2

SQL इंजेक्शन: जब उपयोगकर्ता के पास कुछ ऐसा इनपुट करने का मौका होता है जो sql स्टेटमेंट का हिस्सा हो सकता है

उदाहरण के लिए:

स्ट्रिंग क्वेरी = "INSERT इनटू स्टूडेंट्स वैल्यूज़ ('" + उपयोगकर्ता + "')"

जब उपयोगकर्ता इनपुट "रॉबर्ट '); ड्रॉप टेबल छात्रों; - "इनपुट के रूप में, यह SQL इंजेक्शन का कारण बनता है

कैसे तैयार बयान इसे रोकता है?

स्ट्रिंग क्वेरी = "छात्रों को शामिल करें ('" + ": नाम" + "')"

पैरामीटर्स.डालव्यू ("नाम", उपयोगकर्ता);

=> जब उपयोगकर्ता इनपुट फिर से "रॉबर्ट '); ड्रॉप टेबल छात्रों; - ", इनपुट स्ट्रिंग को ड्राइवर पर शाब्दिक मूल्यों के रूप में पहले से रखा गया है और मुझे लगता है कि इसे पसंद किया जा सकता है:

कास्ट (रॉबर्ट '); ड्रॉप टेबल छात्रों; - 'एएस वर्चर (30))

इसलिए अंत में, स्ट्रिंग को शाब्दिक रूप से तालिका में नाम के रूप में डाला जाएगा।

http://blog.linguiming.com/index.php/2018/01/10/why-prepared-statement-avoids-sql-injection/


1
अगर मैं गलत नहीं हूँ, भाग CAST(‘Robert’);से CAST(‘Robert’); DROP TABLE students; –‘ AS varchar(30))टूट जाएगा, तो यह तालिका ड्रॉप करने कि अगर मामला था आगे बढ़ना होगा। यह इंजेक्शन बंद कर देता है, इसलिए मेरा मानना ​​है कि परिदृश्य को समझाने के लिए उदाहरण पर्याप्त नहीं है।
Héctor vlvarez

1

तैयार बयान:

1) SQL स्टेटमेंट का प्रीकंप्लीमेंटेशन और DB- साइड कैशिंग समग्र तेजी से निष्पादन और बैचों में समान SQL स्टेटमेंट को फिर से उपयोग करने की क्षमता की ओर जाता है।

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


1

जैसा कि इस पोस्ट में बताया गया है , PreparedStatementयदि आप अभी भी स्ट्रैटनिंग कर रहे हैं तो अकेले आपकी मदद नहीं करते हैं।

उदाहरण के लिए, एक दुष्ट हमलावर अभी भी निम्नलिखित कर सकता है:

  • स्लीप फ़ंक्शन को कॉल करें ताकि आपके सभी डेटाबेस कनेक्शन व्यस्त हो जाएं, इसलिए आपके एप्लिकेशन को अनुपलब्ध बना दिया जाएगा
  • डीबी से संवेदनशील डेटा निकालना
  • उपयोगकर्ता प्रमाणीकरण को दरकिनार

यदि आप बाइंड मापदंडों का उपयोग नहीं कर रहे हैं तो न केवल SQL, बल्कि JPQL या HQL से भी समझौता किया जा सकता है।

निचला रेखा, आपको एसक्यूएल स्टेटमेंट का निर्माण करते समय स्ट्रिंग कॉनट्रैक्शन का उपयोग कभी नहीं करना चाहिए। उस उद्देश्य के लिए समर्पित API का उपयोग करें:


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

-3

तैयार किए गए विवरणों में उपयोगकर्ता को पैरामीटर के रूप में डेटा दर्ज करने के लिए मजबूर किया जाता है। यदि उपयोगकर्ता कुछ कमजोर बयानों जैसे DROP TABLE या SELECT * FROM USERS में प्रवेश करता है तो डेटा प्रभावित नहीं होगा क्योंकि इन्हें SQL कथन के पैरामीटर के रूप में माना जाएगा


कम पूर्वसूचनाओं के साथ चयनित उत्तर के समान उत्तर।
जुलिएन मेरेट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.