Sql इंजेक्शन को रोकने के लिए पैरामीटर्स वास्तव में पर्याप्त हैं?


83

मैं एसक्यूएल प्रश्नों में मापदंडों का उपयोग करने की अच्छाई के बारे में अपने सहयोगियों और यहां एसओ दोनों को प्रचार कर रहा हूं, विशेष रूप से .NET अनुप्रयोगों में। मैं भी एसक्यूएल इंजेक्शन हमलों के खिलाफ प्रतिरक्षा देने के रूप में उन्हें वादा करने के लिए इतनी दूर चला गया है।

लेकिन मुझे आश्चर्य हो रहा है कि क्या यह वास्तव में सच है। क्या कोई ज्ञात एसक्यूएल इंजेक्शन हमले हैं जो एक पैरामीटर क्वेरी के खिलाफ सफल होंगे? क्या आप उदाहरण के लिए एक स्ट्रिंग भेज सकते हैं जो सर्वर पर एक बफर अतिप्रवाह का कारण बनता है?

यह सुनिश्चित करने के लिए कि एक वेब एप्लिकेशन सुरक्षित है (उपयोगकर्ता इनपुट और इस तरह के सभी सामान को साफ करने की तरह), लेकिन अब मैं एसक्यूएल इंजेक्शन के बारे में सोच रहा हूं, अन्य विचार हैं। मुझे विशेष रूप से MsSQL 2005 और 2008 के खिलाफ हमलों में दिलचस्पी है क्योंकि वे मेरे प्राथमिक डेटाबेस हैं, लेकिन सभी डेटाबेस दिलचस्प हैं।

संपादित करें: यह स्पष्ट करने के लिए कि मैं मापदंडों और मानकीकृत प्रश्नों से क्या मतलब रखता हूं। एक स्ट्रिंग में sql क्वेरी बनाने के बजाय "वैरिएबल्स" का उपयोग करने का मेरा मतलब है कि मापदंडों का उपयोग करके।
इसलिए ऐसा करने के बजाय:

SELECT * FROM Table WHERE Name = 'a name'

हम यह करते हैं:

SELECT * FROM Table WHERE Name = @Name

और फिर क्वेरी / कमांड ऑब्जेक्ट पर @Name पैरामीटर का मान सेट करें।


हमें यह स्पष्ट करना चाहिए कि मापदंडों का क्या मतलब है (जैसा कि जोनाथन लेफ़लर ने बताया) - मैं संग्रहीत-प्रक्रिया मापदंडों को सोच रहा था, लेकिन वहाँ भी हैं? parms और {0} parms ...
स्टीवन ए। लोव

यह कहना बहुत आसान है, हम क्वेरी बनाने के लिए कंसीनेशन का उपयोग नहीं करते हैं।

चूंकि टैग asp.net है, इसलिए मुझे लगता है कि आप वेब एप्लिकेशन बना रहे हैं। इस मामले में, आपको XSS हमलों और शायद दूसरों का भी ध्यान रखना चाहिए
Spikolynn

जवाबों:


50

प्लेसहोल्डर इंजेक्शन को रोकने के लिए पर्याप्त हैं। आप अभी भी ओवरफ्लो को बफर करने के लिए खुले हो सकते हैं, लेकिन यह SQL इंजेक्शन से हमले का एक बिल्कुल अलग स्वाद है (हमला वेक्टर SQL सिंटैक्स नहीं बल्कि बाइनरी होगा)। चूंकि पारित किए गए पैरामीटर सभी ठीक से बच जाएंगे, इसलिए किसी हमलावर के पास डेटा को पारित करने का कोई तरीका नहीं है जिसे "लाइव" SQL की तरह माना जाएगा।

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

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

उस ने कहा, यदि आप security_levelकिसी चीज़ के मूल्य को निर्धारित करने के लिए उपयोग इनपुट का उपयोग कर रहे हैं , तो कोई व्यक्ति केवल आपके सिस्टम में खुद को प्रशासक बना सकता है और सभी के लिए एक स्वतंत्र है। लेकिन यह केवल मूल इनपुट सत्यापन है, और इसका SQL इंजेक्शन से कोई लेना-देना नहीं है।


स्टीव लोव के उत्तर द्वारा उठाए गए मुद्दे को मुख्य बिंदु समझ रहा है, यह भी लेख @mikekidder के हवाले से बताया गया है - आपको डायनामिक SQL जहां भी है, चाहे वह एप्लिकेशन में हो या सर्वर में। डायनेमिक SQL खतरनाक है - लेकिन इसे सुरक्षित बनाया जा सकता है।
जोनाथन लेफ्लर

"एक हमलावर के पास डेटा को पारित करने का कोई तरीका नहीं है जिसे 'लाइव' एसक्यूएल की तरह माना जाएगा।" - यह बिल्कुल सच नहीं है, नीचे दिए गए उदाहरण देखें।
बूजी बॉय

नीचे दिए गए सभी उदाहरण "पैरामीटराइज्ड क्वेरी" को परिभाषित कर रहे हैं, जिसका अर्थ है कि SQL कोड स्वीकार करने वाला पैरामीटर। सामान्य परिभाषा एक क्वेरी है जो आपके DBMS पैरामीटर संग्रह का उपयोग करती है। DBMS बग को छोड़कर, यह बाद की तकनीक SQL इंजेक्शन को रोकता है।
HTTP 410

2
मैंने हर एक लिंक को पढ़ा है। कृपया किसी भी लिंक का उल्लेख करें जो DBMS पैरामीटर संग्रह के खिलाफ काम कर रहे इंजेक्शन हमले को संदर्भित करता है। वास्तव में, आपके द्वारा विशेष रूप से पोस्ट किया गया लिंक SQL इंजेक्शन को पराजित करने के रूप में इस दृष्टिकोण को संदर्भित करता है ("टाइप-सेफ SQL पैरामीटर्स का उपयोग करें" अनुभाग देखें)।
HTTP 410

नमस्ते! क्या आप Oracle SQL व्याकरण या उस उत्तर को साबित करने के लिए ऐसा कुछ भी लिंक प्रदान कर सकते हैं। मैं इसे समझता हूं और आपके साथ पूरी तरह से सहमत हूं, लेकिन प्रलेखन, व्याकरण आदि के लिए आधिकारिक लिंक रखना बहुत अच्छा होगा, बेस्टग्रैड्स, रायमबेक
रायमबेक राखीमबेक

13

नहीं, जब भी आप किसी SQL क्वेरी में अनवांटेड डेटा को इंटरपोलेट करते हैं, तब भी SQL इंजेक्शन का जोखिम रहता है।

क्वेरी पैरामीटर SQL सिंटैक्स से शाब्दिक मानों को अलग करके इस जोखिम से बचने में मदद करते हैं।

'SELECT * FROM mytable WHERE colname = ?'

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

'SELECT * FROM ' + @tablename + ' WHERE colname IN (' + @comma_list + ')'
' ORDER BY ' + @colname'

इससे कोई फर्क नहीं पड़ता कि आप संग्रहीत प्रक्रियाओं का उपयोग कर रहे हैं या एप्लिकेशन कोड से डायनेमिक SQL क्वेरी को सीधे निष्पादित कर रहे हैं। जोखिम अभी भी है।

इन मामलों में उपाय आवश्यकतानुसार FIEO को नियोजित करना है :

  • फ़िल्टर इनपुट: मान्य करें कि डेटा आपके द्वारा प्रक्षेपित करने से पहले वैध पूर्णांक, तालिका नाम, स्तंभ नाम आदि की तरह दिखता है।

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


12

"पैरामीटर क्वेरी" की परिभाषा के बारे में इस धागे में कुछ भ्रम प्रतीत होता है।

  • एसक्यूएल जैसे संग्रहित खरीद जो मापदंडों को स्वीकार करता है।
  • SQL जिसे DBMS पैरामीटर संग्रह का उपयोग करके कहा जाता है।

पूर्व परिभाषा को देखते हुए, कई लिंक काम करने के हमलों को दिखाते हैं।

लेकिन "सामान्य" परिभाषा बाद वाली है। उस परिभाषा को देखते हुए, मैं किसी भी SQL इंजेक्शन हमले के बारे में नहीं जानता जो काम करेगा। इसका मतलब यह नहीं है कि कोई नहीं है, लेकिन मुझे अभी तक इसे देखना नहीं है।

टिप्पणियों से, मैं खुद को स्पष्ट रूप से पर्याप्त रूप से व्यक्त नहीं कर रहा हूं, इसलिए यहां एक उदाहरण है जो उम्मीद है कि स्पष्ट होगा:

यह दृष्टिकोण है एसक्यूएल इंजेक्शन के लिए खुला

exec dbo.MyStoredProc 'DodgyText'

यह दृष्टिकोण SQL इंजेक्शन के लिए खुला नहीं है

using (SqlCommand cmd = new SqlCommand("dbo.MyStoredProc", testConnection))
{
    cmd.CommandType = CommandType.StoredProcedure;
    SqlParameter newParam = new SqlParameter(paramName, SqlDbType.Varchar);
    newParam.Value = "DodgyText";
    .....
    cmd.Parameters.Add(newParam);
    .....
    cmd.ExecuteNonQuery();
}

क्या आप स्पष्ट कर सकते हैं कि DBMS पैरामीटर्स कलेक्शन से आपका क्या मतलब है जो मापदंडों को स्वीकार करने वाली प्रक्रिया के विपरीत है?
रुण ग्रिमस्टैड

Rune, इस लिंक के "Use Type-Safe SQL Parameters" सेक्शन को पढ़ें
HTTP 410

अद्यतन के साथ संपादित करने से पहले मेरी प्रतिक्रिया रुण के मूल प्रश्न पर थी।
माइककेडर सुंदर

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

यह बंधन है जो फर्क करता है। यदि आप सीधे संग्रहीत मापदंडों के साथ कॉल करते हैं, तो कोई इनपुट फ़िल्टरिंग नहीं की जाती है। लेकिन यदि आप (उदाहरण के लिए) .NET में SqlCommand पैरामीटर संग्रह का उपयोग करके बाइंड करते हैं, तो सभी मापदंडों को फ़िल्टर किया जाएगा और सादे पाठ के रूप में माना जाएगा।
HTTP 410

10

डायनेमिक क्वेरी बनाने के लिए उपयोग किया जाने वाला स्ट्रिंग प्रकार (varchar, nvarchar, आदि) का कोई भी sql पैरामीटर अभी भी असुरक्षित है

अन्यथा पैरामीटर प्रकार रूपांतरण (उदाहरण के लिए, दशमलव, तिथि, आदि) पैरामीटर के माध्यम से sql को इंजेक्ट करने के किसी भी प्रयास को समाप्त करना चाहिए

संपादित करें: एक उदाहरण, जहां पैरामीटर @ p1 एक तालिका नाम है

create procedure dbo.uspBeAfraidBeVeryAfraid ( @p1 varchar(64) ) 
AS
    SET NOCOUNT ON
    declare @sql varchar(512)
    set @sql = 'select * from ' + @p1
    exec(@sql)
GO

यदि @ p1 को ड्रॉप-डाउन सूची से चुना गया है तो यह एक संभावित sql-injection attack वेक्टर है;

यदि @ p1 प्रोग्रामेटिक रूप से w / तैयार किया जाता है, तो उपयोगकर्ता की हस्तक्षेप करने की क्षमता समाप्त हो जाती है, तो यह संभावित sql-injection attack वेक्टर नहीं है


नहीं; संपूर्ण बिंदु यह है कि DBMS को दिया गया स्ट्रिंग SQL स्टेटमेंट का हिस्सा नहीं है। इसलिए, स्ट्रिंग में मान SQL की व्याख्या के लिए कोई फर्क नहीं पड़ता है - सिर्फ SQL द्वारा संदर्भित मानों के लिए।
जोनाथन लेफ्लर

यही कारण है कि मैं मापदंडों को भी देखता हूं। वे इस समस्या को रोकने वाले हैं।
रुन ग्रिमस्टैड

2
स्टीवन सही है अगर उदाहरण के लिए आप एक स्ट्रिंग को एक sp में पास कर रहे हैं जो इसे sp_executeSql (sql server) जैसी किसी चीज़ को चलाने के लिए उपयोग करता है तो आपके पास अभी भी एक sql इंजेक्शन जोखिम है।
एलेक्समैक

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

@ उत्तर: शायद 'पैरामीटर' शब्द को एक बार भी अधिभारित किया गया है। : डी
जोनाथन लेफ़लर

6

एक बफर अतिप्रवाह एसक्यूएल इंजेक्शन नहीं है।

पैरामीटर क्वेरीज़ की गारंटी देता है कि आप SQL इंजेक्शन के खिलाफ सुरक्षित हैं। वे गारंटी नहीं देते कि आपके SQL सर्वर में बग के रूप में संभावित कारनामे नहीं हैं, लेकिन कुछ भी गारंटी नहीं देगा।


2

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


इसलिए यहां सबक यह है कि यदि आपको डायनेमिक एसक्यूएल का उपयोग करना है, तो केवल एक संग्रहीत प्रक्रिया के अंदर ही ऐसा करें। +1 अच्छी सलाह!
स्टीवन ए। लोव

1
संकलित प्रोक्स में नो - डायनेमिक एसक्यूएल अभी भी डायनेमिक क्वेरी में अनवीलेटेड डेटा को इंटरपोल करके SQL इंजेक्शन की खामियों को पेश कर सकता है।
बिल करविन

यहाँ कोई सबक गतिशील SQl
HLGEM

@HLGEM - सही, और ऑटोमोबाइल यातायात दुर्घटनाओं में शामिल हैं, इसलिए हमें कभी भी ऑटोमोबाइल का उपयोग नहीं करना चाहिए।
बिल करविन

लेकिन संग्रहित खरीद में गतिशील एसक्यूएल, कॉलर की अनुमति से चलता है (डिफ़ॉल्ट रूप से), स्थिर एसक्यूएल की तरह नहीं, जो संग्रहीत खरीददार की अनुमति से चलता है। यह एक महत्वपूर्ण अंतर है।
HTTP 410

1

अतिप्रवाह / छंटनी के माध्यम से विशेष प्रकार के एसक्यूएल इंजेक्शन के प्रति संवेदनशील होने के लिए एक संग्रहीत खरीद के लिए संभव है, देखें: यहां डेटा ट्रंकेशन द्वारा सक्षम इंजेक्शन:

http://msdn.microsoft.com/en-us/library/ms161953.aspx


यदि आप लेख को विस्तार से पढ़ते हैं, तो आप देखेंगे कि SQL सर्वर के पैरामीटर संग्रह का उपयोग इस हमले को रोकता है। और यह "पैरामीटर क्वेरी" की सामान्य परिभाषा है - यह DBMS के पैरामीटर संग्रह का उपयोग करता है।
HTTP 410

1

बस याद रखें कि मापदंडों के साथ आप आसानी से स्ट्रिंग को स्टोर कर सकते हैं, या उपयोगकर्ता नाम कह सकते हैं यदि आपकी कोई नीतियां नहीं हैं, "); ड्रॉप टेबल उपयोगकर्ता; -"

यह अपने आप में कोई नुकसान नहीं पहुंचाएगा, लेकिन आप बेहतर जानते हैं कि आपके आवेदन में आगे कहां और कैसे तिथि का उपयोग किया जाता है (जैसे कि कुकी में संग्रहीत, बाद में अन्य सामान करने के लिए पुनः प्राप्त।


1

आप उदाहरण के रूप में गतिशील sql चला सकते हैं

DECLARE @SQL NVARCHAR(4000);
DECLARE @ParameterDefinition NVARCHAR(4000);

SELECT  @ParameterDefinition = '@date varchar(10)'

SET @SQL='Select CAST(@date AS DATETIME) Date'

EXEC sp_executeSQL @SQL,@ParameterDefinition,@date='04/15/2011'
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.