Запретить SQL-инъекцию, когда имя таблицы и предложение where являются переменными
У меня в ситуации нужна твоя помощь. На данный момент я создал приложение asp.net, используя ado.net. Я использую CommandText для построения динамического запроса, поэтому в нем есть уязвимость SQL-инъекции. Мой CommandText, как это
String.Format("SELECT COUNT(*) FROM {0} {1}", tableName, whereClause)
TableName и whereClause передаются разработчиком. Как вы видите, я не могу использовать SQLParameters здесь, потому что мне нужно передать весь tableName и whereClause не только значения параметров.
Мое решение для предотвращения SQL-инъекций - использовать проверку BlackNist TableName и whereClause для обнаружения вредоносной строки, но я не знаю, что это лучший способ в этой ситуации, не так ли? И если это кто-то может помочь мне, где найти ссылки BlackList или библиотеки.
1 ответ
Не зная дополнительных подробностей, у вас есть несколько вариантов, чтобы избежать атак SQL-инъекций или, по крайней мере, минимизировать ущерб, который может быть нанесен:
- Белый список более безопасен, чем черный: подумайте, действительно ли вам нужен доступ ко всем таблицам, кроме черных. Если кто-то добавит таблицы позднее, он может забыть добавить их в черный список.
- Может быть, вы можете ограничить доступ к определенному подмножеству таблиц. В идеале эти таблицы следуют общей схеме именования, поэтому имя таблицы может быть проверено по этой схеме. Если схема именования отсутствует, вы также можете добавить список таблиц, к которым можно получить доступ в программе или конфигурации приложения, чтобы вы могли проверить, содержится ли имя таблицы в этом списке. Если вы сохраните список в файле конфигурации, вы сможете расширить список без повторной компиляции приложения.
- Если вы не можете внести в белый список имена таблиц, вы можете по крайней мере проверить, присутствует ли указанное имя таблицы в базе данных, запросив
sys.tables
системная таблица (в SQL Server другие СУБД могут иметь аналогичные таблицы). В этом запросе вы можете использовать параметры, чтобы вы были в безопасности. - Для SQL Server вы должны поставить имя таблицы в квадратных скобках (
SELECT COUNT(*) FROM [" + tableName + "]"
). Квадратные скобки используются для разделения идентификаторов (см. Также эту ссылку). Для того, чтобы это работало, вы должны проверить, чтоtableName
переменная не содержит закрывающей квадратной скобки. ЕслиtableName
переменная может содержать идентификатор схемы (например,dbo.MyTable
вам нужно сначала разделить части, а затем добавить квадратные скобки ([dbo].[MyTable]
), поскольку это отдельные идентификаторы (один для схемы, один для имени таблицы). - Проверяйте содержимое переменных очень тщательно, используя регулярные выражения или аналогичные проверки. Это легко для имени таблицы, но очень трудно для
WHERE
предложение, поскольку вам, в основном, придется проанализировать предложение SQL WHERE и утверждать, что опасный код не содержится. - Самое сложное - это проверить
WHERE
пункт. Также в этом отношении было бы лучше, если бы вы могли ограничить параметры для пользователя и внести в белый список возможныеWHERE
статьи. Это означает, что пользователь может выбирать из диапазонаWHERE
пункты, которые программа знает или создает на основе пользовательского ввода. Эти известныеWHERE
предложения могут содержать параметры и, следовательно, безопасны от атак SQL-инъекций. Если вы не можете внести в белый списокWHERE
пункты, вам придется проанализироватьWHERE
пункт, чтобы иметь возможность решить, является ли определенный запрос опасным или нет. Это потребует больших усилий (если вы не найдете библиотеку, которая может сделать это за вас), поэтому я постараюсь внести в белый список как можно больше частей динамического запроса. - Чтобы уменьшить ущерб от успешной атаки, вы должны выполнить запрос под определенной учетной записью с очень ограниченными правами. Вам необходимо добавить еще одну строку подключения в файл конфигурации, который использует эту учетную запись, и создать подключение с помощью строки ограниченного подключения. В SQL Server вы можете перемещать таблицы, к которым эта учетная запись может обращаться к определенной схеме, и ограничивать доступ к этой схеме для этой учетной записи.
- Очень хорошо защитите свой сервис от несанкционированного доступа, чтобы только доверенные разработчики могли получить к нему доступ. Это можно сделать, используя некоторые компоненты инфраструктуры (брандмауэры, безопасность на транспортном уровне и т. Д.), А также добавив надежный механизм аутентификации пользователей.
- Записывайте каждый запрос в службу, чтобы можно было идентифицировать пользователя и машину. Уведомите пользователей об этом механизме регистрации, чтобы они знали, что они будут идентифицированы, если что-то пойдет не так.
Несколько заключительных мыслей: даже если кажется, что очень просто предоставить разработчикам такой открытый метод для запроса данных, подумайте, действительно ли это необходимо. Один из возможных вариантов - не иметь этого открытого доступа, а вместо этого настраивать запросы, которые нужны другим разработчикам, в файле конфигурации. Каждый запрос получает идентификатор, и текст запроса сохраняется в файле и, следовательно, известен заранее. Тем не менее, вы можете добавлять новые запросы или изменять существующие после развертывания службы. Вы можете разрешить параметры в запросе, которые задают вызывающие (может быть схема нумерованных параметров, такая как p1, p2, ...).
Как видно из приведенного выше списка, очень сложно (а в некоторых областях, близких к невозможным) заблокировать службу и избежать всевозможных атак с использованием SQL-инъекций, как только вы разрешите этот открытый доступ. С подходом, описанным в предыдущем параграфе, вы теряете некоторую гибкость, но вам больше не придется беспокоиться о атаках с использованием SQL-инъекций.