Введение

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

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

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

Приведённая строка содержит несколько характерных признаков инъекции: закрывающие кавычки и скобки, логический оператор AND, вызов функций EXTRACTVALUE и CONCAT, а также комментарий -- в конце. Рассмотрим каждый элемент по порядку.

Разбор структуры запроса

1. Начальные символы: %")))

Символ % часто используется в URL-кодировании, но в данном контексте это может быть частью полезной нагрузки. Далее идут закрывающая кавычка " и несколько закрывающих скобок ))). Их цель — «закрыть» ранее открытые в оригинальном запросе конструкции (строковый литерал, функцию или подзапрос), чтобы внедрить свой код. Количество скобок подбирается экспериментально или на основе анализа ошибок, возвращаемых сервером.

2. Оператор AND

Оператор AND используется для добавления нового условия к существующему запросу. Если исходный запрос был, например, SELECT * FROM users WHERE id = '...', то после подстановки полезной нагрузки условие может стать таким: WHERE id = '%"))) AND EXTRACTVALUE(...)-- -'. Всё, что идёт после --, интерпретируется как комментарий и игнорируется, поэтому исходное условие может быть обойдено.

3. Функция EXTRACTVALUE

EXTRACTVALUE — это функция MySQL (и MariaDB), предназначенная для извлечения значения из XML-документа по заданному XPath-выражению. Синтаксис: EXTRACTVALUE(XML_document, XPath_expression). Она возвращает текст из XML-фрагмента. Однако в контексте SQL-инъекций эта функция часто используется для организации так называемой error-based инъекции: при передаче некорректного XPath-выражения MySQL генерирует ошибку, в тексте которой может содержаться результат вычисления вложенного подзапроса. Это позволяет злоумышленнику извлекать данные из базы, даже если приложение не выводит результаты запроса напрямую.

4. CONCAT(0x7e, ..., 0x7e)

Функция CONCAT объединяет строки. Здесь она используется для обрамления извлекаемого значения символами ~ (тильда). 0x7e — это шестнадцатеричное представление символа ~ в ASCII. Обрамление помогает легко найти извлечённые данные в сообщении об ошибке, которое может быть длинным и содержать другой текст. Например, ошибка может выглядеть так: XPATH syntax error: '~1~', где 1 — результат внедрённого подзапроса.

5. Вложенный подзапрос (SELECT (ELT(7201=7201,1)))

Внутри CONCAT находится подзапрос SELECT (ELT(7201=7201,1)). Функция ELT в MySQL возвращает N-й элемент из списка строк: ELT(N, str1, str2, ...). В данном случае ELT(7201=7201, 1) — условие 7201=7201 всегда истинно и возвращает 1 (в MySQL логическое истинное значение приводится к 1). Таким образом, ELT(1, 1) вернёт первый элемент списка, то есть строку '1'. Фактически это простой способ получить константное значение 1, которое затем попадёт в CONCAT и вызовет ошибку EXTRACTVALUE с текстом ~1~.

В реальной атаке вместо ELT(7201=7201,1) мог бы стоять подзапрос, извлекающий, например, имя пользователя или хеш пароля из таблицы users. Но в данном примере используется безопасная константа, вероятно, для проверки уязвимости (например, при пентесте).

6. Комментарий -- -

Два дефиса и пробел (или дефис) обозначают начало комментария в SQL. Всё, что следует после, игнорируется парсером. Это позволяет «отрезать» оставшуюся часть оригинального запроса, которая могла бы вызвать синтаксическую ошибку или помешать выполнению внедрённого кода.

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

MySQL при вызове EXTRACTVALUE с некорректным XPath-выражением возвращает ошибку вида XPATH syntax error: '...'. Если в XPath-выражение внедрить результат подзапроса, он отобразится в тексте ошибки. Например, запрос:

SELECT EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e));

вызовет ошибку XPATH syntax error: '~5.7.32~', из которой можно узнать версию СУБД. Аналогично можно извлекать любые данные, если у атакующего есть доступ к выводу ошибок (например, через отладочную страницу или необработанное исключение).

В разбираемой строке вместо version() используется ELT(7201=7201,1), что даёт предсказуемый результат 1. Это может быть тестовой инъекцией для проверки, возвращает ли сервер ошибки с внедрённым текстом.

Меры защиты

Чтобы предотвратить подобные атаки, необходимо:

  • Использовать параметризованные запросы (prepared statements). Это самый надёжный способ: пользовательский ввод передаётся отдельно от SQL-кода и не может изменить структуру запроса.
  • Экранировать специальные символы. Если параметризация невозможна, применяйте функции экранирования, предоставляемые драйвером базы данных (например, mysqli_real_escape_string в PHP).
  • Ограничить права пользователя базы данных. Веб-приложение должно подключаться к БД с минимально необходимыми привилегиями (обычно только SELECT, INSERT, UPDATE, DELETE для конкретных таблиц).
  • Отключить вывод подробных ошибок в production. Сообщения об ошибках БД не должны попадать к конечному пользователю.
  • Использовать WAF (Web Application Firewall). Современные WAF могут обнаруживать и блокировать типовые сигнатуры SQL-инъекций, включая конструкции с EXTRACTVALUE.
  • Регулярно проводить аудит кода и пентесты. Это помогает выявлять уязвимости до того, как их обнаружат злоумышленники.

Заключение

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

Источники