Введение

В логах веб-серверов, в полях ввода или в параметрах 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-инъекций

Основные меры защиты:

  1. Использование параметризованных запросов (prepared statements) — самый надёжный способ. При этом SQL-код и данные передаются раздельно, и база данных не интерпретирует ввод как команды.
  2. Экранирование специальных символов — менее надёжно, но может применяться в legacy-системах.
  3. Валидация и фильтрация входных данных — проверка типов, длины, допустимых символов.
  4. Ограничение прав пользователя базы данных — приложение должно работать с минимально необходимыми привилегиями.
  5. Регулярное обновление СУБД и фреймворков — закрытие известных уязвимостей.
  6. Использование WAF (Web Application Firewall) — помогает обнаруживать и блокировать попытки инъекций.

Заключение

Строка %" OR EXTRACTVALUE(4024,CONCAT(0x7e,((SELECT (ELT(4024=4024,1)))),0x7e))-- - — это не случайный набор символов, а тщательно сконструированная SQL-инъекция, использующая ошибки функций MySQL для извлечения данных. Понимание таких запросов помогает разработчикам и администраторам своевременно выявлять атаки и укреплять защиту своих систем. Если вы встретили подобную строку в логах, это повод проверить безопасность вашего веб-приложения.

Источники