Введение

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

Что такое ExtractValue и XPATH-инъекции

Функция EXTRACTVALUE в MySQL предназначена для извлечения значения из XML-документа по заданному XPath-выражению. Синтаксис: EXTRACTVALUE(XML_fragment, XPath_expression). Если XPath-выражение некорректно, MySQL возвращает ошибку с указанием проблемного фрагмента. Именно это свойство используется хакерами: они передают в функцию специально сформированную строку, содержащую результат подзапроса, и сервер выводит её в тексте ошибки.

Этот метод известен как error-based SQL injection via XPATH. Он позволяет обходить ограничения, когда приложение не выводит данные напрямую, но показывает сообщения об ошибках СУБД.

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

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

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

Внутри EXTRACTVALUE используется CONCAT для объединения символа ~ (0x7e) с результатом подзапроса. Подзапрос SELECT (ELT(5028=5028,1)) возвращает число 1, если условие 5028=5028 истинно. ELT — функция, возвращающая N-й элемент из списка; здесь список состоит из одного элемента «1». Таким образом, выражение всегда возвращает «1». Это упрощённый пример; на практике вместо ELT подставляют вызовы системных функций для извлечения имён таблиц, колонок или хешей паролей.

Когда MySQL выполняет EXTRACTVALUE с аргументом, содержащим символ ~, он пытается интерпретировать его как XPath. Поскольку ~ не является допустимым символом XPath, возникает ошибка: XPATH syntax error: '~1~'. В этом сообщении и утекает результат подзапроса.

Пример работы в реальных условиях

Предположим, уязвимый запрос выглядит так: SELECT * FROM users WHERE id = '$id'. Злоумышленник передаёт в параметр id строку 1')) AND EXTRACTVALUE(5028,CONCAT(0x7e,(SELECT database()),0x7e))-- -. После подстановки запрос становится:

SELECT * FROM users WHERE id = '1')) AND EXTRACTVALUE(5028,CONCAT(0x7e,(SELECT database()),0x7e))-- -'

База данных выполнит подзапрос, получит имя текущей БД, вставит его в XPath, и вернёт ошибку вида: XPATH syntax error: '~mydatabase~'. Так злоумышленник узнаёт имя базы данных.

Какие данные можно извлечь

С помощью этой техники атакующий может получить:

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

Ограничение — длина вывода в сообщении об ошибке (обычно около 32 символов), поэтому данные извлекаются по частям с использованием функций SUBSTRING или MID.

Меры защиты

Чтобы предотвратить подобные атаки, необходимо:

  1. Использовать подготовленные выражения (prepared statements) с параметризацией. Это самый надёжный способ, так как данные не попадают в текст SQL-запроса.
  2. Экранировать специальные символы при невозможности использовать параметризацию (например, через mysqli_real_escape_string).
  3. Отключить вывод ошибок СУБД на продакшене. Сообщения об ошибках должны логироваться, а пользователю показываться общая страница ошибки.
  4. Ограничить привилегии пользователя БД, от имени которого работает приложение. Не давайте ему доступ к information_schema без необходимости.
  5. Регулярно обновлять MySQL и использовать WAF для фильтрации подозрительных запросов.

Важно понимать, что error-based инъекции — лишь один из многих векторов. Комплексная защита включает валидацию всех входных данных, минимизацию прав и мониторинг аномалий.

Заключение

Полезная нагрузка )) AND EXTRACTVALUE(5028,CONCAT(0x7e,((SELECT (ELT(5028=5028,1)))),0x7e))-- - демонстрирует, как простая функция MySQL может стать инструментом для извлечения конфиденциальной информации. Понимание механизма работы таких атак помогает разработчикам и администраторам своевременно закрывать уязвимости и защищать данные пользователей.

Источники