क्या संग्रहीत कार्यविधियाँ SQL इंजेक्शन को रोकती हैं?


83

क्या यह सच है कि संग्रहीत कार्यविधियाँ PostgreSQL डेटाबेस के खिलाफ SQL इंजेक्शन के हमलों को रोकती हैं? मैंने थोड़ा शोध किया और पाया कि SQL सर्वर, Oracle और MySQL SQL इंजेक्शन के खिलाफ सुरक्षित नहीं हैं, भले ही हम केवल संग्रहीत प्रक्रियाओं का उपयोग करें। हालाँकि, यह समस्या PostgreSQL में मौजूद नहीं है।

क्या PostgreSQL कोर में संग्रहीत कार्यविधि कार्यान्वयन SQL इंजेक्शन हमलों को रोकता है या यह कुछ और है? या PostgreSQL भी SQL इंजेक्शन के लिए अतिसंवेदनशील है, भले ही हम केवल संग्रहीत प्रक्रियाओं का उपयोग करें? यदि हां, तो कृपया मुझे एक उदाहरण (उदाहरण के लिए पुस्तक, साइट, कागज, आदि) दिखाएं।


4
अजीब तरह से, यहाँ शीर्ष उत्तर ज्यादातर ओटी SQL सर्वर के साथ काम कर रहे हैं, जबकि सवाल पोस्टग्रेज के बारे में है । यहाँ Postgres के लिए एक संबंधित जवाब है: dba.stackexchange.com/questions/49699/… । दूसरों के एक जोड़े हैं, एक खोज का प्रयास करें: dba.stackexchange.com/…
Erwin Brandstetter

@ErwinBrandstetter पोस्ट के साथ मूल प्रश्न (ओपी द्वारा) टैग नहीं किया गया था और - और अभी भी - कई अन्य डीबीएमएस का उल्लेख करता है। मुझे लगता है कि rthe विभिन्न DBMS पर ध्यान केंद्रित विभिन्न उत्तरों का कारण है। मेरा सुझाव है कि आप पोस्टग्रेज पर एक और ध्यान केंद्रित करें।
ypercube y

@ ypercube y: समय मिलने पर मैं यहां एक उत्तर दूंगा। इस बीच मैंने dba.stackexchange.com/questions/49699/… को अधिक स्पष्ट और व्यापक रूप से अपडेट किया ।
एरविन ब्रैंडस्टैटर

जवाबों:


71

नहीं, संग्रहीत कार्यविधियाँ SQL इंजेक्शन को रोकती नहीं हैं। यहां एक वास्तविक उदाहरण (एक इन-हाउस ऐप से कोई व्यक्ति जहां मैं काम करता हूं) एक संग्रहीत कार्यविधि है जो दुर्भाग्य से SQL इंजेक्शन की अनुमति देता है:

यह sql सर्वर कोड:

CREATE PROCEDURE [dbo].[sp_colunmName2]   
    @columnName as nvarchar(30),
    @type as nvarchar(30), 
    @searchText as nvarchar(30)           
AS
BEGIN
    DECLARE @SQLStatement NVARCHAR(4000)
    BEGIN
        SELECT @SQLStatement = 'select * from Stations where ' 
            + @columnName + ' ' + @type + ' ' + '''' + @searchText + '''' 
        EXEC(@SQLStatement)
    END      
END
GO

मोटे तौर पर पोस्टग्रेज के बराबर:

CREATE or replace FUNCTION public.sp_colunmName2 (
    columnName  varchar(30),
    type varchar(30), 
    searchText  varchar(30) ) RETURNS SETOF stations LANGUAGE plpgsql            
AS
$$
DECLARE SQLStatement VARCHAR(4000);
BEGIN
    SQLStatement = 'select * from Stations where ' 
            || columnName || ' ' || type || ' ' || ''''|| searchText || '''';
    RETURN QUERY EXECUTE  SQLStatement;
END
$$;

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

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


46

एसक्यूएल-इंजेक्शन हमले वे हैं जहां अविश्वासित इनपुट को सीधे तौर पर जोड़ा जाता है, जिससे उपयोगकर्ता को प्रभावी रूप से मनमाने ढंग से कोड निष्पादित करने की अनुमति मिलती है, जैसा कि इस कैनोनिकल एक्सकेसीडी कॉमिक में सचित्र है

इस प्रकार, हमें स्थिति मिलती है:

userInput = getFromHTML # "रॉबर्ट ') ड्रॉप टेबल छात्र; -"

प्रश्न = "छात्रों से जहां छात्रनाम =" + userInput का चयन करें

संग्रहीत कार्यविधियाँ, सामान्य रूप से, SQL इंजेक्शन हमलों के खिलाफ अच्छे बचाव हैं क्योंकि आने वाले पैरामीटर कभी भी पार्स नहीं होते हैं।

एक संग्रहीत कार्यविधि में, अधिकांश DBs (और प्रोग्राम्स में, यह मत भूलो कि प्रीक्लेम्ड क्वेरीज़ को संग्रहीत प्रक्रियाओं के रूप में गिना जाता है) निम्नलिखित की तरह दिखते हैं:

 

संग्रहित उपसंहार फू
उन छात्रों में से चुनें, जहाँ छात्रनाम =: 1 है
);

फिर, जब कार्यक्रम की इच्छा होती है, तो यह कॉल करता है foo(userInput)और खुशी से परिणाम प्राप्त करता है।

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

आप SQL- इंजेक्शन के बारे में अधिक पढ़ सकते हैं:


29

हां, कुछ हद तक।
अकेले संग्रहीत कार्यविधियाँ SQL इंजेक्शन को नहीं रोकेंगी।

मुझे पहले OWASP से SQL इंजेक्शन के बारे में उद्धरण दें

SQL इंजेक्शन हमले में क्लाइंट से एप्लिकेशन में इनपुट डेटा के माध्यम से SQL क्वेरी के सम्मिलन या "इंजेक्शन" होते हैं। एक सफल SQL इंजेक्शन शोषण डेटाबेस से संवेदनशील डेटा को पढ़ सकता है, डेटाबेस डेटा (इन्सर्ट / अपडेट / डिलीट) को संशोधित कर सकता है, डेटाबेस पर प्रशासन संचालन को निष्पादित कर सकता है (जैसे कि DBMS को शटडाउन करें), DBMS फाइल पर मौजूद किसी दिए गए फ़ाइल की सामग्री को पुनर्प्राप्त करें। सिस्टम और कुछ मामलों में ऑपरेटिंग सिस्टम को कमांड जारी करता है। SQL इंजेक्शन हमले एक प्रकार का इंजेक्शन हमला है, जिसमें पूर्वनिर्धारित SQL कमांड के निष्पादन को प्रभावित करने के लिए SQL कमांड को डेटा-प्लेन इनपुट में इंजेक्ट किया जाता है।

आपको उपयोगकर्ता इनपुट को सैनिटाइज़ करना होगा और SQL स्टेटमेंट्स को कंसीनेट नहीं करना होगा, भले ही आप स्टोर की गई प्रक्रिया का उपयोग कर रहे हों।

जेफ Attwood समझाया "में एसक्यूएल श्रृंखलाबद्ध के परिणामों मुझे पैरामिट्रीकृत एसक्यूएल दो, या मुझे मौत दे "

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

SQL इंजेक्शन रोकथाम धोखा शीट पर एक नजर है , रोकथाम के तरीकों को बड़े करीने से समझाया गया है ...


12

स्ट्रिंग कॉन्सेप्टेशन SQL इंजेक्शन का कारण है। पैरामीट्रिशन का उपयोग करने से बचा जाता है।

संग्रहीत कार्यविधियाँ, जब आप सहमति देते हैं, तो अवैध सिंटैक्स लागू करके सुरक्षा की एक अतिरिक्त परत जोड़ते हैं, लेकिन यदि आप उनका उपयोग करते हैं, तो कहते हैं कि "सुरक्षित" नहीं हैं।

तो, अपने कोड से ऊपर के कारण होता है संयोजन इन तारों के

  • exec sp_GetUser '
  • x' AND 1=(SELECT COUNT(*) FROM Client); --
  • ' , '
  • monkey
  • '

यह अवैध रूप से वाक्यविन्यास देता है, सौभाग्य से

यह पैरामीटर देना होगा

exec sp_GetUser 'x'' AND 1=(SELECT COUNT(*) FROM Client); --' , 'monkey'

इसका मतलब है की

  • @UserName = x' AND 1=(SELECT COUNT(*) FROM Client); --
  • @Password = monkey

अब, ऊपर दिए गए कोड में आपको कोई पंक्तियाँ नहीं मिलेंगी क्योंकि मुझे लगता है कि आपके पास कोई उपयोगकर्ता नहीं है x' AND 1=(SELECT COUNT(*) FROM Client); --

यदि संग्रहित खरीद इस तरह दिखाई देती है (कॉन्कैटेड डायनेमिक SQL का उपयोग करके ), तो आपकी पैरामीटरी स्टोर की गई कॉल फिर भी SQL इंजेक्शन की अनुमति देगी

...
SET @sql = 'SELECT userName from users where userName = ''' + 
               @UserName + 
               ''' and userPass = ''' +
               @Password +
               ''''
EXEC (@sql)
....

इसलिए, जैसा कि दिखाया गया है, एसक्यूएल इंजेक्शन के लिए स्ट्रिंग शत्रुता मुख्य दुश्मन है

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

आप के बारे में अधिक के लिए स्टैक ओवरफ़्लो पर देख सकते हैं parametrisation


10

"SQL इंजेक्शन हमले से जाने के बाद क्या उपयोगकर्ता इनपुट को अनुचित तरीके से एन्कोड किया गया है। कुछ डेटा उपयोगकर्ता उसकी क्वेरी के साथ भेजता है, में यानी मूल्यों आमतौर पर, उपयोगकर्ता इनपुट है $_GET, $_POST, $_COOKIE, $_REQUEST, या $_SERVERसरणियों। हालांकि, उपयोगकर्ता इनपुट भी अन्य की एक किस्म से आ सकता है स्रोत, जैसे सॉकेट, दूरस्थ वेबसाइट, फाइलें, आदि। इसलिए, आपको वास्तव में उपयोगकर्ता इनपुट के रूप में सब कुछ लेकिन स्थिरांक (जैसे 'foobar') का इलाज करना चाहिए । "

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



YouTube से


विकिपीडिया से


OWASP से


PHP मैनुअल से


Microsoft और Oracle से


स्टैक ओवरफ़्लो


एसक्यूएल इंजेक्शन स्कैनर


2

संग्रहीत प्रक्रियाएँ जादुई रूप से SQL इंजेक्शन को रोकती नहीं हैं, लेकिन वे इसे रोकना बहुत आसान है। आपको बस इतना करना है कि निम्नलिखित कुछ है (उदाहरण उदाहरण के लिए):

CREATE OR REPLACE FUNCTION my_func (
  IN in_user_id INT 
)
[snip]
  SELECT user_id, name, address FROM my_table WHERE user_id = in_user_id; --BAM! SQL INJECTION IMMUNE!!
[snip]

बस! समस्या केवल तब होती है जब स्ट्रिंग संघनन (यानी गतिशील एसक्यूएल) के माध्यम से एक क्वेरी बनाते हैं, और यहां तक ​​कि उन मामलों में भी आप बांधने में सक्षम हो सकते हैं! (डेटाबेस पर निर्भर करता है।)

अपनी गतिशील क्वेरी में SQL इंजेक्शन से कैसे बचें:

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

चरण 2) अपने विशेष RDBMS के लिए चर सेट करने के लिए उचित तरीके पर शोध करें। उदाहरण के लिए Oracle आपको निम्नलिखित करने देता है (उनके डॉक्स से उद्धृत):

sql_stmt := 'UPDATE employees SET salary = salary + :1 WHERE ' 
           || v_column || ' = :2';
EXECUTE IMMEDIATE sql_stmt USING amount, column_value; --INJECTION IMMUNE!!

यहां आप अभी भी इनपुट नहीं कर रहे हैं। आप सुरक्षित रूप से बाध्यकारी हैं! हुर्रे!

यदि आपका डेटाबेस ऊपर की तरह कुछ का समर्थन नहीं करता है (उम्मीद है कि उनमें से कोई भी अभी भी यह खराब नहीं है, लेकिन मुझे आश्चर्य नहीं होगा) - या यदि आपको अभी भी अपने इनपुट को संक्षिप्त करना होगा (जैसे कि कभी-कभी रिपोर्टिंग प्रश्नों के "केस" के रूप में मैंने ऊपर संकेत दिया), तो आपको एक उचित भागने के कार्य का उपयोग करना चाहिए। इसे स्वयं न लिखें। उदाहरण के लिए postgres उद्धरण_literal () फ़ंक्शन प्रदान करता है। तो आप दौड़ेंगे:

sql_stmt := 'SELECT salary FROM employees WHERE name = ' || quote_literal(in_name);

इस तरह अगर in_name '[स्निप] या 1 = 1' ("या" 1 = 1 "भाग की तरह कुछ कुटिल है, तो सभी पंक्तियों का चयन करें, जिससे उपयोगकर्ता को वह वेतन नहीं देखना चाहिए!), तो बोली_लिटरल आपके बट को बचाता है! परिणामी स्ट्रिंग बनाना:

SELECT salary FROM employees WHERE name = '[snip] or 1=1'

कोई परिणाम नहीं मिलेगा (जब तक कि आपके पास वास्तव में अजीब नामों वाले कुछ कर्मचारी न हों।)

यही इसका सार है! अब मैं आपको केवल घर पर ड्राइव करने के लिए SQL इंजेक्शन के विषय पर Oracle गुरु टॉम कय्टे द्वारा एक क्लासिक पोस्ट के लिंक के साथ छोड़ देता हूं: Linky


उल्लेख करना न भूलें quote_ident()- लेकिन सामान्य तौर पर इंजेक्शन-प्रूफ डायनामिक एसक्यूएल लिखने का सबसे आसान तरीका पहचानकर्ताओं के लिए और शाब्दिक के लिए format()प्लेसहोल्डर्स का उपयोग और उपयोग करना है। इस तरह एसक्यूएल का उपयोग करने और कार्यों के बराबर संस्करण की तुलना में बहुत अधिक पठनीय है%I%L||quote_....()
a_horse_with_no_name
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.