У меня было несколько контекстов, когда имена таблиц или схемы не были жестко запрограммированы, а скорее настроены администратором или, что еще хуже, сгенерированы из пользовательского ввода.
Поскольку случаи были простыми (схемы и имена таблиц на простом английском языке, без цифр и символов), было легко избежать SQL-инъекций, просто запретив любой символ вне диапазонов A-Z
и a-z
. Но такой подход неудачен, когда приложение должно обрабатывать любые символы Unicode, когда они могут быть частью имени схемы или таблицы.
Теперь, если SQL-запрос использует '['
и ']'
для включения имен в схему, таблицу и столбец, достаточно ли запретить только ']'
символов в именах, чтобы избежать SQL-инъекции?
Пример:
A'B - допустимое имя таблицы. Итак:
string tableNameFromUserInput = "A'B"; // Let's imagine it is a user input.
using (SqlCommand getEverything = new SqlCommand(
string.Format("select * from [dbo].[{0}]", tableNameFromUserInput),
sqlConnection)
{
// Do stuff.
}
совершенно корректно, и нет никаких причин блокировать символ одинарной кавычки.
Так есть ли риск внедрения SQL в следующем коде?
string tableName = UserInput.GetUnsafeInputFromUser();
// Search for ']' character only.
if (tableName.IndexOf(']') != -1)
{
throw new HackerDetectedException();
}
else
{
using (SqlCommand getEverything = new SqlCommand(
string.Format("select * from [dbo].[{0}]", tableNameFromUserInput),
sqlConnection)
{
// Do stuff.
}
}
Изменить:
После некоторого поиска я обнаружил статью о Идентификаторы с разделителями в Microsoft SQL. Согласно этому:
Тело идентификатора может содержать любую комбинацию символов в текущей кодовой странице, кроме самих символов-разделителей.
Кстати, идентификаторы с разделителями ограничены 128 символами.
Чтобы заставить его работать:
- Символ
']'
должен быть запрещен (или, лучше, заменен на ']]'
; см. Ответ Марка Байерса ниже).
- Длина должна быть ограничена 128 символами (не сделано в приведенном выше примере кода),
- Кодовая страница, вероятно, должна быть проверена, чтобы получить правильную таблицу.