Введение
В логах веб-серверов, в полях ввода или в отчётах систем безопасности часто встречается строка вида:
%" 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 помогает разработчикам и специалистам по безопасности лучше защищать свои приложения. Если вы встретили подобную строку в логах, это сигнал о попытке взлома, и следует немедленно проверить код на наличие уязвимостей и внедрить параметризованные запросы.
Комментарии
—Войдите, чтобы оставить комментарий