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

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

Подобные строки часто встречаются в логах веб-серверов, в отчётах систем обнаружения вторжений (IDS) и в материалах по безопасности. Понимание того, как они устроены, помогает разработчикам и администраторам правильно настраивать защиту и распознавать атаки.

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

MySQL предоставляет несколько функций, которые при некорректных аргументах генерируют сообщение об ошибке, содержащее переданные данные. Две самые известные — EXTRACTVALUE() и UPDATEXML(). Обе работают с XML и XPath. Если в качестве XPath-выражения передать строку, которая не является корректным XPath, СУБД выдаст ошибку, включив в её текст фрагмент переданного выражения. Именно это и эксплуатируется.

В нашем случае используется EXTRACTVALUE(3006, CONCAT(0x7e, (SELECT ...), 0x7e)). Первый аргумент — произвольное число (3006), оно не играет роли. Второй аргумент — строка, начинающаяся с символа 0x7e (тильда ~), затем идёт результат подзапроса, и снова тильда. Тильда недопустима в начале XPath-выражения, поэтому MySQL гарантированно выдаст ошибку вида «XPATH syntax error: '~<результат>~'». В этом сообщении и утечёт искомая информация.

Разбор по частям

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

  • ")) — закрывает ранее открытые скобки и кавычки в уязвимом запросе приложения. Это нужно, чтобы «разорвать» оригинальный SQL и добавить свой код.
  • AND — логический оператор, позволяющий присоединить условие к существующему запросу (например, к WHERE).
  • EXTRACTVALUE(3006, ...) — функция MySQL для извлечения значения из XML по XPath. Первый аргумент может быть любым; важен второй.
  • CONCAT(0x7e, ((SELECT (ELT(3006=3006,1)))), 0x7e) — конкатенация тильды, результата подзапроса и ещё одной тильды. 0x7e — шестнадцатеричный код символа ~.
  • SELECT (ELT(3006=3006,1)) — вложенный подзапрос. ELT(N, str1, str2, ...) возвращает строку по номеру N. Здесь 3006=3006 — всегда истина (1), поэтому ELT(1, 1) вернёт строку '1'. Это простейшая проверка работоспособности инъекции: если ошибка содержит ~1~, значит, внедрение выполнено.
  • -- - — комментарий в MySQL (пробел после двух дефисов обязателен). Он «отрезает» оставшуюся часть оригинального запроса, чтобы не возникло синтаксической ошибки.

В реальной атаке вместо ELT(3006=3006,1) подставляется подзапрос, возвращающий нужные данные, например SELECT database() или SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema=database(). Тогда в тексте ошибки появятся имена таблиц или текущая база данных.

Пример эксплуатации

Классический пример из публичных источников: SELECT EXTRACTVALUE(1, CONCAT(0x7e, (SELECT DATABASE()))). Сервер вернёт ошибку с именем текущей базы данных. Аналогично для таблиц:

SELECT EXTRACTVALUE(1, CONCAT(0x7e, (SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema=DATABASE())))

Это позволяет атакующему шаг за шагом выведывать структуру базы. Ограничение — длина сообщения об ошибке (обычно 32 символа), поэтому данные извлекают по частям с помощью SUBSTRING или LIMIT.

Опасность и меры защиты

Error-based SQL-инъекции опасны тем, что не требуют «слепого» перебора и дают быстрый отклик. Однако они легко обнаруживаются при правильной настройке: сервер БД не должен отдавать подробные сообщения об ошибках конечному пользователю. Основные меры профилактики:

  • Использовать параметризованные запросы (prepared statements) — самый надёжный способ.
  • Экранировать все пользовательские данные, особенно кавычки и специальные символы.
  • Отключить вывод ошибок СУБД в production-окружении, вести логирование на сервере.
  • Применять принцип наименьших привилегий для учётной записи, от имени которой работает приложение.
  • Регулярно проводить сканирование уязвимостей и код-ревью.

Важно понимать: строка ")) AND EXTRACTVALUE(3006,CONCAT(0x7e,((SELECT (ELT(3006=3006,1)))),0x7e))-- - сама по себе не является вирусом или программой. Это текстовый шаблон, который может быть использован злоумышленником. Если вы встретили её в логах, стоит проверить, не было ли успешной атаки, и убедиться, что все входные данные фильтруются.

Итог

Рассмотренная конструкция — учебный пример error-based SQL-инъекции для MySQL. Она демонстрирует, как через функцию EXTRACTVALUE и символ-разделитель ~ можно заставить СУБД выдать результат подзапроса в сообщении об ошибке. Понимание механики таких атак необходимо для построения безопасных веб-приложений.

Источники