SQL инъекции. 5 советов по борьбе с уязвимостями

Недавно, сидя вечером дома, я обнаружил, что у меня нет рабочих задач. Это заставило мыслить об окружающем мире. И я вспомнил сайт одного заказчика, который раньше обслуживался у другого поставщика IT-решений (назовем эту фирму — NON). У нас были данные доступа в админпанель. Немного поразмыслив, я обнаружил уязвимость в коде фирмы NON. Через час я взломал другой сайт этой фирмы, а еще через час и сайт самой компании NON.

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

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

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

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

SQL инъекции. 5 советов по борьбе с уязвимостями
SQL инъекции. 5 советов по борьбе с уязвимостями

Пример уязвимости на PHP

Следующий фрагмент кода предназначен для смены пароля пользователем:

$password = $_POST['password'];
$id = $_POST['id'];
$sql = «UPDATE users SET password = ‘$password’ WHERE user_id = $id»;

Предположим, атакующий передал следующие данные POST запросом:

password=12345 и id=account_id

В итоге запрос примет следующий вид:

UPDATE users SET password = ’12345′ WHERE user_id = user_id

Ожидалось, что user_id – число, но никак не название столбца. Естественно, данный запрос затронет каждую строку в БД. Теперь атакующий с лёгкостью может войти под любым аккаунтом на сайте, включая, даже аккаунт администратора.

Как предотвратить SQL инъекции такого типа

  1. Всегда проверяйте валидность входящих данных. Числа должны быть числами, строки – строками (привет динамическая типизация PHP:)
  2. Фильтруйте специальные символы (кавычки, тире). В PHP есть для этого специальная функция: mysql_escape_string.
  3. Не передавайте данные прямо в запрос. Используйте подготовленные запросы, а лучше хранимые процедуры. Рассмотренный выше запрос будет лучше, если использовать подготовленный запрос:

$statement = $db->prepare(‘UPDATE users SET password = :password WHERE user_id = :id ‘);
$statement->bindValue(‘:password’, $password);
$statement->bindValue(‘:id, $id);
$statement->execute();

  1. Не давайте скрипту полный доступ на операции с БД. Зачем скрипту сайта визитки разрешение на операцию DROP?
  2. Не выводите системные сообщения об ошибках запроса. Это усложнит понимание структуры БД злоумышленником.
Nazario

Я — Nazario, создатель и автор сайта linuxwin.ru, специализируюсь на информационных технологиях с акцентом на системное администрирование Linux и Windows, веб-разработку и настройку различных систем.

Linux и Windows
Выскажите своё мнение или присоединяйтесь к обсуждению:

Отправляя комментарий, вы даете согласие на обработку ваших данных в соответствии с политикой конфиденциальности и даёте согласие на их использование.