Что это за строка?

Строка %' AND EXTRACTVALUE (2015,CONCAT (0x7e, ( (SELECT (ELT (2015=2015,1)))),0x7e))-- - — это классический пример error-based SQL-инъекции для СУБД MySQL. Она предназначена для внедрения в уязвимый SQL-запрос с целью заставить базу данных выдать сообщение об ошибке, содержащее полезные данные. Подобные конструкции часто используются пентестерами и злоумышленниками для извлечения информации из базы данных, когда прямой вывод данных невозможен.

В запросе пользователя фигурирует вариант с числом 4442, но суть от этого не меняется: это попытка эксплуатации функции EXTRACTVALUE() через внедрение в параметр, который не проходит должную фильтрацию. Давайте разберём, как это работает и почему это опасно.

Как работает EXTRACTVALUE в MySQL

Функция EXTRACTVALUE() принимает два строковых аргумента: фрагмент XML-разметки и выражение XPath. Она возвращает текст (CDATA) первого текстового узла, который является дочерним для элемента или элементов, соответствующих XPath-выражению. Например, запрос:

SELECT EXTRACTVALUE('<a>текст</a>', '/a');

вернёт текст. Однако если XPath-выражение некорректно, MySQL генерирует ошибку XPATH syntax error. Именно на этом строится атака: злоумышленник конструирует XPath так, чтобы в тексте ошибки отобразились данные из базы.

Разбор полезной нагрузки

Рассмотрим строку по частям:

  • %' — закрывающая кавычка (в URL-кодировке), которая завершает строковый литерал в уязвимом запросе.
  • AND EXTRACTVALUE(2015, CONCAT(0x7e, ((SELECT (ELT(2015=2015,1)))), 0x7e)) — вызов функции с двумя аргументами. Первый аргумент (2015) — произвольное число, которое будет использовано как XML-фрагмент. Второй аргумент — результат конкатенации символа ~ (0x7e), подзапроса и снова ~.
  • -- - — комментарий, который обрезает остаток оригинального SQL-запроса.

Подзапрос SELECT (ELT(2015=2015,1)) всегда возвращает 1, так как условие 2015=2015 истинно. Это тестовый пример: в реальной атаке вместо этого подзапроса подставляется выражение для извлечения данных, например, версии СУБД, имени базы или хешей паролей.

Функция CONCAT объединяет тильды и результат подзапроса в строку вида ~1~. Затем EXTRACTVALUE пытается интерпретировать эту строку как XPath-выражение. Поскольку строка не является валидным XPath, MySQL выбрасывает ошибку, в тексте которой фигурирует переданная строка. Таким образом, данные из подзапроса попадают в сообщение об ошибке, которое злоумышленник может прочитать.

Почему используется 0x7e?

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

Цели атаки

Error-based SQL-инъекции через EXTRACTVALUE позволяют извлекать произвольные данные из базы. В первую очередь злоумышленников интересует:

  • версия MySQL и операционной системы;
  • имя текущей базы данных и пользователя;
  • список таблиц и столбцов;
  • учётные данные пользователей (логины, хеши паролей);
  • персональные данные клиентов.

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

Пример уязвимого кода

Рассмотрим фрагмент на PHP, который может быть уязвим:

$id = $_GET['id'];
$query = "SELECT * FROM products WHERE id = '$id'";
$result = mysqli_query($link, $query);

Если параметр id не фильтруется, злоумышленник может передать строку 1' AND EXTRACTVALUE(4442,CONCAT(0x7e,((SELECT (ELT(4442=4442,1)))),0x7e))-- - и выполнить произвольный SQL-код.

Как защититься от SQL-инъекций

Основной метод защиты — использование подготовленных выражений (prepared statements) с параметризацией запросов. В PHP это делается через PDO или mysqli с плейсхолдерами. Например:

$stmt = $pdo->prepare('SELECT * FROM products WHERE id = :id');
$stmt->execute(['id' => $id]);

Дополнительные меры:

  • валидация и фильтрация всех входных данных (приведение к ожидаемому типу);
  • экранирование специальных символов с помощью mysqli_real_escape_string (но это не панацея);
  • использование ORM, которые автоматически параметризуют запросы;
  • ограничение прав пользователя базы данных (не использовать root для веб-приложений);
  • включение логирования и мониторинга ошибок СУБД;
  • регулярное обновление MySQL и веб-приложений.

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

Заключение

Строка с EXTRACTVALUE — это не случайный набор символов, а тщательно сконструированная полезная нагрузка для эксплуатации уязвимости SQL-инъекции. Понимание принципов её работы помогает разработчикам и специалистам по безопасности лучше защищать свои приложения. Если вы обнаружили подобные строки в логах, это сигнал о попытке взлома. Немедленно проверьте свой код на наличие уязвимостей и внедрите практики безопасной разработки.

Источники