Welche Funktion zitiert einen Bezeichner in dynamic-sql mit SQL Server?

11

Was ist die SQL Server-Methode zum sicheren Zitieren von Bezeichnern für die dynamische SQL-Generierung?

Wie stelle ich sicher, dass bei einem dynamisch generierten Spaltennamen für eine dynamisch generierte Anweisung die Spalte selbst kein SQL-Injection-Angriff ist?

Angenommen, ich habe eine SQL-Anweisung.

SELECT [$col] FROM table;

das ist im Wesentlichen das gleiche wie

'SELECT [' + $col + '] FROM table;'

Was stoppt einen Injektionsangriff wo?

$col = "name] FROM sys.objects; \r\n DROP TABLE my.accounts; \r\n\ --";

Ergebend

SELECT [name] FROM sys.objects;
DROP TABLE my.accounts;
-- ] FROM table;
Evan Carroll
quelle

Antworten:

14

Die Funktion, die Sie suchen, ist QUOTENAME!

Durch die praktische Verwendung der Square-Bracket-Technologie können Sie Zeichenfolgen sicher kapseln, um Hot-SQL-Injection-Angriffe zu verhindern.

Beachten Sie, dass das einfache Anbringen von eckigen Klammern um etwas nicht sicher ist, obwohl Sie vermeiden können, dass Ihr Code mit ungültigen Zeichen in Objektnamen fehlerhaft ist.

Guter Code

DECLARE @sql NVARCHAR(MAX) = N''
SELECT @sql = 'SELECT ' + QUOTENAME(d.name) + ' FROM your_mom'
FROM sys.databases AS d

Schlechter Code

DECLARE @sql NVARCHAR(MAX) = N''
SELECT @sql = 'SELECT [' + d.name + '] FROM your_mom'
FROM sys.databases AS d

Um ein konkretes Beispiel zu geben ...

Das Folgende funktioniert gut für die anfängliche Eingabe

DECLARE @ObjectName SYSNAME = 'sysobjects';

DECLARE @dynSql NVARCHAR(MAX) = 'SELECT COUNT(*) FROM [' + @ObjectName + ']';

EXEC (@dynSql);

Bei böswilligen Eingaben ist es jedoch anfällig für SQL-Injection

DECLARE @ObjectName SYSNAME = 'sysobjects];SELECT ''This is some arbitrary code executed. It might have dropped a table or granted permissions''--'

DECLARE @dynSql NVARCHAR(MAX) = 'SELECT  COUNT(*)  FROM [' + @ObjectName + ']';

EXEC (@dynSql);

Bei QUOTENAMEkorrekter Verwendung wird das Embedded entgangen ]und die versuchte SQL-Injection wird verhindert.

DECLARE @ObjectName SYSNAME = 'sysobjects];SELECT ''This is some arbitrary code executed. It might have dropped a table or granted permissions''--'

DECLARE @dynSql NVARCHAR(MAX) = 'SELECT  COUNT(*)  FROM ' + QUOTENAME(@ObjectName);

EXEC (@dynSql);

Ungültiger Objektname 'sysobjects]; SELECT' Dies ist ein beliebiger Code, der ausgeführt wird. Möglicherweise wurde eine Tabelle gelöscht oder die Berechtigung '-' erteilt.

Erik Darling
quelle