Введение

В логах веб-серверов, в полях ввода или в отчётах систем безопасности часто встречается строка вида:

%" OR EXTRACTVALUE(2423,CONCAT(0x7e,((SELECT (ELT(2423=2423,1)))),0x7e))-- -

Многие задаются вопросом: что это и какова её цель? Это классический пример SQL-инъекции, нацеленной на извлечение данных из базы данных MySQL. В данной статье мы детально разберём каждый элемент этого payload, объясним, как он работает, и расскажем, как защититься от подобных атак.

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

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

Существует несколько типов SQL-инъекций: union-based, error-based, blind, time-based и другие. Рассматриваемый payload относится к error-based инъекциям, так как использует функцию EXTRACTVALUE, которая при определённых условиях вызывает ошибку, содержащую результат подзапроса.

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

Давайте разберём строку %" OR EXTRACTVALUE(2423,CONCAT(0x7e,((SELECT (ELT(2423=2423,1)))),0x7e))-- - на составляющие.

1. Начало: %"

Символ % часто используется в LIKE-запросах как подстановочный знак. Кавычка " закрывает строковый литерал в исходном SQL-запросе. Таким образом, атакующий пытается «вырваться» из контекста строки, чтобы внедрить свой код. В некоторых случаях используется одинарная кавычка, но здесь применена двойная — это зависит от того, как формируется запрос в уязвимом приложении.

2. Оператор OR

Логический оператор OR позволяет добавить условие, которое всегда истинно, если внедрение удалось. Это нужно, чтобы исходный запрос не завершился ошибкой и вернул результаты, даже если первая часть условия ложна.

3. Функция EXTRACTVALUE

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

В нашем payload первым аргументом идёт число 2423 — это произвольное число, которое не является корректным XML-документом. Второй аргумент — сложное выражение, которое при вычислении вызовет ошибку с внедрёнными данными.

4. Функция CONCAT и шестнадцатеричные литералы 0x7e

CONCAT объединяет строки. Здесь она склеивает символ ~ (тильда), представленный в шестнадцатеричном виде как 0x7e, с результатом подзапроса и ещё одной тильдой. Тильда используется как маркер, чтобы облегчить поиск выведенных данных в сообщении об ошибке. Часто в таких payload применяют и другие разделители, например 0x3a (двоеточие).

5. Подзапрос (SELECT (ELT(2423=2423,1)))

Внутри CONCAT находится подзапрос, который возвращает значение, зависящее от условия. Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В данном случае ELT(2423=2423,1) — условие 2423=2423 всегда истинно (возвращает 1), поэтому ELT вернёт первый элемент — число 1. Это простейший пример; в реальных атаках вместо 1 может быть подзапрос, извлекающий имена таблиц, столбцов или данные пользователей.

Таким образом, выражение CONCAT(0x7e, (SELECT (ELT(2423=2423,1))), 0x7e) сформирует строку ~1~.

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

Два дефиса с пробелом (или без) в MySQL означают начало комментария до конца строки. Это позволяет «отрезать» оставшуюся часть оригинального SQL-запроса, чтобы синтаксис был корректным. Пробел после -- обязателен в некоторых СУБД, поэтому часто пишут -- - или --+.

Как работает атака целиком

Предположим, уязвимый запрос выглядит так:

SELECT * FROM articles WHERE title LIKE '%" OR EXTRACTVALUE(2423,CONCAT(0x7e,((SELECT (ELT(2423=2423,1)))),0x7e))-- -%';

После подстановки пользовательского ввода запрос превращается в:

SELECT * FROM articles WHERE title LIKE '%" OR EXTRACTVALUE(2423,CONCAT(0x7e,((SELECT (ELT(2423=2423,1)))),0x7e))-- -%';

База данных пытается выполнить EXTRACTVALUE с первым аргументом 2423, который не является XML. Это вызывает ошибку вида:

XPATH syntax error: '~1~'

В сообщении об ошибке мы видим результат выполнения подзапроса, обёрнутый тильдами. Если бы вместо 1 стоял подзапрос, например (SELECT version()), мы бы увидели версию СУБД. Так злоумышленник может пошагово извлекать любые данные.

Зачем это нужно злоумышленнику?

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

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

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

  • Параметризация запросов — самый надёжный способ.
  • Экранирование специальных символов — менее надёжно, но может применяться в legacy-коде.
  • Валидация и фильтрация входных данных — по белым спискам, а не чёрным.
  • Ограничение прав пользователя БД — не давайте приложению прав на удаление таблиц или доступ к системным функциям.
  • Отключение вывода ошибок БД — сообщения об ошибках не должны попадать в браузер.
  • Использование WAF — веб-application firewall может блокировать известные сигнатуры атак, но не заменяет правильное кодирование.

Заключение

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

Источники