Что такое EXTRACTVALUE?
Функция EXTRACTVALUE — это встроенная функция MySQL (и некоторых других СУБД), предназначенная для извлечения данных из XML-документов с помощью языка XPath. Она принимает два строковых аргумента: фрагмент XML-разметки и выражение XPath (локатор). Функция возвращает текст (CDATA) первого текстового узла, который является дочерним по отношению к элементу или элементам, соответствующим XPath-выражению.
В контексте информационной безопасности EXTRACTVALUE приобрела дурную славу как инструмент для проведения error-based SQL-инъекций. Злоумышленники используют её способность генерировать ошибки, содержащие результаты выполнения вложенных SQL-запросов, что позволяет извлекать данные из базы.
Разбор конкретного запроса
Рассмотрим запрос, который часто встречается в отчётах об уязвимостях и на форумах пентестеров:
) AND EXTRACTVALUE(6668,CONCAT(0x7e,((SELECT (ELT(6668=6668,1)))),0x7e))-- -
Этот фрагмент — классический пример внедрения в параметр, который передаётся в SQL-запрос. Давайте разберём его по частям:
- ) — закрывает ранее открытую скобку в исходном запросе, чтобы внедрение было синтаксически корректным.
- AND — логический оператор, присоединяющий наше условие к оригинальному запросу.
- EXTRACTVALUE(6668, CONCAT(...)) — вызов функции EXTRACTVALUE. Первый аргумент — произвольное число (6668), которое не является корректным XML. Это гарантирует, что функция вызовет ошибку.
- CONCAT(0x7e, ((SELECT (ELT(6668=6668,1)))), 0x7e) — конкатенация символа тильды (~, код 0x7e), результата подзапроса и ещё одной тильды. Тильды используются как маркеры, чтобы облегчить поиск вывода в сообщении об ошибке.
- SELECT (ELT(6668=6668,1)) — подзапрос, который возвращает 1, если условие 6668=6668 истинно. ELT — функция, возвращающая N-й элемент из списка; здесь список состоит из одного элемента 1. Фактически это проверка истинности, которая всегда возвращает 1.
- -- - — комментарий, который отсекает оставшуюся часть оригинального SQL-запроса, чтобы избежать синтаксических ошибок.
При выполнении этого кода MySQL попытается обработать EXTRACTVALUE с некорректным XML и сгенерирует ошибку, в тексте которой будет содержаться результат CONCAT, то есть ~1~. Именно так злоумышленник может узнать значение, возвращаемое подзапросом.
Как работает error-based SQL-инъекция через EXTRACTVALUE?
Механизм основан на том, что СУБД при ошибке в функции EXTRACTVALUE выводит в сообщении об ошибке переданный ей XPath-выражение. Если в это выражение подставить результат другого SQL-запроса, то этот результат окажется в тексте ошибки, который затем отображается пользователю (или сохраняется в логах).
Типичный сценарий атаки:
- Злоумышленник находит параметр, уязвимый для SQL-инъекции.
- Внедряет конструкцию с EXTRACTVALUE, где второй аргумент содержит CONCAT с полезной нагрузкой.
- СУБД выполняет подзапрос, получает данные (например, версию БД, имя пользователя, хеши паролей).
- Эти данные попадают в сообщение об ошибке, которое видит атакующий.
Важно отметить, что для успешной эксплуатации необходимо, чтобы приложение выводило ошибки СУБД пользователю. В противном случае атака может быть слепой (blind), и тогда используются другие техники.
Примеры полезных нагрузок
Вот несколько примеров, которые могут быть использованы в реальных атаках:
AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e))— получение версии MySQL.AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT user()), 0x7e))— получение текущего пользователя БД.AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT database()), 0x7e))— получение имени текущей базы данных.AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT table_name FROM information_schema.tables LIMIT 1), 0x7e))— извлечение имён таблиц.
Все эти конструкции работают по одному принципу: вызывают ошибку, содержащую нужные данные.
Ограничения и особенности
Функция EXTRACTVALUE имеет ограничение на длину выводимой строки — обычно 32 символа. Это связано с тем, что MySQL использует тип данных для сообщений об ошибках, ограниченный по длине. Поэтому для извлечения длинных значений (например, хешей паролей) приходится использовать посимвольное извлечение с помощью SUBSTRING и смещений.
Кроме того, начиная с MySQL 5.7.9, функция EXTRACTVALUE была объявлена устаревшей (deprecated), а в MySQL 8.0 удалена. Однако во многих старых системах она всё ещё доступна, что делает её популярной среди пентестеров.
Защита от SQL-инъекций через EXTRACTVALUE
Основной способ защиты — использование параметризованных запросов (prepared statements). Это полностью исключает возможность внедрения SQL-кода, так как данные передаются отдельно от структуры запроса. Дополнительные меры:
- Отключение вывода подробных сообщений об ошибках СУБД в production-окружении.
- Использование ORM и современных фреймворков, которые автоматически экранируют данные.
- Регулярное обновление СУБД до версий, где уязвимые функции удалены или исправлены.
- Применение веб-фаервола (WAF) для фильтрации подозрительных запросов.
Важно понимать, что EXTRACTVALUE — лишь один из многих инструментов в арсенале злоумышленников. Комплексный подход к безопасности приложений и баз данных — залог защиты от подобных атак.
Заключение
Запрос ) AND EXTRACTVALUE(6668,CONCAT(0x7e,((SELECT (ELT(6668=6668,1)))),0x7e))-- - — это типичный пример error-based SQL-инъекции, использующей функцию EXTRACTVALUE для извлечения данных через сообщения об ошибках. Понимание механики таких атак помогает разработчикам и специалистам по безопасности правильно выстраивать защиту и предотвращать утечки информации.
Комментарии
—Войдите, чтобы оставить комментарий