9

को रोकें हमारे पास SQL ​​सर्वर संग्रहीत प्रक्रियाओं का एक टन है जो गतिशील एसक्यूएल पर भरोसा करता है।एसक्यूएल सर्वर में गतिशील एसक्यूएल को कैसे साफ करें - एसक्यूएल इंजेक्शन

संग्रहीत प्रक्रिया के पैरामीटर गतिशील SQL कथन में उपयोग किए जाते हैं।

हमें इन पैरामीटर को सत्यापित करने और एसक्यूएल इंजेक्शन को रोकने के लिए इन संग्रहीत प्रक्रियाओं के अंदर मानक सत्यापन फ़ंक्शन की आवश्यकता है।

मान लें हम इन बाधाओं है:

  1. हम प्रक्रियाओं को फिर से लिखने नहीं कर सकते गतिशील एसक्यूएल

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

  3. हम संग्रहीत प्रक्रिया को पारित करने से पहले पैरामीटर को सत्यापित करने के लिए संग्रहीत प्रक्रिया को कॉल करने वाले एप्लिकेशन को संशोधित नहीं कर सकते हैं।

वहाँ वर्णों का एक सेट हम को फ़िल्टर सुनिश्चित करने के लिए हम एसक्यूएल इंजेक्शन की संभावना नहीं हैं सकता है?

+0

ouch। आमतौर पर यह 3 है) जिसे एसक्यूएल इंजेक्शन को रोकने के लिए संशोधित किया जाना चाहिए। याद रखें, यह "एसक्यूएल इंजेक्शन" है, न कि "एसक्यूएल अस्वीकृति"। एक बार यह डीबी तक पहुंच जाता है, इसे पहले से ही साफ किया जाना चाहिए। लेकिन अगर आप कहते हैं कि आप ऐप नहीं बदल सकते हैं, तो मुझे लगता है कि आप नहीं कर सकते। जवाब देखने में रुचि रखते हैं। – RPM1984

उत्तर

10

मेरा मानना ​​है कि तीन अलग-अलग मामलों आप के बारे में चिंता है कि देखते हैं:

  • तार (कुछ भी है कि उद्धरण की आवश्यकता है): '''' + replace(@string, '''', '''''') + ''''
  • नाम (कुछ भी जहां उद्धरण की अनुमति नहीं है): quotename(@string)
  • चीजें हैं जो उद्धृत नहीं किया जा सकता: इस श्वेत-सूची की आवश्यकता है

नोट: एक स्ट्रिंग चर (char, varchar, nchar, nvarchar, आदि) में सब कुछ कि उपयोगकर्ता के नियंत्रित स्रोतों से आता है ऊपर एक विधि का उपयोग करना होगा। इसका मतलब यह है कि यदि आप स्ट्रिंग वेरिएबल्स में संग्रहीत हैं तो भी जिन चीजों की आप उम्मीद करते हैं उन्हें उद्धृत किया जाता है।:

अधिक जानकारी के लिए Microsoft Magazine (2016/10/19 अप्रचलित लिंक) देखें।

EXEC 'SELECT * FROM Employee WHERE Salary > ''' + 
    REPLACE(@salary, '''', '''''') + -- replacing quotes even for numeric data 
    ''' ORDER BY ' + QUOTENAME(@sort_col) + ' ' + -- quoting a name 
    CASE @sort_dir WHEN 'DESC' THEN 'DESC' END  -- whitelisting 

भी ध्यान रखें कि वहाँ काट-छांट की समस्याओं के साथ कोई चिंता का विषय है EXEC बयान में इनलाइन सभी स्ट्रिंग आपरेशन करके:

यहाँ एक उदाहरण सभी तीन तरीकों का उपयोग कर रहा है। यदि आप चर के लिए इंटरमीडिएट परिणाम असाइन करते हैं, तो आप सुनिश्चित कर सकते हैं कि वेरिएबल्स परिणाम रखने के लिए पर्याप्त हैं। यदि आप SET @result = QUOTENAME(@name) करते हैं तो आपको कम से कम 258 (2 * 128 + 2) वर्ण रखने के लिए @result परिभाषित करना चाहिए। यदि आप SET @result = REPLACE(@str, '''', '''''') करते हैं तो आपको @result को @str के आकार से दोगुना करना चाहिए (मान लें कि प्रत्येक वर्ण @str में उद्धरण हो सकता है)। और निश्चित रूप से, अंतिम SQL कथन धारण करने वाला स्ट्रिंग वेरिएबल सभी स्थिर SQL और सभी परिणाम चर को पकड़ने के लिए पर्याप्त होना चाहिए।

+0

मैं यहां सहमत हूं, यह पूरी तरह से निर्भर करता है कि एसक्यूएल का निर्माण किस प्रकार किया जा रहा है –

2

ओडब्ल्यूएएसपी इस रणनीति पर कुछ जानकारी है। यह हमेशा एक आखिरी विकल्प होना चाहिए (जैसा कि लेख मैं को जोड़ने कर रहा हूँ में समझाया गया है) लेकिन अगर यह आपके ही एकमात्र विकल्प है ...

http://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet

यह एक last- होने के बारे में लेख से एक उद्धरण खाई विकल्प

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

संक्षेप में, इस दृष्टिकोण के खिलाफ तर्क भले ही आप सभी ज्ञात गलत इनपुट भागने करते हैं, तो कोई गारंटी नहीं है कि किसी को एक तरह से भविष्य inthe यह नाकाम करने के लिए साथ नहीं आएगा है।

हालांकि, आपके सवाल का विशेष रूप से बचने के लिए लेख मैं ऊपर से जुड़ा हुआ है वर्णों की एक सूची जवाब देने के लिए ...

संपादित करें जैसा कि उल्लेख किया गया है, लेख बहुत अच्छे लिंक प्रदान नहीं करता है। हालांकि, SQL सर्वर के लिए, यह एक करता है: http://msdn.microsoft.com/en-us/library/ms161953.aspx

ध्यान दें कि पात्रों की सूची आप डीबी मंच आधार पर भिन्न होगी बचने के लिए की जरूरत है, लेकिन आप एसक्यूएल सर्वर का उपयोग कर रहे है, तो यह प्रासंगिक होना चाहिए जैसे कि यह लग रहा है। ।

छनन इनपुट भी बच पात्रों को हटाने के द्वारा एसक्यूएल इंजेक्शन के खिलाफ की रक्षा करने में सहायक हो सकता है: नीचे दिए गए लेख से

उद्धरण।हालांकि, बड़ी संख्या में वर्णों की वजह से समस्याएं पैदा हो सकती हैं, यह एक विश्वसनीय रक्षा नहीं है। निम्नलिखित उदाहरण वर्ण स्ट्रिंग डिलीमीटर के लिए खोज करता है।

private string SafeSqlLiteral(string inputSQL) 
{ 
    return inputSQL.Replace("'", "''"); 
} 

क्लाज की तरह

ध्यान दें कि यदि आप एक तरह खंड का उपयोग कर रहे, वाइल्डकार्ड वर्णों अभी भी फरार हो जाना चाहिए:

s = s.Replace("[", "[[]"); 
s = s.Replace("%", "[%]"); 
s = s.Replace("_", "[_]"); 
+1

-1: आलेख यह नहीं कहता कि एमएस एसक्यूएल सर्वर के लिए कौन से पात्र भागने हैं। यह सिर्फ एक और लेख से जुड़ा हुआ है जो यह स्पष्ट नहीं करता कि कौन से पात्र भागने के लिए हैं। – Gabe

+0

आप सही हैं। मेरा जवाब संपादित करना – David

3

यह एक बहुत बुरा समस्या अपने नहीं एक समस्या है, आप हल करना चाहते हैं, हालांकि यहां एक मामूली मामला है जो काम करता है, (समीक्षाकर्ता, अगर मुझे कोई मामला याद आया तो कृपया मुझे बताएं, यह NO गारंटी के साथ आता है)

create proc Bad 
    @param nvarchar(500) 
as 

exec (N'select ''' + @param + N'''') 

go 

-- oops injected 
exec Bad 'help'' select ''0wned!'' select ''' 

go 

create proc NotAsBad 
    @param nvarchar(500) 
as 

declare @safish nvarchar(1000), @sql nvarchar(2000) 
set @safish = replace(@param, '''', '''''') 

set @sql = N'select ''' + @safish + N'''' 

exec (@sql) 

go 

-- this kind of works, but I have not tested everything 
exec NotAsBad 'help'' select ''0wned!'' select ''' 
+0

+1, मैंने यह सुझाव देने के लिए कुछ भी नहीं देखा है कि यह काम नहीं करता है। – Gabe

+1

मेरी राय में, sp_executesql के अलावा किसी भी गतिशील एसक्यूएल को चलाने के सभी पैरामीटर के साथ पैरामीटर के रूप में पारित किया गया है, केवल शुद्ध कदाचार है। –

+0

अभी भी कमजोर है। मान लीजिए कि NotAsBad के शरीर में निम्न शामिल हैं: '@ @ql =' से सुरक्षित करें * + @ safish .... अगर उपयोगकर्ता किसी तालिका का नाम अनुमान लगा सकता है तो वे @param = 'tablename सबमिट कर सकते हैं; डेटाबेस xyz ड्रॉप; - ' – frankadelic

6

तुच्छ मामलों QUOTENAME द्वारा निर्धारित किया जा सकता है और बदल देते हैं:

set @sql = N'SELECT ' + QUOTENAME(@column) + 
    N' FROM Table WHERE Name = ' + REPLACE(@name, '''', ''''''); 

QUOTENAME एकल उद्धरण जोड़ सकते हैं और डबल एकल उद्धरण के साथ एकल उद्धरण को बदलने के लिए भी शाब्दिक पर इस्तेमाल किया जा सकता है, क्योंकि यह करने के लिए इनपुट ट्रंकेटस 128 वर्णों की अनुशंसा नहीं की जाती है।

लेकिन यह सिर्फ हिमशैल की नोक है।मल्टीपार्ट नाम हैं (dbo.table) आपको उचित देखभाल करने की आवश्यकता है: मल्टीपार्टनाम को उद्धृत करने के परिणामस्वरूप अमान्य पहचानकर्ता [dbo.table] होगा, इसे पार्स और विभाजित किया जाना चाहिए (PARSENAME का उपयोग करके), फिर उचित रूप से [dbo].[table] में उद्धृत किया जाना चाहिए।

एक और समस्या छंटनी हमले है, जो तब भी हो सकती है जब आप शाब्दिक पर छोटी प्रतिस्थापन करते हैं, New SQL Truncation Attacks And How To Avoid Them देखें।

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

+0

मैं * PARSENAME' का उपयोग करके * नहीं * की सिफारिश करता हूं क्योंकि इसका उद्देश्य पहले से उद्धृत नामों पर उपयोग करना है। यदि आपका उपयोगकर्ता आपको बताता है कि वह 'गुप्त..टेबल' से डेटा प्राप्त करना चाहता है, तो आप '[secret..table]' के खिलाफ पूछना चाहते हैं और एक त्रुटि प्राप्त करना चाहते हैं। आप नहीं चाहते कि वह '[गुप्त] .. [टेबल]' पूछने में सक्षम हो! – Gabe

+0

मेरी राय में, sp_executesql के अलावा किसी भी गतिशील एसक्यूएल को चलाने के सभी पैरामीटर के साथ पैरामीटर के रूप में पारित किया गया है, केवल शुद्ध कदाचार है। –

0

क्या आप एसक्यूएल सीएलआर का बहुत उपयोग कर सकते हैं - आप कम से कम टी-एसक्यूएल का उपयोग करके अधिक से अधिक प्रभावी स्वच्छता लिखने के लिए इसका उपयोग कर सकते हैं। एक perfact दुनिया में, आप संग्रहीत procs पूरी तरह से पैरामीटरयुक्त बयान और अन्य मजबूत संरचनाओं के साथ प्रतिस्थापित कर सकते हैं।

+0

दुर्भाग्य से, मैं डीबीए प्रतिबंधों के कारण सीएलआर का उपयोग नहीं कर सकता – frankadelic

4

इन बाधाओं के साथ आप बहुत खराब हैं।

  1. उपयोग सफेद सूची सत्यापनकर्ता/पार्सर कि केवल प्रश्नों है कि एक प्रारूप में और कीवर्ड्स और तालिकाओं कि उम्मीद कर रहे हैं के साथ कर रहे हैं स्वीकार करते हैं:

    यहाँ एक दो विकल्प है कि आप कुछ दिशा दे सकते हैं। यह शायद केवल एक बहुत अच्छा एसक्यूएल पार्सर के साथ काम करेगा जो वास्तव में वाक्यविन्यास को समझता है।

  2. प्रतिबंधित वातावरण में क्वेरी निष्पादित करें। उदाहरण के लिए, बहुत सीमित अधिकार वाले उपयोगकर्ता खाते का उपयोग करें। उदाहरण के लिए, केवल कुछ दृश्यों तक पहुंच (पढ़ने) की अनुमति दें जो संवेदनशील डेटा कभी नहीं लौटेगी और सभी अन्य दृश्यों, सभी संग्रहीत प्रक्रियाओं, कार्यों और तालिकाओं तक पहुंच को अस्वीकार नहीं करेगी। उन प्रश्नों को किसी अन्य डेटाबेस सर्वर पर निष्पादित करना भी सुरक्षित है। OPENROWSET कमांड को अक्षम करना भी न भूलें।

कृपया ध्यान दें निम्नलिखित:

  1. जब आप उन अवैध कीवर्ड नहीं है सिवाय इसके कि सभी प्रश्नों स्वीकार करते हैं, आप निश्चित रूप से, असफल हो जायेगी क्योंकि काला सूची हमेशा विफल रहता है। खासकर एसक्यूएल के रूप में ऐसी जटिल भाषा के साथ।

  2. मत भूलना स्रोत हैं जो आपको नहीं कर सकते विश्वास अपने शुद्ध अर्थों में बुराई है, भले ही आप इन युक्तियों का उपयोग से गतिशील एसक्यूएल की इजाजत दी है, क्योंकि एक समय bugs खोज कर रहे हैं कि विशेष रूप से तैयार की गई एसक्यूएल भेजकर साथ दुर्व्यवहार किया जा सकता है में एक बार एक सर्वर के लिए। इसलिए, भले ही आप इन युक्तियों को लागू करते हैं, फिर भी जोखिम अभी भी है।

  3. जब आप ऐसे समाधान के साथ जाने का निर्णय लेते हैं जो गतिशील एसक्यूएल की अनुमति देता है। कृपया यह न सोचें कि आप अपने आप को एक सुरक्षित समाधान के साथ आ सकते हैं, खासकर यदि आप संवेदनशील व्यावसायिक डेटा की रक्षा करने की कोशिश कर रहे हैं। इसके साथ आपकी सहायता के लिए डेटाबेस सर्वर सुरक्षा विशेषज्ञ को किराए पर लें।

-1

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

create procedure dbo.MYSP(@p1 varchar(100)) 
as begin 
    set @p1 = Replace(@p1, '''',' '); -- Convert single quotes to spaces 
    set @p1 = Replace(@p1, ';', ' '); 
    set @p1 = Replace(@p1, '--', ' ');  
    set @p1 = Replace(@p1, '/*', ' ');  
    set @p1 = Replace(@p1, '*/', ' ');  
    set @p1 = Replace(@p1, 'xp_', ' ');  
    ... 
end; 

आप रिक्त स्थान के साथ या कोई रिक्त स्ट्रिंग के साथ किसी भी एकल उद्धरण की जगह ले सकता: उदाहरण के लिए आप इस सपा है। इस दृष्टिकोण का उपयोग अधिक प्रतिस्थापन आदेशों का उपयोग करके/* */- जैसे टिप्पणी वर्णों को प्रतिस्थापित करने के लिए भी किया जा सकता है (जैसा कि मैंने अभी ऊपर दिखाया है)। लेकिन ध्यान दें कि यह दृष्टिकोण केवल तभी काम करेगा यदि आप इन अक्षरों को सामान्य इनपुट में कभी उम्मीद नहीं करते हैं, और यह आपके आवेदन पर निर्भर करता है।

नोट की जगह पात्रों में से सेट https://msdn.microsoft.com/en-us/library/ms161953(SQL.105).aspx

+0

एसक्यूएल इंजेक्शन को "सिंगल कोट इंजेक्शन" नहीं कहा जाता है। किसी कारण से। –

+0

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

+0

फिर सुरक्षा मूल बातें से परिचित हो जाएं और जानें कि क्यों कोई ब्लैकलिस्ट-आधारित दृष्टिकोण जानबूझकर त्रुटिपूर्ण है –

2

पर आधारित है वहाँ पात्रों हम को फ़िल्टर सुनिश्चित करने के लिए हम एसक्यूएल इंजेक्शन की संभावना नहीं हैं कर सकते हैं का एक सेट है?

नहीं

एसक्यूएल इंजेक्शन एक "वर्ण इंजेक्शन के कुछ सेट" नहीं कहा जाता है, और एक कारण के लिए। कुछ चरित्र को फ़िल्टर करना विशेष शोषण को जटिल कर सकता है, लेकिन एसक्यूएल इंजेक्शन को स्वयं नहीं रोकता है। एसक्यूएल इंजेक्शन का फायदा उठाने के लिए किसी को एसक्यूएल लिखना होगा। और एसक्यूएल कुछ विशेष पात्रों तक ही सीमित नहीं है।