Что такое EXTRACTVALUE и при чём тут SQL-инъекции
Функция EXTRACTVALUE() в MySQL предназначена для работы с XML-данными. Она принимает два строковых аргумента: фрагмент XML-разметки и XPath-выражение (локатор). Функция возвращает текст (CDATA) первого текстового узла, который является дочерним для элемента или элементов, соответствующих XPath-выражению. Например, запрос SELECT EXTRACTVALUE('<a>текст</a>', '/a') вернёт строку «текст».
Однако эта безобидная на первый взгляд функция стала одним из классических инструментов для проведения error-based SQL-инъекций в СУБД MySQL. Причина в том, что при передаче некорректного XPath-выражения функция генерирует ошибку, в тексте которой отображается переданное значение. Злоумышленники научились использовать это для извлечения произвольных данных из базы через сообщения об ошибках.
Разбор конкретного запроса
Рассмотрим строку, которая стала предметом этого разбора:
')) AND EXTRACTVALUE(8636,CONCAT(0x7e,((SELECT (ELT(8636=8636,1)))),0x7e))-- -
Это типичная полезная нагрузка (payload) для проверки наличия error-based SQL-инъекции. Разберём её по частям:
- ')) — закрывающие кавычка и скобка. Они нужны, чтобы «закрыть» оригинальный SQL-запрос, в который внедряется код. Если приложение подставляет пользовательский ввод внутрь запроса с кавычками и скобками, эти символы позволяют выйти за пределы строкового литерала.
- AND EXTRACTVALUE(8636, ...) — добавляет условие в запрос. Число 8636 здесь — произвольный идентификатор, не влияющий на логику, но необходимый для синтаксиса функции.
- CONCAT(0x7e, ((SELECT (ELT(8636=8636,1)))), 0x7e) — формирует строку для XPath. 0x7e — это шестнадцатеричный код символа «~» (тильда). Внутри выполняется подзапрос
SELECT ELT(8636=8636,1). Функция ELT возвращает N-й элемент из списка; условие 8636=8636 всегда истинно, поэтому возвращается 1. Фактически это заглушка, демонстрирующая возможность выполнения подзапросов. - -- - — комментарий, который отсекает оставшуюся часть оригинального SQL-запроса, чтобы не возникло синтаксической ошибки.
Если запрос уязвим, MySQL попытается вычислить EXTRACTVALUE с аргументом, начинающимся с тильды, что не является корректным XPath. В результате возникнет ошибка вида XPATH syntax error: '~1~'. Именно этот текст, содержащий результат подзапроса, увидит атакующий в ответе сервера.
Почему это работает: механизм error-based инъекции
Error-based SQL-инъекция — это метод, при котором злоумышленник заставляет базу данных выдать конфиденциальные сведения прямо в сообщении об ошибке. В MySQL для этого traditionally использовались функции EXTRACTVALUE() и UPDATEXML(). Обе они при некорректном XPath возвращают ошибку, включающую переданную строку.
Атакующий может подставить в CONCAT не просто число, а, например, результат подзапроса (SELECT version()) или (SELECT password FROM users LIMIT 1). Тогда в тексте ошибки отобразится версия СУБД или хеш пароля. Поскольку длина сообщения ограничена (около 32 символов), данные извлекаются посимвольно с помощью функций SUBSTRING, MID или LIMIT.
Важно отметить, что начиная с MySQL 5.7.9 функция EXTRACTVALUE была объявлена устаревшей, а в MySQL 8.0 удалена. Однако множество legacy-систем до сих пор работают на старых версиях, что делает эту технику актуальной.
Как распознать попытку эксплуатации
В логах веб-сервера или WAF можно заметить характерные признаки:
- Наличие в параметрах запросов функций EXTRACTVALUE, UPDATEXML, CONCAT с шестнадцатеричными последовательностями (0x7e).
- Комбинации закрывающих кавычек и скобок:
')),")),')и т.п. - Использование комментариев
-- -,#,/* */для обрыва запроса. - Подзапросы с ELT, IF, CASE, направленные на извлечение метаданных.
Если вы обнаружили такие строки в логах, это сигнал о попытке взлома. Необходимо срочно проверить код приложения на наличие уязвимостей.
Меры защиты от error-based SQL-инъекций
Основной способ предотвращения — использование параметризованных запросов (prepared statements). При этом пользовательские данные передаются отдельно от SQL-кода и не могут изменить структуру запроса. Даже если злоумышленник введёт ')) AND EXTRACTVALUE(...)-- -, это будет воспринято как обычная строка.
Дополнительные меры:
- Экранирование специальных символов с помощью функций драйвера (mysqli_real_escape_string, PDO::quote).
- Валидация и фильтрация входных данных по белому списку.
- Отключение вывода подробных ошибок СУБД в production-окружении. Ошибки должны логироваться, а пользователь видеть общее сообщение.
- Использование WAF (Web Application Firewall) для блокировки подозрительных запросов.
- Регулярное обновление MySQL до версий, где уязвимые функции удалены или исправлены.
- Проведение аудита кода и пентестов.
Помните: безопасность — это процесс, а не разовое действие. Даже одна неэкранированная кавычка может привести к полной компрометации базы данных.
Заключение
Запрос ')) AND EXTRACTVALUE(8636,CONCAT(0x7e,((SELECT (ELT(8636=8636,1)))),0x7e))-- - — это учебный пример error-based SQL-инъекции через функцию EXTRACTVALUE в MySQL. Он демонстрирует, как злоумышленники используют особенности обработки ошибок для извлечения данных. Понимание этого механизма позволяет разработчикам и администраторам своевременно выявлять и устранять уязвимости, а также выстраивать надёжную защиту веб-приложений.
Комментарии
—Войдите, чтобы оставить комментарий