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

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

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

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

Механизм основан на том, что СУБД MySQL при определённых условиях выводит в сообщении об ошибке результат выполнения вложенного запроса. Рассмотрим по частям:

  • %"))) — это часть исходного запроса, которая «ломает» его синтаксис, закрывая кавычки и скобки. Символ % часто используется в LIKE-запросах, а "))) — попытка закрыть строковый литерал и скобки, чтобы внедрить свой код.
  • AND EXTRACTVALUE(6676,CONCAT(0x7e,((SELECT (ELT(6676=6676,1)))),0x7e)) — это и есть полезная нагрузка. Функция EXTRACTVALUE получает два аргумента: первый — число 6676 (может быть любым), второй — результат CONCAT, который объединяет тильду (0x7e — шестнадцатеричный код символа ~), результат подзапроса и ещё одну тильду.
  • SELECT (ELT(6676=6676,1)) — это подзапрос, который возвращает 1, если условие 6676=6676 истинно. В реальной атаке вместо этого условия может быть любой запрос к базе, например, извлечение имени пользователя или хеша пароля.
  • -- - — комментарий, который отсекает оставшуюся часть оригинального SQL-запроса, чтобы он не вызвал синтаксическую ошибку.

Когда MySQL выполняет EXTRACTVALUE с аргументом, содержащим символ ~ (тильда), функция пытается интерпретировать его как XPath. Поскольку это невалидный XPath, генерируется ошибка вида XPATH syntax error: '~1~'. В этом сообщении и оказывается результат подзапроса — в примере это 1. Если вместо ELT(6676=6676,1) подставить, например, (SELECT version()), то в ошибке отобразится версия MySQL. Так злоумышленник может пошагово извлекать любые данные: имена таблиц, столбцов, логины, пароли.

Зачем используется ELT и условие 6676=6676?

Конструкция ELT(6676=6676,1) — это простейший способ вернуть константу 1. Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Если N=1, возвращается первая строка. В данном случае 6676=6676 — это выражение, которое всегда истинно (равно 1), поэтому ELT(1,1) вернёт 1. Это нужно для демонстрации работоспособности инъекции: если приложение уязвимо, в ответе появится ошибка с тильдами и единицей. В реальной атаке вместо этого примитивного условия подставляют подзапросы, извлекающие ценную информацию.

Число 6676 в первом аргументе EXTRACTVALUE может быть любым — оно не влияет на результат, но иногда используется для обхода простых фильтров. Главное — второй аргумент, который содержит вредоносный XPath.

Почему это опасно и как защититься

Error-based SQL-инъекции через EXTRACTVALUE (а также через UPDATEXML) — один из самых быстрых способов получения данных из уязвимой базы MySQL. Они не требуют слепого перебора и часто срабатывают даже при минимальном выводе ошибок. Основная причина уязвимости — недостаточная фильтрация пользовательского ввода и конкатенация SQL-запросов вместо параметризации.

Чтобы защититься, необходимо:

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

Важно понимать, что EXTRACTVALUE — это лишь инструмент. Сама по себе функция не является уязвимостью; уязвимость возникает, когда злоумышленник может внедрить произвольный SQL-код в запрос. Поэтому главный совет: никогда не доверяйте пользовательскому вводу и всегда используйте параметризованные запросы.

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

Вместо конкатенации:

$query = "SELECT * FROM users WHERE name = '" . $_GET['name'] . "'";

Используйте подготовленные выражения:

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

Такой подход полностью исключает возможность SQL-инъекции, включая error-based через EXTRACTVALUE.

Заключение

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

Источники