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

Функция ExtractValue в MySQL предназначена для извлечения данных из XML-документа по заданному XPath-выражению. Однако злоумышленники часто используют её для проведения так называемых error-based SQL-инъекций. Суть метода: при передаче некорректного XPath-выражения MySQL генерирует сообщение об ошибке, которое может содержать результат выполнения вложенного SQL-запроса. Это позволяет атакующему получать данные из базы, даже если приложение не выводит результаты запроса напрямую.

Рассмотрим типичный пример инъекции:

'))) AND EXTRACTVALUE(8768,CONCAT(0x7e,((SELECT (ELT(8768=8768,1)))),0x7e))-- -

Здесь злоумышленник внедряет вызов EXTRACTVALUE с заведомо некорректным XPath (начинается с символа ~, 0x7e). Внутри CONCAT выполняется подзапрос SELECT (ELT(8768=8768,1)), который возвращает 1. В результате MySQL выдаёт ошибку вида XPATH syntax error: '~1~', и атакующий видит результат выполнения подзапроса. Меняя условие внутри ELT, можно извлекать произвольные данные посимвольно.

Механизм работы error-based инъекции через ExtractValue

Функция EXTRACTVALUE(XML_document, XPath_expression) возвращает содержимое XML-узла, соответствующего XPath. Если XPath синтаксически неверен, MySQL выбрасывает ошибку. Ключевая особенность: в текст ошибки попадает часть переданного XPath. Это позволяет внедрить в XPath результат выполнения SQL-подзапроса, обёрнутый в специальные символы (например, ~), чтобы облегчить извлечение.

Пошагово атака выглядит так:

  1. Приложение принимает параметр, который подставляется в SQL-запрос без должной очистки.
  2. Атакующий добавляет конструкцию AND EXTRACTVALUE(...), чтобы выполнить свой подзапрос.
  3. Если исходный запрос был истинным, подзапрос выполняется, и MySQL возвращает ошибку с внедрёнными данными.
  4. Если исходный запрос ложный, функция может не выполниться, и ошибки не будет — это позволяет реализовать слепую инъекцию.

Для извлечения данных посимвольно используются функции вроде SUBSTRING, ASCII, а также условные выражения. Например, чтобы узнать имя пользователя, можно сравнивать ASCII-коды символов с помощью IF или CASE.

Пример извлечения имени базы данных

Допустим, атакующий хочет получить имя текущей базы данных. Он может использовать такой payload:

AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT database()), 0x7e))-- -

В ответе сервера появится ошибка: XPATH syntax error: '~имя_базы~'. Так злоумышленник узнаёт название базы.

Извлечение таблиц и колонок

Аналогично можно получить список таблиц из information_schema.tables:

AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT table_name FROM information_schema.tables WHERE table_schema=database() LIMIT 0,1), 0x7e))-- -

Меняя LIMIT, атакующий перебирает все таблицы. Затем подобным образом извлекаются имена колонок и данные.

Почему ExtractValue опасен и как его обнаружить

Основная опасность в том, что ошибки СУБД часто отображаются в браузере или логируются, что даёт атакующему обратную связь. Даже если приложение скрывает ошибки, они могут попадать в логи, доступные злоумышленнику. Кроме того, error-based инъекции работают быстрее, чем слепые, так как не требуют множественных запросов для каждого бита информации.

Обнаружить попытки эксплуатации можно по следующим признакам:

  • В логах веб-сервера появляются запросы с символами ~, EXTRACTVALUE, CONCAT, 0x7e.
  • В ответах сервера возникают ошибки MySQL с сообщениями XPATH syntax error.
  • Необычные параметры в GET/POST-запросах, содержащие кавычки, скобки, комментарии --.

Для автоматического выявления таких уязвимостей пентестеры используют SQL-инъекционные сканеры (sqlmap, OWASP ZAP), а также ручной анализ входных точек.

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

Главный способ защиты — использование параметризованных запросов (prepared statements). При этом данные передаются отдельно от SQL-кода, и внедрение функций вроде EXTRACTVALUE становится невозможным.

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

  • Валидация и фильтрация всех входных данных на стороне сервера.
  • Экранирование специальных символов, если параметризация невозможна.
  • Отключение вывода подробных ошибок СУБД в production-окружении.
  • Ограничение прав пользователя базы данных: не давать приложению доступ к information_schema без необходимости.
  • Регулярное обновление MySQL и использование WAF (Web Application Firewall) для блокировки подозрительных запросов.

Важно понимать, что EXTRACTVALUE — не единственная функция, используемая для error-based инъекций. Аналогично работают UPDATEXML, GTID_SUBSET, EXP и другие. Поэтому защита должна быть комплексной.

Заключение

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

Источники