Безопасность Базы Данных (SQL Injection)
Задание:
наверняка вы где-нибудь да слышали о том, что существует множество различных способов атаковать сайт, приложение или программу через дыры в безопасности, которые оставляют разработчики. Часто либо от лени, либо по незнанию, незащищённой оставляется и база данных, поэтому одной из самых распространённых атак до сих пор являются SQL-инъекции. Их суть заключается во внедрении взломщиком произвольного SQL кода в наш запрос, и это очень опасно, поскольку злоумышленник может как своровать или удалить данные из базы, так и занести вредоносную информацию. Соответственно, задача любого ответственного разработчика - обезопасить своё приложение и его пользователей от подобного рода проблем.
Подробная инструкция:
- Чаще всего инъекцию можно провести либо через GET параметры адресной строки, либо при помощи пользовательской формы. Делается это весьма несложно - если мы, к примеру, ищем какую-либо запись в базе по id из адресной строки с помощью такого запроса:
$id = $_GET['id'];
$sql = "SELECT * FROM table_name WHERE {$id}";
то в адресной строке можно дописать следующее:
'page.php?id=4;DELETE FROM users;'
При этом всё, что было написано после знака =
подставится в запрос вместо переменной $id
и вся таблица с пользователями будет удалена. Это происходит потому, что разделитель ;
в языке SQL - это спец символ, означающий конец запроса, после которого можно написать ещё один, при этом отработают они оба. Здесь как раз и приходят на помощь подготовленные запросы и PDO.
- Суть подготовленного выражения в том, что на место переменной мы подставляем метку (или плейсхолдер), которой затем присваивается значение нужной переменной. Метод специальной подготовки запроса
prepare()
проверяет содержимое меток и автоматически экранирует все спец символы, которые после этого будут считываться как обычный текст.
- Метки бывают двух видов - именованные и неименованные, но многие используют первые для повышения читабельности и наглядности кода. Выглядит это так:
$sql = "SELECT * FROM table_name WHERE id=:id";
При таком способе в execute()
передаётся ассоциативный массив с ключами, соответствующими названиям меток, примерно такого плана: [':id' => $id]
. Есть и другой способ использования меток:
$sql = "SELECT * FROM table_name WHERE id = ? AND title = ?";
массив для execute()
в таком случае будет простым, но при этом его значения должны идти СТРОГО в том порядке, в котором расположены метки в запросе: array($id, $title)
ПОЯСНЕНИЯ И ПОЛЕЗНАЯ ИНФОРМАЦИЯ
- Конечно, использование подготовленных выражений не является стопроцентной гарантией безопасности, поэтому существуют и дополнительные меры предосторожности для защиты от SQL инъекций. Например, если вы ожидаете в полученной от пользователя переменной число, проверяйте, действительно ли в неё пришло числовое значение, или принудительно приводите к этому типу данных, если есть такая возможность.
- В этом уроке мы разобрали, почему важно следить за уязвимостями своей базы данных, а так же основные аспекты, на которые стоит обратить внимание. Узнать наиболее подробную информацию про подготовленные выражения и защиту от SQL-инъекций можно в мануале
PHP.net
, а так же в открытом доступе сети интернет