Что такое SQL-инъекция через ExtractValue?
SQL-инъекция — один из самых распространённых способов взлома веб-приложений. Когда пользовательский ввод попадает в SQL-запрос без должной очистки, злоумышленник может внедрить собственные команды. Среди множества техник особое место занимает error-based SQL-инъекция — метод, при котором хакер заставляет базу данных выдать сообщение об ошибке, содержащее конфиденциальные данные. Функция EXTRACTVALUE в MySQL как раз позволяет реализовать такую атаку.
В этой статье мы детально разберём конкретный payload: %" OR EXTRACTVALUE(3023,CONCAT(0x7e,((SELECT (ELT(3023=3023,1)))),0x7e))-- -. Вы узнаете, как он устроен, зачем нужны отдельные его части и какие меры защиты помогут предотвратить подобные вторжения.
Как работает функция EXTRACTVALUE в MySQL
EXTRACTVALUE — встроенная функция MySQL, предназначенная для извлечения значения из XML-документа по заданному XPath-выражению. Синтаксис:
EXTRACTVALUE(XML_документ, XPath_выражение)
Если XPath-выражение синтаксически некорректно, MySQL генерирует ошибку, в текст которой попадает переданная строка. Это и используется в error-based инъекциях: злоумышленник подставляет вместо корректного XPath выражение, содержащее результат подзапроса, и сервер возвращает его в сообщении об ошибке.
Например, запрос SELECT EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e)) вызовет ошибку вида XPATH syntax error: '~5.7.33~', раскрыв версию СУБД.
Разбор payload: %" OR EXTRACTVALUE(3023,CONCAT(0x7e,((SELECT (ELT(3023=3023,1)))),0x7e))-- -
Рассмотрим каждую часть запроса по порядку.
%"— начало внедрения. Символ%и кавычка используются для «разрыва» исходного SQL-запроса, чтобы закрыть строковый литерал и добавить условие OR.OR— логический оператор, который делает условие истинным при любом раскладе, если внедрённая часть вернёт ошибку (в error-based инъекциях это не важно, так как цель — вызвать ошибку, а не получить истинное условие).EXTRACTVALUE(3023, ...)— вызов уязвимой функции. Первый аргумент (3023) — произвольное число, имитирующее XML-документ (фактически не используется).CONCAT(0x7e, ((SELECT (ELT(3023=3023,1)))), 0x7e)— конкатенация тильды (0x7e), результата подзапроса и ещё одной тильды. Тильды служат маркерами, чтобы облегчить поиск вывода в сообщении об ошибке.SELECT (ELT(3023=3023,1))— подзапрос, возвращающий строку '1'.ELT(N, str1, str2, ...)возвращает N-ю строку из списка. Здесь3023=3023— всегда истина (1), поэтомуELT(1, 1)вернёт '1'. Это простейшая демонстрация; на практике вместо '1' подставляют имя пользователя, хэш пароля и т.п.-- -— комментарий, который «отрезает» оставшуюся часть оригинального запроса, чтобы синтаксис стал корректным.
В результате MySQL пытается выполнить EXTRACTVALUE(3023, CONCAT('~', '1', '~')), что даёт XPath-выражение ~1~. Это синтаксически неверно, и СУБД возвращает ошибку: XPATH syntax error: '~1~'. Злоумышленник видит этот ответ и понимает, что инъекция работает.
Практическое применение и модификации
В реальных атаках вместо ELT(3023=3023,1) внедряют подзапросы, извлекающие данные из системных таблиц. Например, чтобы получить имя текущей базы данных, используют:
OR EXTRACTVALUE(1, CONCAT(0x7e, (SELECT database()), 0x7e))-- -
Для получения списка таблиц:
OR EXTRACTVALUE(1, CONCAT(0x7e, (SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema=database()), 0x7e))-- -
Аналогично можно извлечь имена столбцов и содержимое таблиц users. Ограничение — длина сообщения об ошибке (обычно около 32 символов), поэтому часто прибегают к посимвольному выводу через substring или используют другие функции, например updatexml.
Чем опасна такая инъекция?
Error-based SQL-инъекции позволяют злоумышленнику полностью прочитать содержимое базы данных, включая логины, пароли, персональные данные клиентов. В некоторых случаях через них можно выполнить произвольный код на сервере (если СУБД имеет соответствующие привилегии). Последствия — утечка конфиденциальной информации, финансовые потери, репутационный ущерб.
Как защититься от SQL-инъекций
Основная причина уязвимости — недостаточная фильтрация пользовательского ввода. Вот ключевые меры защиты:
- Параметризованные запросы (prepared statements). Используйте их везде, где возможно. Они разделяют код и данные, делая инъекции невозможными.
- Экранирование спецсимволов. Если параметризация недоступна, применяйте функции экранирования (например,
mysqli_real_escape_stringв PHP). - Валидация входных данных. Проверяйте типы, форматы и диапазоны значений. Не доверяйте данным от клиента.
- Принцип наименьших привилегий. Учётная запись, от имени которой работает приложение, должна иметь только необходимые права. Не используйте root для подключения из веб-скриптов.
- Регулярное обновление СУБД и фреймворков. Исправляйте известные уязвимости.
- Использование WAF. Веб-application firewall может блокировать подозрительные запросы, но не заменяет правильного кодирования.
Также рекомендуется проводить аудит кода и пентесты для выявления подобных брешей до того, как их обнаружат злоумышленники.
Заключение
Payload %" OR EXTRACTVALUE(3023,CONCAT(0x7e,((SELECT (ELT(3023=3023,1)))),0x7e))-- - — это классический учебный пример error-based SQL-инъекции через функцию EXTRACTVALUE в MySQL. Он демонстрирует, как злоумышленник может заставить базу данных выдать данные в сообщении об ошибке. Понимание механики таких атак необходимо для построения надёжной защиты. Помните: лучшая защита — это параметризованные запросы и внимательное отношение к любому пользовательскому вводу.
Комментарии
—Войдите, чтобы оставить комментарий