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

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

Классический пример, который часто встречается в отчётах по пентесту, выглядит так:

` AND EXTRACTVALUE(9128,CONCAT(0x7e,((SELECT (ELT(9128=9128,1)))),0x7e))-- -

Этот запрос внедряется в уязвимый параметр, например, в строку URL или поле формы. Давайте разберём его по частям.

Разбор вредоносного запроса

1. Обратная кавычка и логика AND

Символ ` (обратная кавычка) часто используется для экранирования имён таблиц или столбцов в MySQL. Злоумышленник ставит его, чтобы разорвать исходный SQL-запрос и добавить своё условие. Конструкция AND позволяет присоединить дополнительное выражение, которое выполнится, только если предыдущее истинно.

2. Функция EXTRACTVALUE(9128, ...)

Первый аргумент — 9128 — это произвольное число, которое не является корректным XML-документом. Второй аргумент — XPath-выражение, которое формируется через CONCAT. Поскольку первый аргумент не XML, MySQL выдаст ошибку. Но хитрость в том, что в тексте ошибки будет отображён результат вычисления второго аргумента.

3. CONCAT и ELT

CONCAT(0x7e, ((SELECT (ELT(9128=9128,1)))), 0x7e) — здесь 0x7e — это шестнадцатеричное представление символа ~ (тильда). Он используется как маркер, чтобы легко найти полезную нагрузку в сообщении об ошибке. Функция ELT(9128=9128,1) возвращает 1, если условие 9128=9128 истинно (а это всегда так). Фактически это заглушка, но в реальной атаке вместо ELT может быть подзапрос, извлекающий данные, например, (SELECT version()).

4. Комментарий -- -

Два дефиса и пробел (или дефис) — это комментарий в SQL, который отсекает оставшуюся часть оригинального запроса. Это позволяет внедрить произвольный код, не нарушая синтаксис.

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

MySQL при вызове EXTRACTVALUE с некорректным XML-документом генерирует ошибку вида: XPATH syntax error: '~результат~'. Злоумышленник помещает в XPath-выражение подзапрос, который возвращает нужные данные. Например:

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

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

Пример реальной эксплуатации

Предположим, есть уязвимый скрипт: SELECT * FROM users WHERE id = '$id'. Злоумышленник передаёт в параметр id следующее:

1' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT table_name FROM information_schema.tables LIMIT 1), 0x7e))-- -

В ответе придёт ошибка с названием первой таблицы. Перебирая LIMIT, можно получить список всех таблиц, а затем и столбцов.

Меры защиты от SQL-инъекций

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

  • Использовать подготовленные выражения (prepared statements) с параметризацией запросов. Это самый надёжный способ.
  • Экранировать все пользовательские данные с помощью функций вроде mysqli_real_escape_string или PDO::quote.
  • Ограничить права пользователя БД, чтобы даже при успешной инъекции нельзя было прочитать системные таблицы.
  • Включить логирование ошибок и не выводить их пользователю — это затруднит эксплуатацию error-based инъекций.
  • Регулярно обновлять СУБД и использовать WAF (Web Application Firewall).

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

Заключение

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

Источники