एक उत्कृष्ट सवाल।
पलायन
से बचने के लिए काम करने के लिए और अधिक परंपरागत तरीका है। यह किसी भी असुरक्षित डेटा में बैकस्लाश जोड़ता है, इसलिए यदि कोई प्रत्यक्ष SQL कथन पास करने का प्रयास करता है, तो वह सचमुच लिया जाने की बजाय हानिरहित रूप से गुजर जाएगा। यहां पकड़ यह है कि कुछ किनारे के मामले हैं जहां एक हमलावर अभी भी बच निकलने वाले समारोह के आसपास हो सकता है। इनमें से अधिकांश भाग में आर्केन चाल शामिल हैं जैसे कि चरित्र सेट और ऐसे बदलना। समझने की मुख्य बात, यदि आप भागने का पीछा करते हैं, तो यह सुनिश्चित नहीं है कि सभी मामलों में सुरक्षा के लिए अग्नि शर्त सुनिश्चित नहीं है।
तैयार वक्तव्य
तैयार बयान एक ही खामियों क्योंकि आप दो भागों में आपकी क्वेरी को तोड़ने रहे हैं के अधीन नहीं हैं। पहले भाग में क्वेरी होती है और दूसरे में उस क्वेरी के पैरामीटर होते हैं। नतीजतन, MySQL पैरामीटर को एक सुरक्षित तरीके से अलग तरीके से इलाज कर सकता है जो इंजेक्शन की अनुमति नहीं देगा (कम से कम किसी को अभी तक कोई रास्ता नहीं मिला है)।
यदि आपको अलग-अलग मूल्यों के साथ एक ही क्वेरी को चलाने की आवश्यकता है, तो तैयार वक्तव्य आपको बहुत समय बचाते हैं। MySQL स्मृति में कथन को संग्रहीत करता है ताकि एकाधिक निष्पादन बहुत तेज़ हो।
आप अपनी क्वेरी के कुछ हिस्सों को पैरामीटर नहीं कर सकते हैं (यानी टेबल नाम)।
चेतावनी emptor
तो तैयार बयानों 100% सुरक्षित हैं, है ना? क्यों न सिर्फ सब कुछ के लिए तैयार बयान का उपयोग करें?हमने एसक्यूएल इंजेक्शन फॉरवर्ड हल कर लिया है! खैर, काफी नहीं। कुछ चेतावनी हैं जिन्हें आपको पहले के बारे में जानना है।
पहला mysqli
पर विशिष्ट है। mysqli
में परिणाम लौटने वाले तैयार बयान करने के लिए आप MySQL Native Driver (mysqlnd
) स्थापित करना चाहते हैं। विशेष रूप से, mysqli_stmt_get_result, जो परिणाम सेट को mysqli_query
जैसा देता है। कुछ साझा मेजबान और पुराने सर्वर अभी भी पुराने MySQL क्लाइंट लाइब्रेरी का उपयोग कर रहे हैं। यदि आप जानना चाहते हैं कि आप किसका उपयोग कर रहे हैं, तो phpinfo()
चलाएं और mysqlnd
ब्लॉक देखें। mysqlnd
एक अच्छा विचार है भले ही आप तैयार कथन का उपयोग नहीं कर रहे हैं क्योंकि यह PHP टीम द्वारा विशेष रूप से MySQL से अधिक बनाने के लिए बनाया गया है। कुछ लोग ड्राइवर को नहीं बदल सकते हैं, हालांकि, यह एक सर्वर कॉन्फ़िगरेशन स्तर परिवर्तन है।
दूसरा उन लोगों के लिए है जो PDO (PHP में अपने डेटाबेस से कनेक्ट करने का एक और तरीका) का उपयोग करते हैं। अब, पीडीओ के पास तैयार बयानों को संभालने का एक बेहतर तरीका है (इसमें एक आसान एलियासिंग सिस्टम है) और तैयार बयान करने के लिए mysqlnd
की आवश्यकता नहीं है। यहां चेतावनी यह है कि पीडीओ, डिफ़ॉल्ट रूप से, केवल तैयार बयानों को अनुकरण करता है, जिसका अर्थ है कि यदि आप इसे सही तरीके से कॉन्फ़िगर नहीं करते हैं, तो आप जो भी कर रहे हैं वह लाइब्रेरी का उपयोग कर रहा है जो आपके लिए बच निकलेगा। अधिक जानकारी के लिए PDO::ATTR_EMULATE_PREPARES
के तहत this page देखें।
तीसरा सबसे दूर तक सबसे महत्वपूर्ण है और आपको यहां पर ध्यान देना होगा क्योंकि यदि आप सावधान नहीं हैं तो इससे आपके कार्यक्रम पर असर पड़ सकता है। अधिकतर लोग जो तैयार बयानों की वकालत करते हैं, वे यहां सबसे बड़ी गड़बड़ी को नजरअंदाज करते हैं, जो आप अपने डेटाबेस पर अधिक प्रश्न पूछ रहे हैं (यहां MySQL 5.5 manual सीएलआई के माध्यम से उन्हें कैसे करें)। अब, INSERT
और UPDATE
बयान के लिए जहां आप एक ही क्वेरी को चलाने के लिए जा रहे हैं और वहां कोई तुलना नहीं है। तैयार बयान आपको अपने समेकित समकक्षों पर बहुत समय बचाते हैं। लेकिन SELECT
के लिए, यह बहुत कम स्पष्ट हो जाता है। ऊपर मेरा उदाहरण ले लो। यह autonumber क्षेत्र के माध्यम से एक रिकॉर्ड की एक साधारण खींच है। लेकिन एक के बजाय अब चलाने के लिए 2 प्रश्न लेते हैं। यदि यह कम यातायात वाला एक आंतरिक अनुप्रयोग है जो शायद एक बड़ा सौदा नहीं हो सकता है, लेकिन यदि उस पृष्ठ को दिन में 100,000 विचार मिलते हैं, तो हो सकता है कि आप उस पृष्ठ पर ओवरहेड को कम करना चाहें। यदि ऐसा है, तो सीधे सीधी क्वेरी बनाना आपके लिए एक समाधान हो सकता है।
तो, संक्षेप में
mysqli_real_escape_string
कुछ नुकसान है, लेकिन जब तक आप उन कमियों को समझते हैं और आप और एसक्यूएल इंजेक्शन के बीच केवल सुरक्षा के रूप में यह इलाज नहीं है एक क्वेरी के लिए "पर्याप्त सुरक्षित" बनाया जा सकता है।
mysqli_prepare
हमेशा सुरक्षित है, लेकिन यह भी अधिक पूछताछ करता है ताकि यह आपके डेटाबेस और/या प्रोग्राम के लिए उतना ही कुशल न हो। कुछ प्रश्न हमेशा तैयार किए जाने चाहिए, जबकि कुछ शायद नहीं होना चाहिए।
अन्य समाधान
- Typecasting
- श्वेत सूची (जहां आप यह सुनिश्चित पीएचपी के माध्यम से, (कुछ सीमाएं लेकिन वह असुरक्षित एसक्यूएल के लिए के साथ-साथ कुछ भी नहीं है), क्या मान होंगे भी या तो का उपयोग कर समाधान के बजाय उपयोगी कर सकते हैं स्वीकार्य और केवल उन मानों को अनुमति दें)
अंत में, यह पता लगाने के लिए आप कहां उपयुक्त हैं और दूसरे का उपयोग करने के लिए बेहतर हो सकता है।
सहमत हैं, लेकिन ध्यान दें कि तैयार कथन के पैरामीटर सर्वर द्वारा SQL के लिए कभी भी पार्स नहीं किए जाते हैं, इसलिए एसक्यूएल के लिए इंजेक्शन के लिए यह असंभव * है; जबकि बचने के तरीके [हैं] [http://vigilance.fr/vulnerability/MySQL-SQL-injection-via-multi-byte-characters-5885) (और [इसके अधीन रहें] (http://stackoverflow.com/ ए/12118602)) शोषण योग्य भेद्यताएं, कुछ अस्पष्ट किनारे के मामलों में, सफल इंजेक्शन हमलों का कारण बन सकती हैं। – eggyal
@eggyal: बिल्कुल। यही कारण है कि वे केवल कार्यात्मक रूप से समान हैं - वास्तव में - जैसा कि कहा गया है, ठीक से बच निकला। हालांकि, इसे ठीक से करना एक आसान काम नहीं है। – jwueller
और यहां मैंने सोचा था कि पीडीओ हमें पढ़ने के लिए सभी @eggyal को बचाने जा रहा था http://stackoverflow.com/a/12118602 (नीचे ** खराब **) –