Введение
В логах веб-сервера или в поле ввода иногда можно встретить загадочные строки, содержащие функции MySQL, шестнадцатеричные числа и странные последовательности символов. Одна из таких строк: %')))) AND EXTRACTVALUE(4624,CONCAT(0x7e,((SELECT (ELT(4624=4624,1)))),0x7e))-- -. Что это? Это классический пример SQL-инъекции (SQL injection), а именно — error-based SQL-инъекции, использующей функцию EXTRACTVALUE для извлечения данных из базы через сообщения об ошибках.
В этой статье мы подробно разберём, как работает данная конструкция, какие цели преследует злоумышленник и как защититься от подобных атак.
Что такое SQL-инъекция?
SQL-инъекция — это один из самых распространённых способов взлома веб-приложений. Суть атаки заключается во внедрении вредоносного SQL-кода в запрос, который приложение отправляет в базу данных. Если приложение недостаточно проверяет пользовательский ввод, злоумышленник может выполнить произвольные SQL-команды: прочитать, изменить или удалить данные, а в некоторых случаях — получить полный контроль над сервером.
Существует несколько типов SQL-инъекций: union-based, error-based, blind, time-based и другие. Строка, которую мы рассматриваем, относится к error-based — методу, при котором хакер заставляет базу данных выдать сообщение об ошибке, содержащее полезную информацию (например, версию СУБД, имена таблиц или конкретные данные).
Разбор строки: EXTRACTVALUE и CONCAT
Давайте разберём каждый элемент конструкции:
%')))) AND EXTRACTVALUE(4624,CONCAT(0x7e,((SELECT (ELT(4624=4624,1)))),0x7e))-- -
- %')))) — это часть, которая, вероятно, закрывает предыдущие кавычки и скобки в уязвимом запросе. Символ
%может быть URL-кодированием, а последовательность'))))— попыткой завершить оригинальный SQL-запрос и добавить свой. - AND EXTRACTVALUE(...) — логическое условие, которое выполняется, если предыдущая часть запроса истинна. Функция
EXTRACTVALUEв MySQL предназначена для извлечения значения из XML-документа, но при неправильном использовании она генерирует ошибку, содержащую переданные аргументы. - 4624 — произвольное число (идентификатор), которое передаётся первым аргументом в
EXTRACTVALUE. Оно не несёт смысловой нагрузки, кроме как быть частью синтаксиса. - CONCAT(0x7e, ((SELECT (ELT(4624=4624,1)))), 0x7e) — конкатенация строк.
0x7e— это шестнадцатеричное представление символа~(тильда). Он используется как разделитель, чтобы облегчить поиск данных в сообщении об ошибке. - SELECT (ELT(4624=4624,1)) — подзапрос, который возвращает результат функции
ELT.ELT(N, str1, str2, ...)возвращает N-ю строку из списка. Здесь4624=4624— всегда истинное условие (1), поэтомуELT(1,1)вернёт1. Это простейший пример; в реальной атаке вместо1могла бы быть, например, версия базы данных или имя пользователя. - -- - — комментарий в SQL. Всё, что идёт после
--, игнорируется базой данных. Пробел после--и дефис добавлены для обхода некоторых фильтров.
Таким образом, злоумышленник пытается выполнить запрос, который вызовет ошибку MySQL с текстом, содержащим результат подзапроса. Например, если вместо ELT(4624=4624,1) подставить SELECT version(), то в ошибке можно увидеть версию СУБД.
Как работает error-based инъекция через EXTRACTVALUE
Функция EXTRACTVALUE(XML_document, XPath_expression) в MySQL анализирует XML и извлекает данные по XPath-выражению. Если XPath-выражение содержит недопустимые символы (например, тильду ~), MySQL выдаёт ошибку вида:
XPATH syntax error: '~1~'
Именно эту ошибку и использует атакующий. Он конструирует XPath-выражение так, чтобы в тексте ошибки оказались данные, которые он хочет получить. В нашем примере CONCAT(0x7e, (SELECT ...), 0x7e) создаёт строку ~<результат>~, которая затем передаётся как XPath. MySQL пытается интерпретировать её и выдаёт ошибку, содержащую эту строку.
В приведённой строке результат подзапроса — просто 1, но это лишь демонстрация. В реальной атаке вместо 1 могут быть:
- версия MySQL:
SELECT version() - имя текущей базы данных:
SELECT database() - имя пользователя:
SELECT user() - список таблиц:
SELECT table_name FROM information_schema.tables LIMIT 1 - пароли пользователей:
SELECT password FROM users LIMIT 1
Получив эти данные, злоумышленник может продолжить атаку: подобрать пароли, получить доступ к админ-панели, загрузить веб-шелл и полностью захватить сервер.
Почему используется ELT и CONCAT?
Комбинация ELT и CONCAT — это стандартный приём в error-based SQL-инъекциях. ELT позволяет выбрать одну строку из списка по индексу, что удобно для перебора данных (например, по буквам). CONCAT объединяет несколько строк в одну, чтобы в ошибке вывести сразу несколько значений. Символ ~ (0x7e) служит маркером начала и конца полезной нагрузки — по нему легко найти данные в сообщении об ошибке.
Последствия успешной атаки
Если SQL-инъекция срабатывает, последствия могут быть катастрофическими:
- Утечка конфиденциальных данных — пароли, персональные данные клиентов, номера кредитных карт.
- Изменение или удаление данных — злоумышленник может выполнить
UPDATEилиDELETE. - Обход аутентификации — вход в систему без пароля.
- Выполнение произвольных команд — в некоторых конфигурациях MySQL позволяет читать и записывать файлы, а также выполнять команды ОС.
- Полный контроль над сервером — через загрузку веб-шелла.
Как защититься от SQL-инъекций
Основной метод защиты — использование параметризованных запросов (prepared statements). Они разделяют код и данные, поэтому внедрённый SQL-код не выполняется. Дополнительные меры:
- Валидация и фильтрация входных данных — проверяйте тип, длину, допустимые символы.
- Экранирование специальных символов — используйте функции экранирования, предоставляемые драйвером БД.
- Минимальные привилегии для пользователя БД — не давайте приложению прав на удаление таблиц или доступ к системным таблицам.
- Регулярное обновление СУБД и фреймворков — закрывайте известные уязвимости.
- Использование WAF — веб-прикладной брандмауэр может блокировать подозрительные запросы.
- Логирование и мониторинг — отслеживайте аномальные запросы в логах.
Важно понимать, что EXTRACTVALUE и подобные функции не являются уязвимостью сами по себе — уязвимость возникает из-за того, что приложение передаёт пользовательский ввод в SQL-запрос без должной обработки.
Заключение
Строка %')))) AND EXTRACTVALUE(4624,CONCAT(0x7e,((SELECT (ELT(4624=4624,1)))),0x7e))-- - — это типичный пример попытки error-based SQL-инъекции. Она демонстрирует, как злоумышленники используют особенности функций MySQL для извлечения данных через сообщения об ошибках. Понимание механизмов таких атак помогает разработчикам и администраторам лучше защищать свои системы. Никогда не доверяйте пользовательскому вводу и всегда используйте параметризованные запросы — это золотое правило веб-безопасности.
Комментарии
—Войдите, чтобы оставить комментарий