17 апреля 2011 г.

PHP: Защита процесса авторизации от SQL-инъекций

Раньше, при разработки сайтов, никогда особо не акцентировал свое внимание на защиту от т.з. "SQL-инъекций". Что это такое думаю много говорить не стоит, просто процитирую, что об этом пишут на сайте php.net:

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

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

Уязвимость была обнаружена в функции, обеспечивающий процесс авторизации администратора на сайте.  Для управления проектом был предусмотрен доступ для администратора через веб-форму на сайте приложения. Форма не отличалась особой оригинальностью: поле E-mail и поле Пароль. На серверной стороне для проверки валидности адреса єл. почты и пароля использовалась очень простая процедура: проверка наявности соответствующей записи в таблице пользователей базы данных. SQL-запрос имел следующий вид:


$email = $_POST['email']  
$password = $_POST['password'];
$query = "SELECT * FROM `users` WHERE `email`='" . $email . "' 
AND password='" . dohash($password) . "'"; 

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

Ошибкой данного подхода есть отсутствие какой либо проверки значения вводимого в поле e-mail. Для того чтобы получить доступ к управлению сайта, при хорошем знании SQL, было достаточно воспользоваться следующей инъекцией: ввести в поле E-mail следующее значение "any@mail.ru' or 1=1 --" и указать произвольный пароль. При таком значении переменной $email, запрос гарантированно возвращал результат.

Самым простым способом избавиться от такого рода инъекций является использование хеш-функций для преобразования вводимых данных как на стороне PHP так и на стороне SQL-сервера. Например, можно использовать функцию MD5 MySQL () для создания хэш данных на стороне сервера, а также аналогичные функции на стороне PHP.

Таким образом, маленькие изменения запроса обеспечат защиту от инъекций.


$query = "SELECT * FROM `users` WHERE MD5(`email`)='" . md5($email) . "' 
AND password='" . dohash($password) . "'

Комментариев нет:

Отправить комментарий