Что такое 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, но это важная тема, о которой все должны знать, поэтому я не собираюсь голосовать, чтобы закрыть этот вопрос.
Вот ссылки на некоторые из моих прошлых ответов на эту тему:
- Что такое SQL-инъекция?
- Как защитить эту функцию от SQL-инъекций?
- Достаточно ли параметров для предотвращения инъекций Sql?
- Является ли инъекция SQL риском сегодня?
Я также выступил с докладом на конференции 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, а не как простая строка или значение.