Что такое EXTRACTVALUE и при чём тут SQL-инъекции?

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

Суть атаки: если злоумышленник может внедрить произвольный SQL-код в запрос, он вызывает EXTRACTVALUE с заведомо некорректным XPath, содержащим результат подзапроса. MySQL генерирует ошибку, в тексте которой отображается переданное значение. Так злоумышленник получает данные из базы (версию СУБД, имена таблиц, логины, пароли) прямо в сообщении об ошибке.

Разбор конкретного payload'а

Рассмотрим строку из запроса: ` AND EXTRACTVALUE(7730,CONCAT(0x7e,((SELECT (ELT(7730=7730,1)))),0x7e))-- -. Это классический пример error-based инъекции через EXTRACTVALUE.

  • ` — обратная кавычка, закрывающая предполагаемое строковое значение в уязвимом параметре.
  • AND — логический оператор, присоединяющий вредоносное условие.
  • EXTRACTVALUE(7730, ...) — первый аргумент — произвольное число (7730), второй — XPath-выражение, которое заведомо вызовет ошибку.
  • CONCAT(0x7e, ((SELECT (ELT(7730=7730,1)))), 0x7e) — формирует строку, состоящую из символа ~ (0x7e), результата подзапроса и ещё одного ~. Подзапрос SELECT (ELT(7730=7730,1)) возвращает 1, так как условие 7730=7730 истинно. ELT(N, str1, str2, ...) возвращает N-ю строку из списка; здесь N=1, поэтому возвращается 1.
  • -- - — комментарий, обрезающий остаток оригинального запроса.

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

Почему это работает?

Функция EXTRACTVALUE при обнаружении недопустимого символа в XPath-выражении генерирует ошибку, в тексте которой указывает проблемный фрагмент. Злоумышленник конкатенирует к этому фрагменту данные, полученные из подзапроса. Таким образом, содержимое базы данных «утекает» через сообщение об ошибке, которое часто отображается на странице или возвращается в HTTP-ответе.

Важно: для успешной эксплуатации приложение должно выводить ошибки СУБД пользователю. В противном случае атака не сработает.

Этот метод относится к классу error-based SQL-инъекций и часто используется, когда другие техники (UNION, blind) недоступны или менее удобны.

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

С помощью EXTRACTVALUE можно получить практически любую информацию, которую возвращает подзапрос:

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

Ограничение — длина выводимой строки. MySQL обрезает сообщение об ошибке, поэтому длинные значения приходится извлекать по частям, используя SUBSTRING и LIMIT.

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

Основной метод — не допускать попадания пользовательского ввода в SQL-запрос без обработки. Рекомендации:

  1. Используйте параметризованные запросы (prepared statements). Это самый надёжный способ, так как данные и код разделяются на уровне драйвера.
  2. Применяйте ORM. Современные ORM (Hibernate, Entity Framework, Eloquent) автоматически экранируют параметры.
  3. Валидируйте входные данные. Если параметр ожидается числовым, приводите его к числу; если строковым — ограничивайте допустимые символы.
  4. Отключайте вывод ошибок СУБД в production. Настройте display_errors = Off в PHP или используйте кастомные страницы ошибок. Это лишает атакующего обратной связи.
  5. Ограничьте права пользователя БД. Не используйте root для веб-приложений; давайте только необходимые привилегии.
  6. Установите WAF (Web Application Firewall). Он может блокировать подозрительные запросы, содержащие EXTRACTVALUE, CONCAT с 0x7e и т.п.

Также рекомендуется регулярно обновлять СУБД и фреймворки — в новых версиях некоторые функции могут быть удалены или изменены для снижения рисков.

Заключение

EXTRACTVALUE — удобная функция для работы с XML, но при небрежном обращении с пользовательским вводом она превращается в инструмент атаки. Error-based SQL-инъекции через EXTRACTVALUE позволяют быстро извлекать данные из базы, если приложение выводит ошибки. Единственная надёжная защита — параметризация запросов и сокрытие деталей ошибок от конечного пользователя.

Источники