Что такое SQL-инъекция?

Возможные дубликаты:

Как работает SQL-инъекция из комикса XKCD "Таблицы Бобби"?
https://stackru.com/search?q=sql+injection

Может кто-нибудь объяснить SQL-инъекцию? Как это вызывает уязвимости? Где именно находится точка, где вводится SQL?

9 ответов

Может кто-нибудь объяснить SQL инъекцию?

Внедрение SQL происходит, когда вы интерполируете некоторый контент в строку запроса SQL, и результат изменяет синтаксис вашего запроса так, как вы этого не предполагали.

Это не должно быть злым, это может быть несчастный случай. Но случайная инъекция SQL с большей вероятностью приведет к ошибке, чем к уязвимости.

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

Как это вызывает уязвимости?

Это может привести к уязвимости, поскольку злоумышленники могут отправлять значения в приложение, которое, как они знают, будет интерполировано в строку SQL. Будучи очень умными, они могут манипулировать результатами запросов, читать данные или даже изменять данные, что им нельзя делать.

Пример в PHP:

$password = $_POST['password'];
$id = $_POST['id'];
$sql = "UPDATE Accounts SET PASSWORD = '$password' WHERE account_id = $id";

Теперь предположим, что атакующий устанавливает параметры запроса POST на "password=xyzzy" а также "id=account_id"приводя к следующему SQL:

UPDATE Accounts SET PASSWORD = 'xyzzy' WHERE account_id = account_id

Хотя я ожидал $id чтобы быть целым числом, злоумышленник выбрал строку, которая является именем столбца. Конечно, теперь условие выполняется в каждой строке, поэтому злоумышленник только что установил пароль для каждой учетной записи. Теперь злоумышленник может войти в любой аккаунт, включая привилегированных пользователей.

Где именно находится точка, где вводится SQL?

Это не SQL, который вводится, это контент, который интерполируется ("внедряется") в строку SQL, что приводит к запросу другого типа, чем я планировал. Я доверял динамическому контенту, не проверяя его, и выполнял полученный SQL-запрос вслепую. Вот тут и начинается беда.

Внедрение SQL - это ошибка в коде приложения, обычно не в базе данных или в библиотеке доступа к базе данных.

В большинстве случаев внедрения SQL можно избежать, используя параметры запроса. См. Как я могу предотвратить внедрение SQL в PHP? Например.

Инъекция SQL происходит, когда пользователь приложения может влиять на значение запроса к базе данных. Это часто происходит, когда произвольные строки из пользовательского ввода объединяются для создания SQL, который подается в базу данных. Например, допустим, у нас был следующий код (в PHP, но то же самое относится и к любому языку), который может быть использован для обработки входа пользователя.

$sql = "SELECT  FROM users WHERE username='".$_GET['username']."' AND password='".$_GET['password']."'";

Вред наносится, когда пользователь вводит что-то вроде

administrator'; --

... для имени пользователя. Без правильного кодирования запрос становится:

SELECT * FROM users WHERE username='administrator'; -- AND password=''

Проблема здесь в том, что 'в имени пользователя закрывает поле имени пользователя, а затем - запускает комментарий SQL, в результате чего сервер базы данных игнорирует остальную часть строки. В результате пользователь может войти в систему как администратор, не зная пароля. SQL Inection также можно использовать для выполнения запросов UPDATE, DELETE или DROP и реального повреждения базы данных.

Инъекцию SQL можно предотвратить с помощью параметризованных запросов или применения экранирующих функций вашего языка / инструментария (таких как mysql_real_escape_string() в PHP).

Как только вы поймете SQL-инъекцию, вы получите шутку за этот мультфильм.

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

Вот ссылки на некоторые из моих прошлых ответов на эту тему:

Я также выступил с докладом на конференции MySQL в этом месяце, и мои слайды онлайн:

Внедрение SQL - это когда объекты, которые должны быть данными, невольно рассматриваются как код SQL.

Например, если вы должны были сделать

mysql_query("SELECT * FROM posts WHERE postid=$postid");

Обычно он получит сообщение с указанным идентификатором, но предположим, что $postid установлен на строку 10; DROP TABLE posts --; внезапно, фактический запрос вы отправляете

mysql_query("SELECT * FROM posts WHERE postid=10; DROP TABLE posts --");

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

Самый простой способ предотвратить это - использовать подготовленные операторы, например, через PDO или MySQLi.

Эквивалентный пример в PDO будет

$statement = $db->prepare('SELECT * FROM posts WHERE postid = :postid');
$statement->bindValue(':postid', $postid);
$statement->execute();

Это гарантирует, что система баз данных знает, что $ postid следует рассматривать как данные, а не как код, и, таким образом, будет обрабатываться соответствующим образом.

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

Совет № 1, которого я придерживаюсь, состоит в том, чтобы использовать параметризованные хранимые процедуры, а не создавать сырой SQL в коде.

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

Я обнаружил, что эта статья является чрезвычайно хорошим чтением о методах внедрения SQL (ссылка на PDF): Расширенное внедрение SQL в приложениях SQL Server.

Несмотря на заголовок "Advanced", он вполне читабелен, даже если у вас мало знаний о внедрении SQL.

Чтобы получить общие сведения, ознакомьтесь со статьей в Википедии об SQL-инъекциях.

Короче говоря, атаки с использованием SQL-инъекций могут сделать вас уязвимыми для кражи и уничтожения данных. Точные детали того, что можно сделать с вашей системой, зависят от деталей самой системы.

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

Вам понравится эта статья из кода проекта;)

Резюме

  • Шифровать конфиденциальные данные.
  • Доступ к базе данных с использованием учетной записи с наименьшими необходимыми привилегиями.
  • Установите базу данных, используя учетную запись с наименьшими необходимыми привилегиями.
  • Убедитесь, что данные действительны.
  • Сделайте обзор кода, чтобы проверить возможность атак второго порядка.
  • Используйте параметризованные запросы.
  • Используйте хранимые процедуры.
  • Повторная проверка данных в хранимых процедурах.
  • Убедитесь, что сообщения об ошибках ничего не сообщают о внутренней архитектуре приложения или базы данных.

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

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

Без надлежащего экранирования некоторый код SQL, "введенный" пользователем, может быть выполнен механизмом SQL как код SQL, а не как простая строка или значение.

Другие вопросы по тегам