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

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

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

Как работает error-based инъекция через EXTRACTVALUE

Рассмотрим классический пример, который часто встречается в отчётах по пентесту. Предположим, есть уязвимый параметр id в URL, и запрос строится так:

SELECT * FROM articles WHERE id = '$id'

Злоумышленник может передать следующее значение:

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

Разберём по частям:

  • 1' AND — закрывает предыдущее условие и добавляет новое.
  • EXTRACTVALUE(5089, CONCAT(...)) — вызывает функцию с первым аргументом 5089 (произвольное число, может быть любым) и вторым аргументом — результатом CONCAT.
  • CONCAT(0x7e, (SELECT (ELT(5089=5089,1))), 0x7e) — объединяет тильды (~) с результатом подзапроса. В данном случае ELT(5089=5089,1) всегда возвращает 1, так как условие истинно. Это простейшая проверка, но вместо 1 может быть любой другой запрос, например, (SELECT password FROM users LIMIT 1).
  • -- - — комментарий, обрезающий остаток исходного запроса.

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

Почему это опасно?

Error-based инъекции через EXTRACTVALUE позволяют атакующему:

  • Извлекать имена таблиц и столбцов из системной схемы information_schema.
  • Получать логины, пароли, номера банковских карт и другие конфиденциальные данные.
  • Обходить фильтрацию, если она настроена только на сигнатуры UNION-инъекций.

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

Примеры полезной нагрузки

Вот несколько вариантов эксплуатации, которые встречаются в реальных атаках:

  1. Получение версии MySQL:
    AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e))
  2. Чтение имени текущей базы данных:
    AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT database()), 0x7e))
  3. Извлечение пароля пользователя:
    AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT password FROM users LIMIT 1), 0x7e))

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

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

Основная причина уязвимости — передача пользовательского ввода в SQL-запрос без должной обработки. Вот ключевые меры защиты:

  • Используйте подготовленные выражения (prepared statements). Это самый надёжный способ: параметры запроса передаются отдельно от SQL-кода, и внедрение становится невозможным.
  • Применяйте ORM. Современные ORM-библиотеки автоматически экранируют параметры.
  • Отключите вывод ошибок СУБД на продакшене. Сообщения об ошибках не должны попадать в ответы сервера. Логируйте их, но не показывайте пользователю.
  • Ограничьте права пользователя БД. Не давайте приложению доступ к information_schema и лишним таблицам.
  • Используйте WAF. Веб-приложения-экраны могут блокировать подозрительные конструкции, но не полагайтесь только на них.
  • Регулярно обновляйте СУБД и фреймворки. В новых версиях MySQL некоторые функции могут быть удалены или изменены, что снижает риск.

Заключение

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

Если вы нашли такую уязвимость в своём приложении, немедленно проведите аудит кода и обновите методы работы с базой данных. Безопасность — это процесс, а не разовое действие.

Источники