Введение
SQL-инъекции остаются одной из самых опасных уязвимостей веб-приложений, несмотря на многолетнюю историю. Согласно OWASP Top 10, они стабильно входят в список критических рисков. В этой статье мы детально разберём конкретный пример инъекции, использующий функцию ExtractValue в MySQL. Запрос, который мы анализируем, выглядит так: ))) AND EXTRACTVALUE(1898,CONCAT(0x7e,((SELECT (ELT(1898=1898,1)))),0x7e))-- -. Это классическая error-based SQL-инъекция, основанная на XPATH-функциях MySQL. Мы объясним, как она работает, какие данные извлекает и как защититься от подобных атак.
Что такое error-based SQL-инъекция
Error-based SQL-инъекция — это метод эксплуатации, при котором злоумышленник заставляет базу данных выдать сообщение об ошибке, содержащее полезные данные. В отличие от UNION-инъекций, здесь не требуется, чтобы приложение выводило результаты запроса на странице. Достаточно, чтобы ошибка отображалась пользователю или сохранялась в логах, к которым есть доступ.
MySQL предоставляет несколько функций для работы с XML, которые при некорректных аргументах генерируют ошибки с включением переданных данных. К таким функциям относятся ExtractValue и UpdateXML. Они были добавлены для поддержки XPATH-запросов, но часто используются пентестерами для извлечения информации.
Разбор функции ExtractValue
Синтаксис функции: EXTRACTVALUE(XML_document, XPath_expression). Она извлекает значение из XML-документа по заданному XPath-выражению. Если XPath-выражение содержит недопустимые символы, MySQL возвращает ошибку вида: XPATH syntax error: '...'. В эту ошибку попадает часть переданного XPath-выражения. Именно это и эксплуатируется.
В нашем запросе: EXTRACTVALUE(1898, CONCAT(0x7e, ((SELECT (ELT(1898=1898,1)))), 0x7e)). Первый аргумент — число 1898 (может быть любым, он не влияет на ошибку). Второй аргумент — результат CONCAT, который начинается и заканчивается символом ~ (0x7e). Внутри — подзапрос SELECT (ELT(1898=1898,1)).
Функция ELT возвращает N-й элемент из списка. Здесь ELT(1898=1898,1): условие 1898=1898 истинно (равно 1), поэтому ELT вернёт первый элемент — число 1. Таким образом, CONCAT собирает строку ~1~. ExtractValue попытается интерпретировать её как XPath, что вызовет ошибку: XPATH syntax error: '~1~'. В реальной атаке вместо 1 подставляется подзапрос, извлекающий данные (например, имя базы, таблицы, хеши паролей).
Синтаксис и особенности запроса
Обратите внимание на обрамление: ))) AND ... -- -. Три закрывающие скобки в начале нужны, чтобы закрыть ранее открытые скобки в оригинальном запросе приложения. Это типичный приём при инъекции в параметры, которые уже находятся внутри скобок. Двойной дефис с пробелом (-- -) — комментарий в MySQL, который отсекает оставшуюся часть оригинального запроса.
Символ ~ (тильда) используется как маркер, чтобы облегчить поиск выведенных данных в тексте ошибки. Он не является обязательным, но часто применяется для удобства.
Пошаговый механизм атаки
- Определение точки инъекции. Злоумышленник находит параметр, который попадает в SQL-запрос без должной обработки. Например,
?id=1. - Проверка уязвимости. Подставляется
'или)и наблюдается ошибка синтаксиса. - Использование ExtractValue. Формируется запрос, который вызывает ошибку с внедрёнными данными. Например:
AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT database()), 0x7e)). - Извлечение данных. В сообщении об ошибке возвращается имя текущей базы данных, например
~myapp_db~. - Итеративное получение информации. Меняя подзапрос, можно извлечь имена таблиц, столбцов, логины, пароли и другие конфиденциальные данные.
Примеры полезных нагрузок
Вот несколько вариантов инъекций с ExtractValue для разных целей:
- Получение версии MySQL:
AND EXTRACTVALUE(1, CONCAT(0x7e, version(), 0x7e)) - Получение имени пользователя БД:
AND EXTRACTVALUE(1, CONCAT(0x7e, user(), 0x7e)) - Получение списка таблиц:
AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT table_name FROM information_schema.tables LIMIT 0,1), 0x7e))
Аналогично работает функция UpdateXML, но с slightly другим синтаксисом.
Ограничения и обход защиты
Длина выводимой строки в ошибке ExtractValue ограничена 32 символами. Для извлечения длинных данных используют функцию SUBSTRING или MID, посимвольно или по частям. Также современные WAF могут блокировать ключевые слова EXTRACTVALUE, CONCAT, SELECT. В таких случаях применяют обфускацию: замену регистра, вставку комментариев /**/, использование шестнадцатеричных литералов.
Некоторые хостинги отключают вывод ошибок MySQL в ответах приложения, что делает error-based инъекции неэффективными. Тогда злоумышленники переходят к blind-инъекциям (boolean-based или time-based).
Как защититься от SQL-инъекций
Основной метод защиты — использование параметризованных запросов (prepared statements) с привязкой переменных. Это исключает попадание пользовательских данных в тело SQL-запроса как исполняемого кода.
Дополнительные меры:
- Валидация и фильтрация всех входных данных (белые списки).
- Применение ORM (например, Hibernate, Entity Framework).
- Ограничение прав пользователя БД: только необходимые операции.
- Отключение вывода подробных ошибок в production.
- Использование WAF для обнаружения и блокировки атак.
- Регулярное обновление СУБД и фреймворков.
Согласно OWASP, SQL-инъекции остаются в Top 10 уже более десяти лет. Правильная архитектура приложения и параметризация запросов полностью устраняют эту уязвимость.
Заключение
Запрос ))) AND EXTRACTVALUE(1898,CONCAT(0x7e,((SELECT (ELT(1898=1898,1)))),0x7e))-- - — это учебный пример error-based SQL-инъекции, демонстрирующий использование функций ExtractValue, CONCAT и ELT для вызова ошибки с внедрёнными данными. Понимание механики таких атак необходимо как пентестерам, так и разработчикам для построения надёжной защиты. Помните: лучшая защита — параметризованные запросы и минимизация привилегий базы данных.
Комментарии
—Войдите, чтобы оставить комментарий