Что такое SQL-инъекция через extractvalue?
SQL-инъекция остаётся одной из самых опасных уязвимостей веб-приложений. Согласно OWASP Top 10, она стабильно входит в список критических рисков. Одним из методов эксплуатации является error-based SQL-инъекция, при которой злоумышленник заставляет базу данных возвращать данные в сообщениях об ошибках. Функция extractvalue в MySQL часто используется для таких атак.
В запросе пользователя: " AND EXTRACTVALUE(3300,CONCAT(0x7e,((SELECT (ELT(3300=3300,1)))),0x7e))-- - — демонстрируется классический пример error-based инъекции. Давайте разберём его по частям.
Синтаксис и назначение функции extractvalue
Функция EXTRACTVALUE(XML_fragment, XPath_expression) извлекает значение из XML-строки по заданному XPath-выражению. Если XPath-выражение некорректно, MySQL генерирует ошибку, которая включает переданный фрагмент. Это и используется для вывода данных.
В нашем примере:
- 3300 — произвольное число, передаваемое как XML-фрагмент (не является корректным XML, что вызовет ошибку).
- CONCAT(0x7e, ((SELECT (ELT(3300=3300,1)))), 0x7e) — формирует строку, начиная и заканчивая тильдой (0x7e). Внутри — подзапрос, возвращающий результат выражения
ELT(3300=3300,1).
Разбор подзапроса ELT(3300=3300,1)
ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Если N=1, возвращается первая строка. Выражение 3300=3300 всегда истинно (1), поэтому ELT(1,1) вернёт 1. Это простейший пример, но на практике вместо 1 подставляются имена таблиц, колонок или другие данные.
Таким образом, CONCAT соберёт строку вида ~1~. При вызове EXTRACTVALUE с некорректным XPath (например, просто числом 3300) MySQL выдаст ошибку: XPATH syntax error: '~1~'. В этом сообщении и утечёт результат подзапроса.
Как это работает на практике
Предположим, есть уязвимый параметр id в URL: http://example.com/product.php?id=1. Злоумышленник может подставить:
1 AND EXTRACTVALUE(3300,CONCAT(0x7e,((SELECT version())),0x7e))-- -
В ответе сервера появится ошибка с версией MySQL. Аналогично можно извлечь имена таблиц, колонок, логины и пароли.
В нашем примере с ELT(3300=3300,1) демонстрируется базовый тест на возможность инъекции. Если приложение возвращает ошибку с ~1~, значит, оно уязвимо.
Пошаговый механизм атаки
- Злоумышленник находит параметр, передаваемый в SQL-запрос без должной фильтрации.
- Внедряет конструкцию с EXTRACTVALUE, используя CONCAT для формирования строки с данными.
- СУБД выполняет запрос, вызывает ошибку и возвращает её текст клиенту (если вывод ошибок включён).
- Атакующий читает данные из сообщения об ошибке.
- Меняя подзапрос, извлекает любую информацию из базы.
Меры защиты от error-based SQL-инъекций
Чтобы предотвратить такие атаки, необходимо:
- Использовать подготовленные выражения (prepared statements) с параметризацией запросов. Это самый надёжный способ.
- Отключить вывод подробных ошибок в production-окружении. Ошибки должны логироваться, а пользователь видеть общее сообщение.
- Применять ORM (например, Hibernate, Entity Framework), которые автоматически экранируют опасные символы.
- Проводить валидацию входных данных на стороне сервера, отклоняя подозрительные символы (кавычки, комментарии, ключевые слова SQL).
- Регулярно обновлять СУБД и использовать WAF (Web Application Firewall) для фильтрации трафика.
Важно понимать, что экранирование спецсимволов не всегда спасает: в некоторых конфигурациях MySQL функции вроде extractvalue могут быть вызваны даже внутри строковых литералов.
Распространённые ошибки при защите
Многие разработчики полагаются только на mysql_real_escape_string, но это не защищает от инъекций в числовых параметрах. Также опасно использовать динамическое конструирование SQL без белого списка допустимых значений.
Ещё одна ошибка — включённый режим display_errors на боевом сервере. Это прямо помогает атакующему получать данные через сообщения об ошибках.
Заключение
Запрос с EXTRACTVALUE — это типичный пример error-based SQL-инъекции, эксплуатирующей особенности MySQL. Понимание механизма помогает разработчикам и специалистам по безопасности правильно выстраивать защиту. Главный вывод: никогда не доверяйте пользовательскому вводу и всегда используйте параметризованные запросы.
Если вы тестируете своё приложение на уязвимости, помните о законности: проводите такие проверки только на собственных системах или с письменного разрешения владельца.
Комментарии
—Войдите, чтобы оставить комментарий