2010-03-08 15 views
58

के लिए सी # में सरल एसक्यूएल प्रश्नों से कैसे बचें मैं एक एसपीआई स्ट्रिंग की अपेक्षा करता हूं जो एक एपीआई का उपयोग करता है। मैं उपयोगकर्ता इनपुट लेता हूं, इसे से बचता हूं और एपीआई के साथ पास करता हूं। उपयोगकर्ता इनपुट काफी सरल है। यह कॉलम मानों के लिए पूछता है। इसलिए जैसा:एसक्यूएल सर्वर

string name = userInput.Value; 

तो मैं एक एसक्यूएल क्वेरी बना:

string sql = string.Format("SELECT * FROM SOME_TABLE WHERE Name = '{0}'", 
          name.replace("'", "''")); 

यह पर्याप्त सुरक्षित है? यदि ऐसा नहीं है, वहाँ है कि स्तंभ मान सुरक्षित बनाने के लिए एक सरल पुस्तकालय समारोह है:

string sql = string.Format("SELECT * FROM SOME_TABLE WHERE Name = '{0}'", 
          SqlSafeColumnValue(name)); 

एपीआई डेटाबेस के रूप में SQLServer उपयोग करता है।

+3

आप ** जरूरत ** पैरामीटर का उपयोग करने के लिए। – SLaks

+1

@SLaks, स्पष्ट है कि एपीआई इसे अनुमति नहीं देता है। शायद उसे एक नई एपीआई चाहिए। –

+3

@ एसआरआई आपको बेहतर जवाब मिलेगा यदि आप समझते हैं कि आप पैरामीटर का उपयोग क्यों नहीं कर सकते/नहीं करेंगे। – Foole

उत्तर

87

SqlParameter का उपयोग कर के बाद से एक विकल्प 'नहीं है, सिर्फ' 'से बदलने (है कि दो एकल कोट, नहीं एक है डबल कोट) स्ट्रिंग अक्षर में। बस।

डाउनवॉटर होने के लिए: प्रश्न की पहली पंक्ति को दोबारा पढ़ें। "मापदंडों का प्रयोग करें" मेरी आंत प्रतिक्रिया भी थी।

संपादित करें: हाँ, मुझे एसक्यूएल इंजेक्शन हमलों के बारे में पता है। यदि आपको लगता है कि यह उद्धरण उन लोगों के लिए कमजोर है, तो कृपया एक काम करने वाले counterexample प्रदान करें। मुझे लगता है कि यह नहीं है।

+2

-1: और यह लिटिल बॉबी जैसी चीजों के खिलाफ कैसे सुरक्षा करता है? (http://xkcd.com/327/ अगर आपको नहीं पता कि इसका क्या अर्थ है)। जबकि पैरामीटर एक विकल्प नहीं हो सकता है, डबल सिंगल कोट्स के साथ सिंगल को बदलने का समाधान निश्चित रूप से आपके उत्तर राज्यों के रूप में 'यह' नहीं है। –

+11

रॉबर्ट के बाद थोड़ा सा है। कि कैसे। उचित रूप से उद्धृत होने पर, बॉबी का अपरंपरागत नाम डेटाबेस में पूरी तरह से संग्रहीत होगा। –

+0

मैं मूर्तिकला बोल रहा था। आपके पास उद्धरण नहीं होंगे, उदाहरण के लिए, संख्यात्मक तर्क। यह इस तरह की * दयालु * समस्या है, यह सही उदाहरण नहीं है। (उदाहरण के लिए, वह सटीक वाक्यविन्यास SQL ​​सर्वर के साथ काम नहीं करेगा, लेकिन समस्या अभी भी लागू होती है।) –

2

सरल:

const string sql = "SELECT * FROM SOME_TABLE WHERE Name = @name"; 

और मूल्य के साथ @name पैरामीटर जोड़ें:

cmd.CommandText = sql; 
cmd.Parameters.AddWithValue("@name", name); 
+30

उसे अभी भी एपीआई को पास करने के लिए कमांड ऑब्जेक्ट से वास्तविक SQL कथन प्राप्त करने की आवश्यकता है। – manu08

-10

आप एक MSSQL क्वेरी के लिए एक स्ट्रिंग से बचने के लिए की जरूरत है इस प्रयास करें:

System.Security.SecurityElement.Escape(Value) 
+8

क्षमा करें केविन लेकिन यह एस्केप फ़ंक्शन केवल एक्सएमएल से नहीं बचता है (http://msdn.microsoft.com/en-us/library/system.security.securityelement.escape.aspx) –

0

मैं गतिशील एसक्यूएल उपयोग कर रहा था खोज की कार्यक्षमता के लिए (मैं निशानेबाज दस्ते उनकी राइफल लोड हो रहा है सुन सकते हैं), लेकिन यह जब भी टूट जाएगा एक उपयोगकर्ता ने "O'Reilly" जैसे उपनाम के साथ किसी के लिए खोज की।

मैं एक काम के आसपास यह पता लगाने की (पढ़ें "हैक") में कामयाब रहे:

एसक्यूएल में एक अदिश-मान समारोह है कि दो एकल उद्धरण के साथ एक एकल बोली की जगह, प्रभावी रूप से अपमानजनक एकल उद्धरण से बचने बनाया गया तो,
"... उपनाम की तरह '% ओ रेली%' और ..." हो जाता है "... उपनाम की तरह '% O''Reilly%' और ..."

इस समारोह लागू हो जाता है एसक्यूएल के भीतर से जब भी मुझे संदेह होता है कि फ़ील्ड में एक एकल उद्धरण चरित्र हो सकता है यानी: पहला नाम, अंतिम नाम।

CREATE FUNCTION [dbo].[fnEscapeSingleQuote] 
    (@StringToCheck NVARCHAR(MAX)) 
RETURNS NVARCHAR(MAX) 
AS 
BEGIN 
    DECLARE @Result NVARCHAR(MAX) 
    SELECT @Result = REPLACE(@StringToCheck, CHAR(39), CHAR(39) + CHAR(39)) 
    RETURN @Result 
END 

बहुत ही सुरुचिपूर्ण या कुशल नहीं है, लेकिन जब आप चुटकी में होते हैं तो यह काम करता है।

0

ब्रेकेज और न्यूनतम परीक्षण के न्यूनतम जोखिम के साथ थोड़ी देर में 'एसक्यूएल' की बड़ी मात्रा में समस्या को हल करने की आवश्यकता होने पर पैरामीटर को बदलने के बजाय 'साथ' को प्रतिस्थापित करना चाह सकता है।

0

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

0

एसक्यूएल कॉमांड और इकाई फ्रेमवर्क exec sp_executesql... का उपयोग करें।

तो वास्तव में आपके अपने बचने वाले पैटर्न के साथ कच्चे तारों का एक विकल्प वास्तव में है। SqlCommand के साथ आप तकनीकी रूप से पैरामीटर किए गए प्रश्नों का उपयोग कर रहे हैं लेकिन आप अंतर्निहित SQL कोड के ADO.Net abstraction को छोड़ रहे हैं।

तो जब आपका कोड SQL इंजेक्शन को रोकता नहीं है, तो अंतिम उत्तर sp_executesql नहीं है SqlCommand।

ऐसा कहकर, मुझे यकीन है कि एसक्यूएल इंजेक्शन-सबूत स्ट्रिंग उत्पन्न करने के लिए विशेष हैंडलिंग आवश्यकताएं हैं जो sp_executesql का उपयोग करती हैं।

देखें: How to return values from a dynamic SQL Stored Procedure to the Entity Framework?

संबंधित मुद्दे