Что такое EXTRACTVALUE и почему она в запросе?

Встречая в логах или в поле ввода строку вида %")))) AND EXTRACTVALUE(4444,CONCAT(0x7e,((SELECT (ELT(4444=4444,1)))),0x7e))-- -, многие задаются вопросом: что это и какова её цель? Это классический пример error-based SQL-инъекции для СУБД MySQL. Она предназначена для извлечения данных из базы через вывод сообщения об ошибке.

Функция EXTRACTVALUE в MySQL используется для извлечения значения из XML-фрагмента по заданному XPath-выражению. Синтаксис: EXTRACTVALUE(XML_frag, XPath_expr). Если XPath-выражение некорректно, MySQL генерирует ошибку, которая включает в себя часть переданного XPath. Именно это свойство эксплуатируют злоумышленники.

Как работает инъекция с EXTRACTVALUE

Рассмотрим строку подробнее:

%")))) AND EXTRACTVALUE(4444,CONCAT(0x7e,((SELECT (ELT(4444=4444,1)))),0x7e))-- -

Она состоит из нескольких частей:

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

Когда MySQL выполняет EXTRACTVALUE с XPath-выражением, начинающимся с тильды (~), он выдаёт ошибку вида: XPATH syntax error: '~1~'. В этом сообщении и оказывается результат подзапроса. Так злоумышленник может извлекать произвольные данные, подставляя вместо ELT(4444=4444,1) другие SQL-выражения, например, версию СУБД, имена таблиц, пароли.

Пошаговый разбор полезной нагрузки

  1. Закрытие предыдущих конструкций: последовательность %")))) пытается завершить строковый литерал и несколько круглых скобок, чтобы обеспечить синтаксическую возможность внедрения.
  2. Логическое условие AND: если предыдущее выражение истинно, выполняется EXTRACTVALUE. Это позволяет обойти некоторые фильтры.
  3. Формирование XPath с ошибкой: CONCAT создаёт строку, начинающуюся с ~ (0x7e), за которой следует результат подзапроса, и заканчивается ~. XPath не допускает такого формата, поэтому MySQL генерирует ошибку.
  4. Извлечение данных: в тексте ошибки возвращается результат подзапроса. Меняя подзапрос, атакующий может получать любые данные из базы.
  5. Комментирование остатка: -- - превращает оставшуюся часть исходного запроса в комментарий, чтобы не нарушать синтаксис.

Цели и опасность error-based инъекций

Error-based SQL-инъекции считаются одними из самых опасных, так как позволяют быстро извлекать информацию без необходимости слепого перебора. Злоумышленник может:

  • Получить версию MySQL и другую служебную информацию.
  • Извлечь имена таблиц и столбцов из информационной схемы.
  • Похитить конфиденциальные данные: логины, пароли, персональные данные пользователей.
  • В некоторых случаях выполнить произвольные SQL-запросы, вплоть до модификации или удаления данных.

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

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

  1. Параметризованные запросы (prepared statements) — самый надёжный способ. Все современные языки программирования и драйверы БД поддерживают параметризацию, при которой данные передаются отдельно от SQL-кода.
  2. Экранирование специальных символов — если параметризация невозможна, используйте функции экранирования, предоставляемые драйвером БД (например, mysqli_real_escape_string в PHP).
  3. Валидация и фильтрация входных данных — проверяйте, что вводимые данные соответствуют ожидаемому формату (числа, email и т.д.).
  4. Ограничение прав пользователя БД — учётная запись, используемая веб-приложением, должна иметь минимально необходимые привилегии. Не давайте ей доступ к INFORMATION_SCHEMA без необходимости.
  5. Отключение вывода подробных ошибок — на продакшене не показывайте пользователям сообщения об ошибках БД. Это затруднит эксплуатацию error-based инъекций.
  6. Использование WAF — веб-application firewall может блокировать известные шаблоны атак, но не должен быть единственной мерой защиты.
  7. Регулярное обновление СУБД и фреймворков — закрывайте известные уязвимости.

Пример безопасного кода

Вместо конкатенации строк используйте параметризованные запросы. Например, на PHP с PDO:

$stmt = $pdo->prepare('SELECT * FROM users WHERE username = :username');
$stmt->execute(['username' => $userInput]);

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

Заключение

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

Источники