Что это за строка?

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

В основе лежит функция EXTRACTVALUE(), которая извлекает значение из XML-документа по заданному XPath-выражению. Если XPath-выражение некорректно, MySQL генерирует ошибку, содержащую переданный фрагмент. Это позволяет атакующему «вытащить» результат подзапроса в тексте ошибки.

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

Рассмотрим каждый элемент по отдельности:

  • )))) — последовательность закрывающих скобок, которая «ломает» исходный SQL-запрос, заставляя его завершиться раньше и добавить условие AND. Это нужно, чтобы внедрить свой код в существующий запрос.
  • AND EXTRACTVALUE(8890,CONCAT(0x7e,((SELECT (ELT(8890=8890,1)))),0x7e)) — основная полезная нагрузка. Функция EXTRACTVALUE принимает два аргумента: XML-документ (здесь просто число 8890) и XPath-выражение. Второй аргумент формируется через CONCAT, который объединяет тильду (0x7e), результат подзапроса и ещё одну тильду.
  • -- - — комментарий, который отсекает оставшуюся часть оригинального запроса, чтобы избежать синтаксических ошибок.

Подзапрос (SELECT (ELT(8890=8890,1))) использует функцию ELT(). ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь 8890=8890 — это логическое выражение, которое всегда истинно (1). Таким образом, ELT(1,1) вернёт строку '1'. Это простейший пример, демонстрирующий, что в реальной атаке вместо '1' мог бы быть, например, database(), user() или version().

Итоговое XPath-выражение будет содержать символ ~ и результат подзапроса, например ~1~. Поскольку это не является корректным XPath, MySQL выдаст ошибку вида: XPATH syntax error: '~1~'. В этом сообщении и окажутся данные, полученные из базы.

Зачем используется EXTRACTVALUE?

Функция EXTRACTVALUE появилась в MySQL 5.1 и предназначена для работы с XML. Однако из-за особенностей обработки ошибок она стала популярным инструментом для error-based SQL-инъекций. Аналогичными свойствами обладают функции UPDATEXML() и GTID_SUBSET().

Главное преимущество такого подхода — возможность получать данные напрямую в ответе сервера, без необходимости использовать слепые инъекции (blind SQL injection), которые требуют множества запросов и времени. Это делает атаку быстрой и эффективной.

Как работает error-based SQL-инъекция

Error-based SQL-инъекция эксплуатирует недостаточную обработку ошибок в веб-приложении. Когда приложение выводит сообщения об ошибках СУБД прямо на страницу, атакующий может внедрить код, который вызовет ошибку с полезной информацией. В случае с EXTRACTVALUE злоумышленник формирует XPath-выражение, включающее результат подзапроса, и сервер возвращает его в тексте ошибки.

Типичный сценарий атаки:

  1. Находится параметр, уязвимый для SQL-инъекции (например, id в URL).
  2. В параметр внедряется строка, подобная рассматриваемой.
  3. Приложение выполняет запрос и выводит ошибку MySQL, содержащую результат подзапроса.
  4. Атакующий последовательно извлекает имена таблиц, колонок и данные.

В примере с ELT(8890=8890,1) возвращается просто '1', но заменив '1' на database(), можно получить имя текущей базы данных. Далее, используя LIMIT и OFFSET, можно перебрать все таблицы и записи.

Примеры реальных атак

В 2019 году исследователь безопасности опубликовал разбор error-based SQL-инъекции через XPATH-инъекцию, обнаруженную при пентесте. В его примере использовалась похожая конструкция для извлечения имён колонок из information_schema.columns. Атака позволяла получить доступ к учётным данным пользователей.

Другой пример из практики: для извлечения имени пользователя применялся запрос:

' AND (SELECT 1 FROM (SELECT COUNT(*), CONCAT((SELECT CONCAT(0x7e, (SELECT user FROM data LIMIT 1,1), 0x7e)), FLOOR(RAND(0)*2))x FROM information_schema.tables GROUP BY x)a AND '1'='2

Здесь используется группировка с GROUP BY и функцией RAND() для вызова ошибки дублирования ключа, что также относится к error-based инъекциям.

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

Основной метод защиты — использование параметризованных запросов (prepared statements). Они разделяют код SQL и данные, поэтому внедрённые строки не интерпретируются как часть запроса.

Дополнительные меры:

  • Экранирование специальных символов с помощью функций вроде mysqli_real_escape_string (для MySQL).
  • Валидация и фильтрация входных данных на стороне сервера.
  • Ограничение привилегий пользователя базы данных, от имени которого работает приложение.
  • Отключение вывода подробных ошибок СУБД в production-окружении.
  • Использование WAF (Web Application Firewall) для блокировки подозрительных запросов.
  • Регулярное обновление СУБД и фреймворков.

Важно понимать, что EXTRACTVALUE — не единственная функция, эксплуатируемая в error-based атаках. Злоумышленники могут использовать UPDATEXML, GTID_SUBSET, JSON_KEYS и другие. Поэтому защита должна быть комплексной.

Заключение

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

Источники