SQL-инъекция на INSERT - PullRequest
       47

SQL-инъекция на INSERT

26 голосов
/ 25 марта 2009

Я создал небольшую страницу с обзором в нашей компании Интранет. Эта веб-страница недоступна извне.

Форма - это просто пара переключателей и поле для комментариев.

Я хотел бы придерживаться хороших методов кодирования и хотел бы защититься от SQL-инъекций.

Может ли SQL-инъекция произойти в операторе вставки с комментариями из текстового поля? Если так, как я могу защититься от этого, используя .NET 2.0?

Ответы [ 8 ]

56 голосов
/ 25 марта 2009

Инъекция может произойти, если оператор 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-инъекцией.

Для предотвращения этого вам необходимо использовать параметризованные операторы SQL .

И это не только по соображениям безопасности. Например, если вы создаете свои операторы SQL наивно следующий комментарий:

I'm just loving this website

вызовет синтаксическую ошибку SQL из-за того, что апостроф интерпретируется SQL как закрывающая кавычка.

27 голосов
/ 25 марта 2009

Используйте параметризованные запросы, чтобы текст автоматически цитировался для вас.

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 голосов
/ 25 марта 2009

Внедрение SQL может произойти каждый раз, когда вы отправляете запрос обратно в базу данных. Вот простая демонстрация:

Внедрение SQL объяснено

Ключ в .NET - это то, что дал Дэйв Уэбб. Это предотвратит попытку внедрения, заключив всю строку в один передаваемый параметр, обрабатывая все символы, которые могут быть интерпретированы SQL Server для изменения запроса или добавления дополнительных команд.

И следует отметить, что внедрение SQL может происходить в любом приложении, а не только в веб-приложениях. И что внутренняя атака, как правило, наиболее затратна для организации. Нельзя смело предположить, что атака не будет происходить изнутри.

0 голосов
/ 30 октября 2012

Предотвращение SQL-инъекций с использованием подготовленного оператора. Использование placehoder (?) Полностью устраняет уязвимость sql Injection. пример String sql = Выбрать * из user_table, где username = '+ request.getparameter ("username") +'; statement.executeQuery (SQL);

вышеприведенный оператор уязвим для SQL-инъекций.

Чтобы обезопасить себя от инъекций sql. Использовать после фрагмента

String sql = Выбрать * из user_table, где username = ?; statement.setString (1, имя пользователя);

0 голосов
/ 25 марта 2009

В дополнение к использованию подготовленных операторов и параметров, а не к конкатенации строк в вашем SQL, вы также должны сделать следующее:

  1. Проверка и форматирование пользовательского ввода на стороне сервера. Проверку и ограничения на стороне клиента можно легко обойти с помощью таких инструментов, как WebScarab, или путем подмены формы.

  2. Настройте соответствующие разрешения для учетной записи пользователя базы данных. Веб-приложение должно использовать отдельную учетную запись или роль в вашей базе данных с разрешениями, ограниченными только таблицами, представлениями и процедурами, необходимыми для запуска вашего приложения. Убедитесь, что у пользователя нет прав выбора для системных таблиц

  3. Скрыть подробные сообщения об ошибках от пользователей и использовать менее распространенные имена для ваших объектов. Меня удивляет, как часто вы можете определить тип сервера (oracle, mysql, sqlserver) и найти основную информацию о схеме в сообщении об ошибке, а затем получить информацию из таблиц под названием «пользователь (ы)», «сотрудник (и)». Если вы не установили свои разрешения, как в (2), и я могу определить тип вашего сервера, вы открыты для таких заявлений для SQL Server

    ВЫБЕРИТЕ имя_таблицы FROM information_schema.table

    EXECUTE sp_help foundTableName

0 голосов
/ 25 марта 2009

Да, они могут случиться. Самый простой способ избежать этого - использовать подготовленные операторы, а не создавать 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.

0 голосов
/ 25 марта 2009

Да, это возможно. Допустим, клиент отправляет это:

OR 1 = 1

Это может быть очень болезненным для вашего

  SELECT * FROM admin WHERE name = @name AND password = @password

Вы можете предотвратить это с помощью

0 голосов
/ 25 марта 2009

Самый простой способ защититься от этой формы внедрения SQL - это использовать параметры и хранимые процедуры, а не создавать операторы SQL для запуска. (В C # или внутри SQL Server).

Однако я не совсем уверен, что вы должны тратить время на это, если, конечно, это не ваша корпоративная политика, поскольку шансы на то, что это когда-либо произойдет внутри компании, в лучшем случае минимальны, и если это произойдет, я надеюсь, что вы это сделаете немедленно знай, кто это.

...