Введение
В логах веб-серверов, в полях ввода или в параметрах URL иногда встречается странная последовательность символов, например: %" OR EXTRACTVALUE(4024,CONCAT(0x7e,((SELECT (ELT(4024=4024,1)))),0x7e))-- -. Для неподготовленного пользователя это выглядит как случайный набор знаков, но на самом деле перед нами классический пример SQL-инъекции — попытки взлома базы данных через уязвимость в веб-приложении. В этой статье мы подробно разберём, что означает каждый элемент этой строки, как она работает и почему такие запросы опасны.
Что такое SQL-инъекция?
SQL-инъекция (SQL injection) — это один из самых распространённых способов атаки на веб-сайты и приложения, работающие с базами данных. Злоумышленник вставляет в поля ввода (формы, параметры URL, cookie) специально сформированные SQL-команды, которые затем выполняются на сервере. Если приложение недостаточно защищено, хакер может получить доступ к конфиденциальным данным: паролям, номерам банковских карт, личной информации пользователей, а иногда и полностью захватить контроль над сервером.
Существует несколько разновидностей SQL-инъекций: UNION-based, error-based, blind, time-based и другие. Строка, которую мы рассматриваем, относится к error-based SQL-инъекции — методу, при котором злоумышленник заставляет базу данных выдать сообщение об ошибке, содержащее полезные данные.
Разбор строки по частям
Давайте разберём запрос %" OR EXTRACTVALUE(4024,CONCAT(0x7e,((SELECT (ELT(4024=4024,1)))),0x7e))-- - на составляющие.
%"— это начало строки, которое часто используется для «разрыва» оригинального SQL-запроса. Символ%может быть частью URL-кодирования, а двойная кавычка"закрывает строковый литерал в уязвимом запросе.OR— логический оператор, который делает условие всегда истинным, если правая часть верна. Это позволяет внедрить дополнительный код.EXTRACTVALUE(4024, CONCAT(...))— функция MySQL, предназначенная для извлечения значения из XML-документа по XPath-выражению. Однако при передаче некорректного XPath она генерирует ошибку, в тексте которой отображается переданное значение. Это и используется для вывода данных.CONCAT(0x7e, ..., 0x7e)— функция конкатенации строк.0x7e— это шестнадцатеричное представление символа~(тильда). Тильда используется как маркер, чтобы в сообщении об ошибке было легко найти выведенные данные.SELECT (ELT(4024=4024,1))— подзапрос, который возвращает результат функцииELT().ELT(N, str1, str2, ...)возвращает N-ю строку из списка. Здесь условие4024=4024всегда истинно (равно 1), поэтомуELT(1,1)вернёт строку'1'. В реальной атаке вместо1могло бы быть имя пользователя, пароль или другая информация из базы.-- -— комментарий в SQL. Всё, что идёт после--, игнорируется базой данных. Пробел после дефисов обязателен в некоторых СУБД, отсюда-- -.
Как работает error-based инъекция через EXTRACTVALUE
Функция EXTRACTVALUE(XML_document, XPath_expression) в MySQL анализирует XML и возвращает значение по указанному пути. Если XPath-выражение синтаксически неверно, MySQL выдаёт ошибку вида: XPATH syntax error: '...'. Злоумышленник конструирует XPath таким образом, чтобы в текст ошибки попало содержимое подзапроса. Например, передавая в качестве XPath строку, начинающуюся с тильды, он получает ошибку, в которой отображается эта строка вместе с полезной нагрузкой. Так через сообщения об ошибках можно посимвольно извлекать данные из базы.
В нашем примере подзапрос SELECT (ELT(4024=4024,1)) возвращает 1. Затем CONCAT объединяет тильду, результат подзапроса и ещё одну тильду: ~1~. Это значение передаётся в EXTRACTVALUE как XPath. Поскольку ~1~ не является корректным XPath, MySQL сгенерирует ошибку, в которой будет фигурировать ~1~. В реальной атаке вместо 1 могла быть версия базы данных, имя пользователя или хеш пароля.
Зачем используется ELT и условие 4024=4024?
ELT — это функция, возвращающая N-й элемент из списка. Конструкция ELT(4024=4024, 1) эквивалентна ELT(1, 1), потому что сравнение 4024=4024 истинно и преобразуется в 1. Это простейший пример, демонстрирующий работу функции. В более сложных атаках вместо 1 может стоять подзапрос, извлекающий конкретные данные, например: ELT(1, (SELECT password FROM users LIMIT 1)). Однако в нашем случае это просто «заглушка», показывающая механизм.
Последствия успешной SQL-инъекции
Если злоумышленнику удаётся выполнить подобный запрос, он может:
- Получить доступ к логинам и паролям пользователей;
- Выгрузить всю базу данных, включая персональные данные и платёжную информацию;
- Изменить или удалить данные;
- Выполнить произвольные команды на сервере в некоторых конфигурациях;
- Использовать сервер для дальнейших атак.
Именно поэтому SQL-инъекции считаются одной из самых опасных уязвимостей веб-приложений.
Как защититься от SQL-инъекций
Основные меры защиты:
- Использование параметризованных запросов (prepared statements) — самый надёжный способ. При этом SQL-код и данные передаются раздельно, и база данных не интерпретирует ввод как команды.
- Экранирование специальных символов — менее надёжно, но может применяться в legacy-системах.
- Валидация и фильтрация входных данных — проверка типов, длины, допустимых символов.
- Ограничение прав пользователя базы данных — приложение должно работать с минимально необходимыми привилегиями.
- Регулярное обновление СУБД и фреймворков — закрытие известных уязвимостей.
- Использование WAF (Web Application Firewall) — помогает обнаруживать и блокировать попытки инъекций.
Заключение
Строка %" OR EXTRACTVALUE(4024,CONCAT(0x7e,((SELECT (ELT(4024=4024,1)))),0x7e))-- - — это не случайный набор символов, а тщательно сконструированная SQL-инъекция, использующая ошибки функций MySQL для извлечения данных. Понимание таких запросов помогает разработчикам и администраторам своевременно выявлять атаки и укреплять защиту своих систем. Если вы встретили подобную строку в логах, это повод проверить безопасность вашего веб-приложения.
Комментарии
—Войдите, чтобы оставить комментарий