SQL-инъекция на INSERT
Я создал небольшую веб-страницу опроса в нашей компании Intranet. Эта веб-страница недоступна извне.
Форма представляет собой просто пару переключателей и поле для комментариев.
Я хотел бы поддерживать хорошие методы кодирования и хотел бы защитить от SQL Injections.
Могут ли SQL-инъекции выполняться в инструкции insert с комментариями из текстового поля?
Если да, то как я могу защититься от него с помощью .NET 2.0?
Ответы
Ответ 1
Инъекция может произойти в любой инструкции SQL, которая не работает должным образом.
Например, допустим, что ваша таблица комментариев имеет два поля, целочисленный идентификатор и строку комментария. Итак, вы бы INSERT
следующим образом:
INSERT INTO COMMENTS VALUES(122,'I like this website');
Подумайте, кто-то вводит следующий комментарий:
'); DELETE FROM users; --
Если вы просто поместите строку комментария в SQL без каких-либо процессов, это может превратить ваш единственный INSERT
в следующие два оператора, за которыми следует комментарий:
INSERT INTO COMMENTS VALUES(123,''); DELETE FROM users; -- ');
Это приведет к удалению всего из вашей таблицы users
. И есть люди, которые готовы потратить весь день на поиск правильного имени табуляции для пустых проб и ошибок и различных трюков. Здесь описано, как можно выполнить атаку SQL Injection.
Для предотвращения этого необходимо использовать параметризованные операторы SQL.
И это касается не только соображений безопасности. Например, если вы создаете свои инструкции SQL наивно следующим комментарием:
I'm just loving this website
приведет к синтаксической ошибке SQL из-за того, что апостроф интерпретируется SQL как закрывающая цитата.
Ответ 2
Используйте параметризованные запросы, чтобы текст автоматически указывался для вас.
SqlCommand command = connection.CreateCommand();
command.CommandText = "insert into dbo.Table (val1,val2,txt) values (@val1,@val2,@txt)";
command.AddParameterWithValue( "val1", value1 );
command.AddParameterWithValue( "val2", value2 );
command.AddParameterWithValue( "txt", text );
...
Ответ 3
SQL-инъекция может произойти при каждом обращении запроса к базе данных. Здесь простая демонстрация:
SQL Injection Explained
Ключ в .NET должен делать, как дал Дейв Вебб. Это предотвратит попытку инъекции, охватывая всю строку в качестве одного параметра, который будет отправлен, обрабатывая все символы, которые могут быть интерпретированы SQL Server для изменения запроса или добавления дополнительных команд.
И следует отметить, что SQL-инъекция может возникать в любом приложении, а не только в веб-приложениях. И что внутренняя атака обычно является самой дорогостоящей для организации. Нельзя смело предположить, что атака не будет происходить изнутри.
Ответ 4
Да, это возможно. Скажем, клиент отправляет это сообщение:
OR 1 = 1
Это может быть очень болезненно для вашего
SELECT * FROM admin WHERE name = @name AND password = @password
Вы можете предотвратить это с помощью
Ответ 5
Да, они могут случиться. Самый простой способ защитить это - использовать подготовленные инструкции, а не строить SQL вручную.
Итак, вместо этого:
String sql =
String.Format("INSERT INTO mytable (text_column) VALUES ( '{0}' )",
myTextBox.Text); // Unsafe!
Вы сделали бы что-то вроде этого:
String sql = "INSERT INTO mytable (text_column) VALUES ( ? )"; // Much safer
Затем добавьте текст текстового поля в качестве параметра в свой DbCommand, который приведет к его автоматическому экранированию и замене "?" в SQL.
Ответ 6
В дополнение к использованию подготовленных операторов и параметров, а не конкатенации строк в ваш SQL, вы также должны сделать следующее:
-
Проверять и форматировать ввод данных на стороне сервера. Проверка и ограничения на стороне клиента можно легко обойти с помощью таких инструментов, как WebScarab, или путем подмены вашей формы.
-
Настройте соответствующие разрешения для учетной записи пользователя базы данных. Веб-приложение должно использовать отдельную учетную запись или роль в вашей базе данных с разрешениями, ограничивающими только таблицы, представления и процедуры, необходимые для запуска вашего приложения. Убедитесь, что пользователь не имеет права выбора в системных таблицах
-
Скрыть подробные сообщения об ошибках от пользователей и использовать менее распространенные имена для ваших объектов. Меня поражает, как часто вы можете определить тип сервера (oracle, mysql, sqlserver) и найти основную информацию о схеме в сообщении об ошибке, а затем получить информацию из таблиц "пользователь (ы)", "сотрудник (ы)". Если вы не установили свои разрешения, как в (2), и я могу определить тип вашего сервера, вы открыты для таких операторов для SQL Server
SELECT table_name FROM information_schema.table
EXECUTE sp_help foundTableName
Ответ 7
Предотвратите SQL-инъекцию с помощью подготовленного оператора. Использование placehoder (?) Полностью исключает уязвимость, вызванную sql Injection.
пример
Строка sql = Выберите * из user_table, где username = '+ request.getparameter( "username" ) +';
statement.executeQuery(SQL);
приведенное выше утверждение уязвимо для SQL-инъекции.
Чтобы сделать его безопасным для SQL-инъекции.
Используйте следующий фрагмент
Строка sql = Выберите * из user_table, где username =?;
statement.setString(1, имя пользователя);
Ответ 8
Самый простой способ защитить эту форму SQL-инъекции - использовать параметры и хранимые процедуры, а не создавать SQL-запросы для запуска. (В С# или внутри SQL Server).
Однако я не совсем уверен, что вы должны тратить время на это, если, конечно, это ваша корпоративная политика, так как шансы на ее внутреннее существование минимальны в лучшем случае, и если бы это произошло, я бы надеюсь, что вы немедленно узнайте, кто это.