Что такое SQL-инъекция через EXTRACTVALUE?

SQL-инъекция — один из самых распространённых и опасных видов атак на веб-приложения. Злоумышленники внедряют вредоносный SQL-код в запросы, чтобы получить доступ к базе данных, изменить или удалить информацию. Одной из техник является использование функции EXTRACTVALUE в СУБД MySQL для извлечения данных через сообщения об ошибках. В запросе OR EXTRACTVALUE(9367,CONCAT(0x7e,((SELECT (ELT(9367=9367,1)))),0x7e))-- - как раз демонстрируется такой подход.

В этой статье мы детально разберём, как работает эта инъекция, какие функции задействованы и как защититься от подобных атак.

Разбор запроса OR EXTRACTVALUE(...)

Рассматриваемый запрос состоит из нескольких частей. Начнём с того, что OR — логический оператор, который добавляется к оригинальному условию, чтобы инъекция сработала, если исходное условие ложно. Далее идёт вызов функции EXTRACTVALUE(9367, CONCAT(...)). Эта функция предназначена для извлечения значения из XML-документа по заданному XPath-выражению. Однако при некорректном XPath она генерирует ошибку, содержащую переданные данные. Именно это и эксплуатируется.

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

Внутри CONCAT находится подзапрос SELECT (ELT(9367=9367,1)). Функция ELT возвращает N-й элемент из списка. Здесь 9367=9367 — всегда истинное условие, которое возвращает 1. Таким образом, ELT(1,1) вернёт строку '1'. Это простейший пример, демонстрирующий работу конструкции. В реальной атаке вместо 1 мог бы быть подзапрос, извлекающий имя пользователя, пароль или другую конфиденциальную информацию.

Завершающая часть -- - — это комментарий, который отсекает оставшуюся часть оригинального SQL-запроса, чтобы избежать синтаксических ошибок.

Как работает EXTRACTVALUE для извлечения данных?

Функция EXTRACTVALUE(XML_document, XPath_expression) анализирует XML и возвращает текст узла, соответствующего XPath. Если XML некорректен или XPath не соответствует ни одному узлу, MySQL выдаёт ошибку вида: XPATH syntax error: '...', где в кавычках может оказаться часть переданного XPath-выражения. Злоумышленник конструирует XPath так, чтобы в сообщение об ошибке попали нужные данные. Например, можно передать CONCAT(0x7e, (SELECT password FROM users LIMIT 1), 0x7e), и тогда в ошибке появится пароль, окружённый тильдами.

Этот метод относится к классу error-based SQL injection (инъекции на основе ошибок). Он удобен тем, что результат виден непосредственно в ответе сервера, без необходимости использовать слепые техники.

Пример практического использования

Предположим, есть уязвимый параметр id в URL: http://example.com/product.php?id=1. Оригинальный запрос: SELECT * FROM products WHERE id = 1. Злоумышленник подставляет:

1 OR EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e))-- -

В результате сервер вернёт ошибку, содержащую версию MySQL, например: XPATH syntax error: '~5.7.31~'. Аналогично можно извлечь имена таблиц, колонок, логины и пароли.

В нашем запросе используется ELT(9367=9367,1), что демонстрирует базовый принцип, но не несёт полезной нагрузки. Это, скорее, тестовый пример для проверки уязвимости.

Какие функции задействованы?

  • EXTRACTVALUE — извлекает значение из XML, но при ошибке выводит переданные данные.
  • CONCAT — объединяет строки, позволяет добавить разделители.
  • ELT — возвращает N-й элемент из списка; используется для формирования вывода.
  • SELECT — подзапрос для получения данных из БД.
  • 0x7e — шестнадцатеричный код символа ~, служит маркером.

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

Последствия успешной SQL-инъекции

Успешная эксплуатация уязвимости может привести к:

  • Утечке конфиденциальных данных (пароли, персональная информация).
  • Изменению или удалению данных.
  • Обходу аутентификации и авторизации.
  • Выполнению административных операций в базе данных.
  • В некоторых случаях — к выполнению команд на сервере.

Поэтому важно своевременно выявлять и устранять такие уязвимости.

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

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

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

Важно понимать, что никакая отдельная мера не даёт 100% гарантии, поэтому рекомендуется комбинировать подходы.

Заключение

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

Если вы нашли подобную уязвимость в своём приложении, немедленно устраните её и проведите аудит безопасности.

Источники