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

Перед нами фрагмент эксплойта для error-based SQL-инъекции в СУБД MySQL. Полная строка выглядит так:

%')) AND EXTRACTVALUE(5763,CONCAT(0x7e,((SELECT (ELT(5763=5763,1)))),0x7e))-- -

Это не случайный набор символов, а тщательно сконструированная полезная нагрузка (payload), цель которой — заставить сервер базы данных вернуть в сообщении об ошибке данные, к которым злоумышленник не имеет прямого доступа. Подобные строки часто встречаются в логах веб-серверов, в полях ввода форм и в параметрах URL. Понимание их устройства помогает разработчикам и администраторам распознавать атаки и правильно выстраивать защиту.

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

Рассмотрим каждый элемент конструкции.

  • %')) — попытка «закрыть» исходный SQL-запрос. Символ % часто используется в LIKE-запросах, две закрывающие скобки и апостроф имитируют завершение строкового литерала и вложенных условий. Задача — выйти из контекста, в который подставляется пользовательский ввод.
  • AND — логический оператор, позволяющий присоединить дополнительное условие к исходному запросу.
  • EXTRACTVALUE(5763, CONCAT(...)) — функция MySQL, извлекающая значение из XML-фрагмента. Если второй аргумент содержит некорректный XPath-выражение, MySQL генерирует ошибку, в тексте которой отображается переданная строка. Это и есть канал утечки данных.
  • CONCAT(0x7e, ..., 0x7e) — склейка строк. 0x7e — шестнадцатеричный код символа ~ (тильда). Тильды служат маркерами, по которым атакующий легко находит нужные данные в сообщении об ошибке.
  • SELECT (ELT(5763=5763,1)) — подзапрос, возвращающий результат функции ELT(). ELT(N, str1, str2, ...) возвращает строку с номером N. Здесь условие 5763=5763 всегда истинно (1), поэтому возвращается первый элемент — число 1. В реальной атаке на месте этого подзапроса стоял бы запрос к системным таблицам, например SELECT version() или SELECT password FROM users LIMIT 1.
  • -- - — комментарий в MySQL. Всё, что идёт после него, игнорируется парсером. Это нужно, чтобы «отрезать» оставшуюся часть оригинального запроса и сделать внедрённую конструкцию синтаксически корректной.

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

Предположим, на сервере выполняется запрос вида:

SELECT * FROM articles WHERE title LIKE '%USER_INPUT%'

Злоумышленник подставляет вместо USER_INPUT нашу строку. После подстановки запрос приобретает вид:

SELECT * FROM articles WHERE title LIKE '%%')) AND EXTRACTVALUE(5763,CONCAT(0x7e,((SELECT (ELT(5763=5763,1)))),0x7e))-- -%'

СУБД пытается выполнить EXTRACTVALUE с заведомо некорректным XPath (второй аргумент не является допустимым выражением XPath). MySQL возвращает ошибку примерно такого содержания:

XPATH syntax error: '~1~'

В этом сообщении между тильдами оказывается результат подзапроса. В нашем демонстрационном примере это «1», но в реальной атаке здесь могли бы оказаться имя пользователя, хеш пароля, версия СУБД или другие конфиденциальные сведения. Именно поэтому метод называется error-based: данные извлекаются через текст ошибки.

Если бы приложение не выводило ошибки базы данных пользователю, а также использовало параметризованные запросы, атака бы не удалась. Но при наличии уязвимости и выводе ошибок на экран злоумышленник получает канал утечки.

Почему используется именно EXTRACTVALUE?

Функция EXTRACTVALUE — не единственный инструмент error-based инъекций. Исторически популярны также UPDATEXML, GEOMETRYCOLLECTION и другие функции, вызывающие ошибки с полезной нагрузкой. EXTRACTVALUE удобна тем, что позволяет передать произвольную строку в сообщение об ошибке и чётко ограничить её маркерами. Однако начиная с MySQL 8.0.17 эта функция объявлена устаревшей, а в новых версиях её поведение может отличаться. Тем не менее в устаревших системах и в образовательных целях подобные примеры по-прежнему актуальны.

Опасность и последствия

Успешная error-based инъекция может привести к:

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

Даже если злоумышленнику не удаётся сразу извлечь данные, сам факт наличия такой строки в логах — сигнал о том, что сайт пытались взломать. Игнорировать его нельзя.

Как защититься

Основные меры противодействия SQL-инъекциям, включая error-based, хорошо известны:

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

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

Если вы администратор или разработчик и обнаружили подобный запрос в логах, следует:

  • зафиксировать IP-адрес, время и полный текст запроса;
  • проверить, не была ли атака успешной (например, по логам ошибок БД);
  • убедиться, что все запросы к базе данных используют параметризацию;
  • проверить, не выводятся ли ошибки СУБД на страницы сайта;
  • при необходимости ограничить доступ с подозрительных адресов;
  • провести аудит кода на предмет других уязвимостей.

Помните: появление такой строки — это не просто «шум», а явная попытка взлома. Реагировать нужно оперативно.

Краткий итог

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

Источники