Введение

В логах веб-сервера или в поле ввода часто встречается загадочная строка: %')))) AND EXTRACTVALUE(6031,CONCAT(0x7e,((SELECT (ELT(6031=6031,1)))),0x7e))-- -. Многие задаются вопросом: что это и какова её цель? Это классический пример SQL-инъекции, нацеленной на извлечение данных из базы через функцию EXTRACTVALUE. В данной статье мы подробно разберём каждый элемент этого запроса, объясним, как он работает, и расскажем, как защититься от подобных атак.

Что такое SQL-инъекция?

SQL-инъекция (SQL injection) — один из самых распространённых способов взлома веб-приложений. Злоумышленник вставляет вредоносный SQL-код в поля ввода или параметры URL, чтобы заставить сервер выполнить непредусмотренные запросы к базе данных. Целью может быть кража конфиденциальной информации (пароли, номера карт), изменение или удаление данных, а иногда и полный контроль над сервером.

Приведённая строка — это типичный пример «слепой» SQL-инъекции, когда атакующий не видит напрямую результаты запроса, но может извлекать данные посимвольно, используя ошибки базы данных.

Разбор строки инъекции

Давайте разложим запрос на составляющие:

%')))) AND EXTRACTVALUE(6031,CONCAT(0x7e,((SELECT (ELT(6031=6031,1)))),0x7e))-- -
  • %' — закрывающая кавычка и процент, часто используемые для завершения исходного SQL-запроса и добавления собственного кода.
  • )))) — закрывающие скобки, чтобы «подогнать» синтаксис под исходный запрос.
  • AND EXTRACTVALUE(...) — вызов функции EXTRACTVALUE, которая извлекает данные из XML и генерирует ошибку, если результат не соответствует ожидаемому формату.
  • 6031 — произвольное число, часто используется как идентификатор для проверки условия.
  • CONCAT(0x7e, ..., 0x7e) — конкатенация символа тильды (~) с полезной нагрузкой, чтобы отделить выводимые данные в сообщении об ошибке.
  • SELECT (ELT(6031=6031,1)) — подзапрос, возвращающий 1, если условие истинно (6031=6031 всегда истинно). ELT — функция, возвращающая N-й элемент из списка.
  • -- - — комментарий, обрезающий остаток исходного запроса.

Как работает EXTRACTVALUE?

Функция EXTRACTVALUE в MySQL (и MariaDB) предназначена для извлечения значения из XML-документа по заданному XPath-выражению. Синтаксис: EXTRACTVALUE(XML_документ, XPath_выражение). Если XPath-выражение возвращает не текстовый узел, а, например, несколько узлов или недопустимый символ, MySQL генерирует ошибку с сообщением, содержащим результат вычисления.

Злоумышленники используют эту особенность для вывода данных: они передают в качестве XPath строку, содержащую конкатенацию тильды и результата подзапроса. Если подзапрос возвращает, например, версию базы данных, она попадёт в текст ошибки, который затем отобразится на странице или сохранится в логе. Это позволяет атакующему «читать» данные по частям.

Пример работы

Предположим, что внедряемый фрагмент выполняется в контексте запроса SELECT * FROM users WHERE id = '...'. После подстановки получается:

SELECT * FROM users WHERE id = '%')))) AND EXTRACTVALUE(6031,CONCAT(0x7e,((SELECT (ELT(6031=6031,1)))),0x7e))-- -'

База данных выполнит функцию EXTRACTVALUE. Поскольку XPath-выражение начинается с символа ~ (тильда), который не является допустимым началом XPath, MySQL выдаст ошибку вида: XPATH syntax error: '~1~'. Здесь 1 — результат подзапроса. В реальной атаке вместо ELT(6031=6031,1) может быть подставлен другой подзапрос, например, (SELECT password FROM users LIMIT 1), и тогда в ошибке появится пароль.

Зачем нужен ELT?

Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В данном случае ELT(6031=6031,1) вернёт 1, так как условие истинно. Это простейший способ вернуть константу, но в более сложных атаках ELT может использоваться для извлечения данных из базы, например: ELT(1, (SELECT table_name FROM information_schema.tables LIMIT 1)). Однако в нашем примере это лишь демонстрация возможности выполнения подзапросов.

Последствия успешной атаки

Если злоумышленнику удаётся эксплуатировать уязвимость, он может:

  • Получить доступ к учётным данным пользователей (логины, пароли, хеши).
  • Извлечь данные банковских карт, персональную информацию.
  • Изменить или удалить содержимое базы данных.
  • Выполнить произвольные команды на сервере (в некоторых конфигурациях).

Поэтому важно своевременно обнаруживать и блокировать такие попытки.

Как защититься от SQL-инъекций через EXTRACTVALUE

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

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

Заключение

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

Источники