Введение
Запрос %' AND EXTRACTVALUE(3619,CONCAT(0x7e,((SELECT (ELT(3619=3619,1)))),0x7e))-- - — это классический пример error-based SQL-инъекции в СУБД MySQL. Подобные конструкции используются злоумышленниками для извлечения данных из базы через сообщения об ошибках. В этой статье мы разберём, как работает каждый элемент payload, зачем нужны шестнадцатеричные префиксы и как защититься от таких атак.
Что такое error-based SQL-инъекция?
SQL-инъекция — это внедрение вредоносного SQL-кода в запрос через пользовательский ввод. При error-based атаке хакер заставляет базу данных вернуть данные в тексте ошибки. MySQL-функция EXTRACTVALUE() изначально предназначена для работы с XML: она извлекает значение из XML-строки по заданному XPath-выражению. Если XPath содержит недопустимые символы, MySQL генерирует ошибку, в которой отображается переданное значение. Это и позволяет вытащить результат подзапроса.
Синтаксис EXTRACTVALUE
EXTRACTVALUE(XML_фрагмент, XPath_выражение). Например, EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e)) вызовет ошибку вида XPATH syntax error: '~5.7.33~', где 0x7e — это тильда (~), служащая визуальным маркером для облегчения чтения.
Разбор payload по частям
Рассмотрим запрос детально:
%'— закрывает предыдущее строковое значение в уязвимом запросе и добавляет символ%для обхода фильтров (часто используется в LIKE-запросах).AND— логический оператор, присоединяющий наше условие.EXTRACTVALUE(3619, CONCAT(0x7e, ((SELECT (ELT(3619=3619,1)))), 0x7e))— вызов уязвимой функции.-- -— комментарий, обрезающий остаток оригинального SQL-запроса (пробел после двух дефисов обязателен в MySQL).
Первый аргумент: 3619
Число 3619 — произвольное целое. Оно не несёт смысловой нагрузки, но должно быть допустимым XML-фрагментом. Фактически это «заглушка», так как ошибка возникает на этапе вычисления XPath.
Второй аргумент: CONCAT(0x7e, ..., 0x7e)
Функция CONCAT склеивает строки. 0x7e — шестнадцатеричное представление символа ~ (тильда). Тильды обрамляют полезную нагрузку, чтобы в сообщении об ошибке было легко найти результат подзапроса. Без них данные сливались бы с текстом ошибки.
Подзапрос: SELECT (ELT(3619=3619,1))
ELT(N, строка1, строка2, ...) возвращает N-ю строку из списка. Выражение 3619=3619 всегда истинно (равно 1), поэтому ELT(1, 1) вернёт строку '1'. В данном случае это демонстрационный пример — в реальной атаке вместо 1 подставляется подзапрос, например (SELECT user()) или (SELECT password FROM users LIMIT 1).
Как это работает на практике
Предположим, уязвимый запрос выглядит так:
SELECT * FROM articles WHERE title LIKE '%ЗАПРОС%'
После подстановки payload запрос превращается в:
SELECT * FROM articles WHERE title LIKE '%%' AND EXTRACTVALUE(3619,CONCAT(0x7e,((SELECT (ELT(3619=3619,1)))),0x7e))-- -%'
MySQL выполняет EXTRACTVALUE, терпит неудачу и возвращает ошибку: XPATH syntax error: '~1~'. Злоумышленник видит результат выполнения подзапроса. Меняя содержимое ELT, можно извлекать имена таблиц, колонок, пароли и другую конфиденциальную информацию.
Почему это опасно?
Error-based инъекции позволяют получить данные напрямую, без слепого перебора. Это быстрее и надёжнее, чем boolean-based или time-based атаки. Особенно уязвимы приложения, которые выводят ошибки СУБД на экран. Даже если ошибки не показываются, злоумышленник может использовать другие каналы (логи, заголовки).
Методы защиты
Чтобы предотвратить подобные атаки, необходимо:
- Использовать подготовленные выражения (prepared statements) с параметризацией. Это самый надёжный способ, так как данные не интерпретируются как SQL-код.
- Экранировать специальные символы при невозможности использовать параметризацию. В MySQL применяйте
mysqli_real_escape_string()или аналоги. - Ограничить права пользователя БД: не давайте приложению доступ к
information_schemaбез необходимости. - Отключить вывод ошибок в production-окружении. Логируйте их, но не показывайте пользователю.
- Использовать WAF (Web Application Firewall) для фильтрации подозрительных запросов.
- Регулярно обновлять СУБД: в новых версиях MySQL функция
EXTRACTVALUEпомечена как устаревшая и может быть удалена, что снижает риск.
Заключение
Запрос %' AND EXTRACTVALUE(3619,CONCAT(0x7e,((SELECT (ELT(3619=3619,1)))),0x7e))-- - — это учебный пример эксплуатации error-based SQL-инъекции. Понимание его механики помогает разработчикам и специалистам по безопасности лучше защищать свои приложения. Помните: любая передача пользовательских данных в SQL-запрос без обработки — потенциальная уязвимость. Используйте параметризованные запросы и следуйте принципу наименьших привилегий.
Комментарии
—Войдите, чтобы оставить комментарий