Наиболее распространенная рекомендация для борьбы с внедрением SQL - использовать параметр запроса SQL (несколько человек в этой теме предложили это).
Это неправильный ответ в данном случае. Нельзя использовать параметр запроса SQL для имени таблицы в инструкции DDL.
Параметры запроса SQL могут использоваться только вместо литерального значения в выражении SQL. Это стандартно для каждой реализации SQL.
Моя рекомендация по защите от внедрения SQL при наличии имени таблицы заключается в проверке входной строки по списку известных имен таблиц.
Вы можете получить список допустимых имен таблиц из INFORMATION_SCHEMA
:
SELECT table_name
FROM INFORMATION_SCHEMA.Tables
WHERE table_type = 'BASE TABLE'
AND table_name = @tableName
Теперь вы можете передать входную переменную этому запросу в качестве параметра SQL. Если запрос не возвращает строк, вы знаете, что ввод недопустим для использования в качестве таблицы. Если запрос возвращает строку, он совпадает, поэтому у вас больше уверенности, что вы можете безопасно его использовать.
Вы также можете проверить имя таблицы по списку определенных таблиц, которые вы определили как приемлемые для усечения вашего приложения, как @John Buchanan предлагает .
Даже после проверки того, что tableName
существует в качестве имени таблицы в вашей РСУБД, я бы также предложил разделить имя таблицы на тот случай, если вы используете имена таблиц с пробелами или специальными символами. В Microsoft SQL Server разделителями идентификаторов по умолчанию являются квадратные скобки:
string sqlStatement = string.Format("TRUNCATE TABLE [{0}]", tableName);
Теперь вы подвержены риску внедрения SQL, только если tableName
соответствует реальной таблице, и вы фактически используете квадратные скобки в именах ваших таблиц!