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

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

Строка начинается с последовательности закрывающих скобок и кавычек, чтобы «разорвать» оригинальный SQL-запрос приложения и внедрить собственный код. Далее идёт оператор AND, за которым следует вызов функции EXTRACTVALUE — она предназначена для работы с XML и в определённых условиях генерирует ошибку, содержащую переданные ей данные. Завершают конструкцию комментарий -- -, который «съедает» остаток исходного запроса, и специальные символы 0x7e (тильда ~), служащие маркерами для извлечения полезной нагрузки из текста ошибки.

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

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

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

XPATH syntax error: '~1~'

Именно этот текст и является целью атакующего: подставив в XPath результат подзапроса, он получает его в сообщении об ошибке.

Разбор внедрённого кода по частям

  • `)))) — последовательность символов для «обрыва» исходного запроса. Конкретный набор зависит от того, как выглядит уязвимый SQL-код приложения (наличие кавычек, скобок, операторов).
  • AND — логический оператор, присоединяющий вредоносное условие к оригинальному запросу.
  • EXTRACTVALUE(8108, ...) — вызов уязвимой функции. Первый аргумент (8108) — произвольное число, которое в данном случае не несёт смысловой нагрузки, но должно быть допустимым для синтаксиса.
  • CONCAT(0x7e, ((SELECT (ELT(8108=8108,1)))), 0x7e) — конкатенация тильды, результата подзапроса и ещё одной тильды. 0x7e — шестнадцатеричное представление символа ~, который используется как маркер начала и конца полезных данных в сообщении об ошибке.
  • SELECT (ELT(8108=8108,1)) — подзапрос, возвращающий значение. ELT() выбирает N-й элемент из списка; здесь условие 8108=8108 всегда истинно, поэтому возвращается 1. В реальной атаке на месте этой конструкции стоял бы запрос к системным таблицам, например SELECT version() или SELECT table_name FROM information_schema.tables.
  • -- - — комментарий, отсекающий остаток оригинального запроса. Пробел после двух дефисов обязателен в MySQL.

Какие данные можно извлечь

Если приложение уязвимо и выводит ошибки СУБД пользователю, атакующий может получить практически любую информацию, доступную учётной записи, от имени которой работает веб-приложение:

  1. Версию СУБД (SELECT version()).
  2. Имя текущей базы данных и пользователя (SELECT database(), SELECT user()).
  3. Список таблиц и колонок через information_schema.
  4. Логины, пароли (в виде хешей), персональные данные пользователей.
  5. Содержимое любых других таблиц, к которым есть доступ.

На практике злоумышленники часто автоматизируют процесс с помощью инструментов вроде sqlmap, которые сами подбирают синтаксис инъекции под конкретную СУБД и извлекают данные посимвольно или целыми строками.

Почему EXTRACTVALUE перестала быть надёжным инструментом

Начиная с MySQL 5.7.9 функция EXTRACTVALUE() была объявлена устаревшей (deprecated), а в MySQL 8.0 — удалена. То же самое произошло с UPDATEXML(). Это связано с тем, что поддержка XML в ядре СУБД была пересмотрена, а сами функции часто использовались именно для эксплуатации уязвимостей. Однако это не означает, что error-based инъекции исчезли: в современных версиях MySQL для вызова ошибок с полезной нагрузкой применяются другие приёмы, например функция GTID_SUBSET() или конструкции с JSON_KEYS() и NAME_CONST().

Кроме того, многие веб-приложения сегодня настроены так, чтобы не показывать пользователю подробные сообщения об ошибках базы данных. Это существенно затрудняет error-based атаки, но не делает их невозможными — иногда ошибки всё же «просачиваются» через отладочные страницы, логи или ответы API.

Как защититься от подобных атак

Главный принцип защиты от SQL-инъекций любого типа — не доверять пользовательскому вводу и никогда не подставлять его в SQL-запрос напрямую. Рассмотрим ключевые меры:

  • Параметризованные запросы (prepared statements). Это самый надёжный способ. Значения передаются отдельно от текста запроса, и СУБД не интерпретирует их как SQL-код. Такой подход поддерживают все современные драйверы и ORM.
  • Хранимые процедуры с параметрами. Если они написаны корректно и не используют динамический SQL, риск инъекции снижается.
  • Экранирование спецсимволов. Менее надёжно, чем параметризация, но может применяться как дополнительный барьер. Важно использовать функции экранирования, соответствующие конкретной СУБД.
  • Ограничение прав учётной записи БД. Веб-приложение не должно подключаться к базе как root или пользователь с правами на чтение системных таблиц. Принцип наименьших привилегий существенно сокращает ущерб от успешной инъекции.
  • Отключение вывода ошибок СУБД пользователю. Подробные сообщения должны писаться в лог, а посетитель видеть нейтральную страницу ошибки.
  • Регулярное обновление СУБД и библиотек. Устаревшие версии MySQL содержат известные уязвимости, которые уже исправлены в новых релизах.
  • Использование WAF. Специализированные межсетевые экраны для веб-приложений могут блокировать характерные шаблоны инъекций, включая конструкции с EXTRACTVALUE.

Что делать, если вы нашли такую строку в логах

Если вы администратор сайта или безопасник и обнаружили в логах запрос, подобный приведённому, это сигнал о попытке взлома. Действия должны быть следующими:

  1. Зафиксируйте IP-адрес, время и полный текст запроса.
  2. Проверьте, не увенчалась ли попытка успехом: просмотрите ответы сервера, убедитесь, что в них нет сообщений об ошибках СУБД.
  3. Проведите аудит кода на предмет наличия уязвимых мест: поищите конкатенацию строк в SQL-запросах, динамическое построение запросов.
  4. При необходимости привлеките специалистов по информационной безопасности для пентеста.
  5. Настройте оповещения о подобных событиях, чтобы реагировать оперативно.

Помните: даже если конкретная попытка не удалась, злоумышленник может вернуться с другим вектором атаки. Безопасность базы данных — это непрерывный процесс, а не разовое мероприятие.

Краткий итог

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

Источники