Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Wie kann man dynamisches SQL in SQL Server bereinigen (SQL-Injection verhindern)?

Ich glaube, es gibt drei verschiedene Fälle, um die Sie sich Sorgen machen müssen:

  • Strings (alles, was Anführungszeichen erfordert):'''' + replace(@string, '''', '''''') + ''''
  • Namen (alles, wo Anführungszeichen nicht erlaubt sind):quotename(@string)
  • Dinge, die nicht zitiert werden können:Dies erfordert eine Whitelist

Hinweis :Alles in einer String-Variablen (char , varchar , nchar , nvarchar usw.), die aus benutzergesteuerten Quellen stammen, müssen eine der oben genannten Methoden verwenden. Das bedeutet, dass selbst Dinge, von denen Sie erwarten, dass es sich um Zahlen handelt, in Anführungszeichen gesetzt werden, wenn sie in String-Variablen gespeichert sind.

Weitere Einzelheiten finden Sie im Microsoft Magazine (Veralteter Link:2016-10-19) .

Hier ist ein Beispiel, das alle drei Methoden verwendet:

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

Beachten Sie auch, dass Sie alle Zeichenfolgenoperationen inline in EXEC ausführen Aussage gibt es keine Bedenken wegen Trunkierungsproblemen. Wenn Sie die Zwischenergebnisse Variablen zuweisen, müssen Sie müssen Stellen Sie sicher, dass die Variablen groß genug sind, um die Ergebnisse aufzunehmen. Wenn Sie SET @result = QUOTENAME(@name) ausführen Sie sollten @result definieren mindestens 258 (2 * 128 + 2) Zeichen enthalten. Wenn Sie SET @result = REPLACE(@str, '''', '''''') ausführen Sie sollten @result definieren doppelt so groß sein wie @str (Nehmen Sie an, dass jedes Zeichen in @str könnte ein Zitat sein). Und natürlich muss die Zeichenfolgenvariable, die die letzte SQL-Anweisung enthält, groß genug sein, um das gesamte statische SQL plus alle Ergebnisvariablen aufzunehmen.