2010-03-08 12 views
58

Ich verwende eine API, die eine SQL-Zeichenfolge erwartet. Ich nehme eine Benutzereingabe, entziehe sie und gebe sie an die API weiter. Die Benutzereingabe ist ziemlich einfach. Es fragt nach Spaltenwerten. Wie so:So entziehen Sie einfache SQL-Abfragen in C# für SqlServer

string name = userInput.Value; 

Dann konstruiere ich eine SQL-Abfrage:

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

Ist das sicher genug? Wenn dies nicht der Fall, gibt es eine einfache Bibliotheksfunktion, die Spaltenwerte sicher zu machen:

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

Die API SQLServer als Datenbank verwendet.

+3

Sie ** ** Bedarf Parameter zu verwenden. – SLaks

+1

@SLaks, offensichtliche die API erlaubt es nicht. Vielleicht braucht er eine neue API. –

+3

@sri Sie erhalten bessere Antworten, wenn Sie erklären, warum Sie Parameter nicht verwenden können/werden. – Foole

Antwort

87

Da SqlParameter verwendet, ist keine Option, nur ersetzen 'mit ''(das ist zwei einfache Anführungszeichen, nicht ein double quote) in den Stringliteralen. Das ist es.

Um Möchtegern-Downvoter: lesen Sie die erste Zeile der Frage erneut. "Verwendungsparameter" war auch meine Bauchreaktion.

EDIT: Ja, ich weiß über SQL-Injection-Angriffe. Wenn Sie denken, dass diese Zitate für diese anfällig sind, stellen Sie bitte ein funktionierendes Gegenbeispiel zur Verfügung. Ich denke es ist nicht.

+2

-1: Und wie schützt das gegen Dinge wie Little Bobby? (http://xkcd.com/327/ wenn Sie nicht wissen, was das bedeutet). Während Parameter möglicherweise keine Option sind, ist die Lösung, einzelne durch doppelte Anführungszeichen zu ersetzen, sicherlich nicht "es", wie Ihre Antwort angibt. –

+11

Da ist ein bisschen nach Robert. So geht das. Wenn richtig zitiert, würde Bobbys unorthodoxer Name in der Datenbank in seiner Gesamtheit gespeichert werden. –

+0

Ich sprach im übertragenen Sinne. Sie hätten keine Anführungszeichen mit beispielsweise numerischen Argumenten. Es ist diese Art von Sache, die das Problem ist, nicht das genaue Beispiel. (Diese genaue Syntax würde beispielsweise nicht mit SQL Server funktionieren, aber das Problem bleibt bestehen.) –

2

Ganz einfach:

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

und fügen Sie den @name Parameter mit Wert:

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

Er braucht noch die tatsächliche SQL-Anweisung aus dem Befehl-Objekt zu erhalten, um die API zu übergeben. – manu08

-10

Wenn Sie eine Zeichenfolge für eine MSSQL-Abfrage entkommen müssen diese versuchen:

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

Sorry Kevin, aber das Escape-Funktion nur entkommt XML nicht SQL (http://msdn.microsoft.com/en-us/library/system.security.securityelement.escape.aspx) –

0

ich dynamische SQL wurde mit (ich kann das Erschießungskommando laden ihre Gewehre hören) für Suchfunktionalität, aber es würde brechen, wenn ein Nutzer hat nach jemandem mit einem Nachnamen wie "O'Reilly" gesucht.

ich es geschafft, eine Behelfslösung, um herauszufinden, (sprich: „Hack“):

eine skalarwertige Funktion in SQL erstellt, die einen Apostroph mit zwei einfachen Anführungszeichen ersetzt, effektiv das störende Apostroph zu entkommen, so
"... Name LIKE '% O'Reilly%' AND ..." wird "... '% O''Reilly%' Nachname LIKE und ..."

Diese Funktion aufgerufen wird innerhalb von sql, wenn ich vermute, Felder könnten ein einzelnes Anführungszeichen enthalten, dh: Vorname, Nachname.

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 

Nicht sehr elegant oder effizient, aber es funktioniert, wenn Sie in Not sind.

0

Anstelle von "Parametrisierung" kann man "mit" ersetzen, wenn das Problem in einer großen Menge von Ad-hoc-SQL in kurzer Zeit mit minimalem Risiko von Brüchen und minimalen Tests angegangen werden muss.

0

Es ist am besten, SQL-Parameter zu verwenden, aber Sie haben dann eine Beschränkung für 2300 Parameter für die Abfrage. In den meisten Fällen wird dies mehr als genug sein. Aber in seltenen Fällen, wenn Sie dieses Limit überschreiten, sehe ich dies als eine Option.

0

SqlCommand und Entity Framework verwenden exec sp_executesql....vermutlich

So gibt es wirklich eine Alternative zu rohen Strings mit Ihren eigenen Flucht Mustern. Mit SqlCommand verwenden Sie technisch parametrisierte Abfragen, umgehen jedoch die ADO.Net-Abstraktion des zugrunde liegenden SQL-Codes.

So, während Ihr Code nicht SQL Injection zu verhindern, ist die ultimative Antwort Sp_executesql nicht SqlCommand.

Having said that, ich bin sicher, dass ein SQL-Injection-proof Zeichenfolge spezielle Handhabungsanforderungen für die Erzeugung, die Sp_executesql nutzt es.

sehen: How to return values from a dynamic SQL Stored Procedure to the Entity Framework?

Verwandte Themen