Sql инъекции

Sql инъекции

SQl-инъекция — это техника, когда злоумышленник вводит команды SQL в input поле на веб-странице. В роли imput-а может выступать текстовое поле в форме, параметр GET/POST, cookies и т.д. Этот метод был весьма эффективным до появления фреймворков в мире PHP. Но этот способ взлома может быть по-прежнему опасен, если вы не используете ORM или какие-либо еще расширения для data object, по причине передачи параметров в SQL запрос.

 

«Слепые» инъекции

mysql_query('SELECT id, login FROM users WHERE login = "' . $login . '" and password = hash("' . $password . '")');

В этом случае в коде нет проверки на ввод неправильных данных. Значения передаются прямо из формы ввода в SQL запрос. В самом лучшем случае пользователь введет здесь свои логин и пароль. Что случится в худшем случае? Давайте попробуем хакнуть эту форму. Это можно сделать, передав «подготовленные» данные. Попытаемся войти как первый пользователь из базы данных, а в большинстве случаев — это админский аккаунт. Для этого, передадим специальную строку вместо ввода логина:

" OR 1=1; --

Первая кавычка может быть и одинарной, поэтому одной попыткой взлома можно не обойтись. В конце стоят точка с запятой и два дефиса, чтобы всё, что идёт после превратилось в комментарий. В результате будет выполнен следующий SQL запрос:

SELECT id, login FROM users WHERE login = "" OR 1=1; --" and password = hash("")

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

 

Более серьезные способы

В предыдущем примере всё не так уж страшно. Возможности в админской панели управления всегда имеют ограничения и потребуется реально много работы, чтобы поломать сайт. А вот атака через SQL инъекции может привести к куда большим повреждениям системы. Задумайтесь, сколько приложений создаются с главной таблицей ‘users’ , и что будет, если злоумышленник введет такой код в незащищённую форму:

My favorite login'; DROP TABLE users; --

Таблица ‘users’ будет удалена. Это одна из причин почаще делать бэкапы баз данных.

 

GET параметры

Все параметры, заполненные через форму, передаются на сервер одним из двух методов — GET или POST. Наиболее распространенный параметр, передаваемый через GET — id. Это одно из самых уязвимых мест для атак, при этом неважно, какого вида урл вы используете

  • http://example.com/users/?id=1
  • http://example.com/users/1
  • http://……./…/post/35

Что произойдет, если мы подставим для

'SELECT id, login, email, param1 FROM users WHERE id = ' . $_GET['id'];

в урл следующий код?

 AND 1=0 UNION SELECT 1,concat(login,password), 3,4,5,6 FROM users WHERE id =1; --

Вероятно, такой запрос вернет нам логин пользователя и хеш от его пароля. Первая часть запроса «AND 1=0» превращает то, что перед ним в false, соответственно никаких записей не будет получено. А вторая часть запроса вернет данные в виде prepared data. А так как первым параметром идет id, следующим будет логин пользователя и хеш его пароля и еще сколько-то параметров. Существует множество программ, с помощью брутфорса декодирующих такой пароль, как в примере. А так как пользователь может использовать один и тот же пароль для разных сервисов, можно получить доступ и к ним.

И вот что любопытно: от такого способа атаки совершенно невозможно защититься методами вроде `mysql_real_escape_string`, `addslashes` и т.д. В принципе, нет способа избежать такой атаки, поэтому, если параметры будут передаваться так:

'SELECT id, login, email, param1 FROM users WHERE id = ' . addslashes($_GET['id']);'

проблемы не исчезнут.

 

Экранирование символов в строке

Проблем, описанных в большинстве предыдущих примеров, можно избежать, используя одинарные кавычки в запросах. Если вы используете addslashes(), атаки через SQL-инъекции, построенные на использовании одинарных кавычек, экранируемых обратным слэшем, потерпят неудачу. Но такая атака может пройти, если просто подставить символ с кодом 0xbf27 , addslashes()преобразует его в символ с кодом 0xbf5c27 – а это вполне валидный символ одинарной кавычки. Другими словами, «뼧» пройдет через addslashes(), а потом маппинг MySQL конвертирует его в два символа 0xbf (¿) и 0x27 (‘).

"SELECT * FROM users WHERE login = '".addslashes($_GET['login'])."'";

Этот пример можно хакнуть, передав '뼧 or 1=1; --' в поле логина в форме. Движок SQL сгенерирует конечный запрос так:

SELECT * FROM users WHERE login = '¿' OR 1=1; --

И вернет первого пользователя из БД.

 

Защита

Как же защитить приложение? Есть куча способов, применение которых не сделает приложение совсем неуязвимым, но хотя бы повысит его защищенность.

 

Использование mysql_real_escape_string

Функция addslashes() ненадежна, так как не предусматривает многие случаи взлома. У mysql_real_escape_string нет таких проблем.

 

Использование MySQLi

Это расширение для MySQL умеет работать со связанными параметрами:

$stmt = $db->prepare('update uets set parameter = ? where id = ?');
$stmt->bind_param('si', $name, $id);
$stmt->execute();

 

Использование PDO

Более продвинутое расширения для работы с подключениями:

$dbh = new PDO('mysql:dbname=testdb;host=127.0.0.1', $user, $password);
$stmt = $dbh->prepare('UPDATE people SET name = :new_name WHERE id = :id');
$stmt->execute( array('new_name' => $name, 'id' => $id) );

 

Использование ORM

Используйте ORM и PDO и связывайте (используйте bind) параметры. Избегайте SQL в коде, если вы видите в коде SQL, значит, с ним что-то не так.

ORM позаботится о безопасности в самых узких местах в коде и о валидации параметров.

 

Опубликовано:
Пожертвование
На развите проекта, продление хостинга и на корм бобику - Дикуше :)