Что это за строка с EXTRACTVALUE?

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

Внешне это может показаться бессмысленным набором символов, но за ним стоит чёткая логика: заставить сервер базы данных вернуть в сообщении об ошибке результат выполнения вложенного запроса. Именно поэтому такой тип инъекции называется error-based (основанный на ошибках).

Как работает эта инъекция?

Разберём по частям. Предположим, что исходный SQL-запрос, который выполняет уязвимое веб-приложение, выглядит примерно так:

SELECT * FROM users WHERE id = 'ВВОД'

Злоумышленник подставляет вместо ВВОД строку %" AND EXTRACTVALUE(...)-- -. В итоге запрос принимает вид:

SELECT * FROM users WHERE id = '%" AND EXTRACTVALUE(2649,CONCAT(0x7e,((SELECT (ELT(2649=2649,1)))),0x7e))-- -'

Символ %" в начале нужен для экранирования кавычки и комментария, а -- - в конце — чтобы закомментировать остаток оригинального запроса. Основная нагрузка ложится на функцию EXTRACTVALUE.

Функция EXTRACTVALUE

В MySQL (до версии 8.0.17) существовала функция EXTRACTVALUE(XML, XPath). Она извлекает значение из XML-документа по заданному XPath-выражению. Если XPath-выражение некорректно или возвращает не скалярное значение, функция генерирует ошибку. Именно эту особенность используют для error-based инъекций: в тексте ошибки MySQL выводит часть переданного XPath, что позволяет извлечь данные.

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

Конструкция ELT и условие 2649=2649

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

В реальной атаке вместо ELT(2649=2649,1) могла бы стоять подзапрос, извлекающий, например, имя пользователя или хеш пароля. Например: (SELECT password FROM users LIMIT 1). Тогда в ошибке MySQL отобразилось бы значение пароля, обрамлённое тильдами.

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

Функция CONCAT объединяет строки. Тильды (0x7e) добавляются, чтобы отделить полезную нагрузку от служебного текста ошибки. Когда MySQL выдаёт ошибку вида XPATH syntax error: '~1~', злоумышленник легко извлекает содержимое между тильдами. Без них было бы сложно понять, где начинаются и заканчиваются данные.

Почему это опасно?

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

Уязвимыми оказываются приложения, которые:

  • подставляют пользовательский ввод в SQL-запросы без параметризации;
  • выводят сообщения об ошибках базы данных прямо на страницу;
  • используют устаревшие версии MySQL, где EXTRACTVALUE ещё доступна.

Как защититься?

Главная мера — использовать параметризованные запросы (prepared statements), при которых пользовательский ввод никогда не интерпретируется как SQL-код. Дополнительно рекомендуется:

  1. Отключить вывод ошибок СУБД в production-окружении.
  2. Обновить MySQL до версии 8.0.17 или выше, где EXTRACTVALUE удалена (заменена на JSON_EXTRACT и другие функции).
  3. Использовать ORM или query builder, которые экранируют входные данные.
  4. Проводить регулярные сканирования уязвимостей и пентесты.

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

Заключение

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

Источники