Что такое EXTRACTVALUE в MySQL?

Функция EXTRACTVALUE — это встроенная функция MySQL, предназначенная для извлечения текстового содержимого из XML-фрагмента с помощью выражения XPath. Синтаксис: EXTRACTVALUE(XML_frag, XPath_expr). Она возвращает текст первого узла, соответствующего XPath. Например, SELECT EXTRACTVALUE('<a><b>текст</b></a>', '/a/b') вернёт «текст». Эта функция часто используется для работы с XML-данными, хранящимися в колонках таблиц.

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

Разбор полезной нагрузки: " OR EXTRACTVALUE(5018,CONCAT(0x7e,((SELECT (ELT(5018=5018,1)))),0x7e))-- -

Данная строка — типичный пример error-based SQL-инъекции. Рассмотрим её по частям:

  • " — закрывающая кавычка для завершения строкового литерала в уязвимом запросе.
  • OR — логический оператор, который делает условие всегда истинным, если подзапрос вернёт результат.
  • EXTRACTVALUE(5018, CONCAT(...)) — вызов функции с заведомо некорректным XPath, чтобы вызвать ошибку.
  • CONCAT(0x7e, ((SELECT (ELT(5018=5018,1)))), 0x7e) — конкатенация тильды (0x7e — шестнадцатеричный код символа ~), результата подзапроса и снова тильды.
  • ELT(5018=5018,1) — функция ELT возвращает N-й элемент из списка. Здесь 5018=5018 — истина (1), поэтому ELT(1, 1) вернёт «1». Это простейшая проверка, которая всегда возвращает 1.
  • -- - — комментарий, отсекающий остальную часть оригинального SQL-запроса.

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

Зачем нужен CONCAT и тильды?

Тильды (0x7e) используются как маркеры, чтобы облегчить парсинг вывода ошибки. Сообщение об ошибке MySQL обычно имеет формат: XPATH syntax error: '...'. Вставив тильды по краям, атакующий легко выделяет полезную нагрузку между ними. CONCAT объединяет маркеры и результат подзапроса в одну строку, которая затем передаётся в EXTRACTVALUE как XPath. Поскольку XPath начинается с тильды, парсер MySQL сразу выдаёт ошибку, но перед этим вычисляет все аргументы, включая подзапрос.

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

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

Важно: начиная с MySQL 5.7.8 функция EXTRACTVALUE помечена как устаревшая (deprecated), а в MySQL 8.0 удалена. Однако многие устаревшие системы всё ещё используют её, что делает эту технику актуальной для пентеста.

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

Основные меры защиты:

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

Также рекомендуется проводить аудит кода и пентесты для выявления уязвимостей.

Заключение

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

Источники