Jaka funkcja cytuje identyfikator w dynamicznym SQL z SQL Server?

11

Jaka jest metoda SQL Server bezpiecznego cytowania identyfikatorów do dynamicznego generowania kodu SQL.

Jak zapewnić otrzymanie dynamicznie generowanej nazwy kolumny dla dynamicznie generowanego oświadczenia, że ​​sama kolumna nie jest atakiem wstrzykiwania SQL.

Powiedzmy, że mam instrukcję SQL,

SELECT [$col] FROM table;

który jest zasadniczo taki sam jak

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

Co zatrzymuje atak iniekcyjny gdzie

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

Wynikające z

SELECT [name] FROM sys.objects;
DROP TABLE my.accounts;
-- ] FROM table;
Evan Carroll
źródło

Odpowiedzi:

14

Funkcja, której szukasz QUOTENAME!

Dzięki praktycznemu zastosowaniu technologii nawiasów kwadratowych możesz bezpiecznie enkapsulować łańcuchy, aby pomóc w zapobieganiu atakom typu „hot SQL injection”.

Zwróć uwagę, że samo nawijanie nawiasów kwadratowych wokół czegoś nie podaje tego bezpiecznie, chociaż możesz uniknąć błędów w kodzie z nieprawidłowymi znakami w nazwach obiektów.

Dobry kod

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

Zły kod

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

Aby podać konkretny przykład ...

Poniższe działa dobrze dla początkowego wprowadzania

DECLARE @ObjectName SYSNAME = 'sysobjects';

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

EXEC (@dynSql);

Ale przy złośliwych danych wejściowych jest podatny na wstrzykiwanie SQL

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);

Poprawne użycie QUOTENAMEpowoduje ucieczkę osadzonego ]i zapobiega wystąpieniu próby wstrzyknięcia SQL.

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);

Nieprawidłowa nazwa obiektu 'sysobjects]; SELECT' Jest to dowolny wykonany kod. Mogło upuścić tabelę lub udzielić uprawnień „-”.

Erik Darling
źródło