Что такое SQL-инъекция через EXTRACTVALUE?
SQL-инъекция — один из самых распространённых способов атаки на веб-приложения. Злоумышленник внедряет вредоносный SQL-код в запросы, которые приложение отправляет в базу данных. Если приложение не фильтрует пользовательский ввод, база данных выполняет этот код, что может привести к утечке конфиденциальной информации, изменению или удалению данных.
Функция EXTRACTVALUE() в MySQL предназначена для работы с XML. Она принимает два аргумента: фрагмент XML-разметки и выражение XPath. Функция возвращает текст первого текстового узла, который является дочерним для элемента, соответствующего XPath-выражению. Однако при некорректном XPath-выражении MySQL генерирует ошибку, которая может содержать переданные данные. Это и используется в error-based SQL-инъекциях.
Как работает эксплойт с EXTRACTVALUE?
Рассмотрим пример запроса, который вы могли встретить в уязвимых приложениях:
%\") AND EXTRACTVALUE(2810,CONCAT(0x7e,((SELECT (ELT(2810=2810,1)))),0x7e))-- -
Этот код пытается внедрить вызов функции EXTRACTVALUE в SQL-запрос. Разберём его по частям:
- %\") — закрывает предыдущую строку и скобку, чтобы вставить свой код.
- AND EXTRACTVALUE(2810, ...) — добавляет условие с вызовом уязвимой функции.
- CONCAT(0x7e, ((SELECT (ELT(2810=2810,1)))), 0x7e) — формирует строку, которая будет использована как XPath. 0x7e — это символ тильды (~). ELT(2810=2810,1) возвращает 1, так как условие истинно.
- -- - — комментарий, обрезающий остаток оригинального запроса.
Когда MySQL выполняет EXTRACTVALUE с XPath, содержащим тильду, возникает ошибка: XPATH syntax error: '~1~'. В тексте ошибки отображается результат подзапроса. Таким образом, злоумышленник может извлекать данные из базы, подставляя вместо ELT(2810=2810,1) другие подзапросы, например, SELECT user FROM mysql.user LIMIT 1.
Пошаговый разбор полезной нагрузки
Полезная нагрузка состоит из нескольких логических блоков. Первый блок — нарушение синтаксиса исходного запроса. Второй — внедрение вызова EXTRACTVALUE. Третий — формирование XPath-выражения, которое заведомо вызовет ошибку. Четвёртый — комментарий, чтобы обрезать оставшуюся часть запроса.
Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В данном случае ELT(2810=2810,1) возвращает 1, потому что условие 2810=2810 истинно. Это простейший пример. На практике вместо этого подзапроса внедряют выборку данных, например:
AND EXTRACTVALUE(2810,CONCAT(0x7e,(SELECT version()),0x7e))-- -
Тогда в ошибке отобразится версия MySQL. Аналогично можно извлечь имена таблиц, колонок, логины и пароли пользователей.
Какие данные можно извлечь?
С помощью error-based SQL-инъекции через EXTRACTVALUE злоумышленник может получить:
- версию СУБД;
- имя текущего пользователя базы данных;
- список баз данных;
- список таблиц и колонок;
- содержимое таблиц, включая учётные данные администраторов.
Важно отметить, что для успешной эксплуатации необходимо, чтобы приложение возвращало сообщения об ошибках базы данных пользователю. Если ошибки подавляются, этот метод не сработает, но могут быть использованы другие техники, например, blind SQL-инъекции.
Примеры эксплуатации
Рассмотрим типичный сценарий. Предположим, есть уязвимый параметр id в URL: http://example.com/product.php?id=1. Злоумышленник может подставить:
1 AND EXTRACTVALUE(1,CONCAT(0x7e,(SELECT user()),0x7e))
В ответе сервера появится ошибка с именем пользователя. Далее, чтобы извлечь имя базы данных, используют:
1 AND EXTRACTVALUE(1,CONCAT(0x7e,(SELECT database()),0x7e))
Для получения списка таблиц применяют подзапросы к information_schema.tables. Например:
1 AND EXTRACTVALUE(1,CONCAT(0x7e,(SELECT table_name FROM information_schema.tables WHERE table_schema=database() LIMIT 0,1),0x7e))
Меняя LIMIT 0,1 на 1,1 и так далее, можно перебрать все таблицы. Аналогично извлекаются колонки и данные.
Как защититься от SQL-инъекций через EXTRACTVALUE?
Основная причина уязвимости — недостаточная фильтрация пользовательского ввода и использование конкатенации строк для построения SQL-запросов. Вот ключевые меры защиты:
- Использование подготовленных выражений (prepared statements). Это самый надёжный способ. Параметры передаются отдельно от SQL-кода, и база данных не интерпретирует их как часть запроса.
- Экранирование специальных символов. Если по каким-то причинам prepared statements недоступны, необходимо экранировать все пользовательские данные с помощью функций типа mysqli_real_escape_string().
- Валидация входных данных. Проверяйте, что вводимые данные соответствуют ожидаемому формату (например, число, email).
- Отключение вывода ошибок БД. Не показывайте пользователям сообщения об ошибках базы данных. Логируйте их, но не выводите в браузер.
- Ограничение прав пользователя БД. Приложение должно подключаться к базе с минимально необходимыми правами. Не используйте root.
- Регулярное обновление СУБД. В новых версиях MySQL функция EXTRACTVALUE помечена как устаревшая, но в старых она всё ещё работает.
Также рекомендуется использовать веб-application firewall (WAF), который может блокировать подозрительные запросы, содержащие EXTRACTVALUE и другие опасные функции.
Заключение
SQL-инъекция через EXTRACTVALUE — это серьёзная угроза, которая позволяет злоумышленнику извлекать данные из базы, эксплуатируя ошибки XPath. Понимание механизма этой атаки помогает разработчикам и администраторам правильно защищать свои приложения. Использование подготовленных выражений, валидация входных данных и отключение вывода ошибок — обязательные меры безопасности.
Комментарии
—Войдите, чтобы оставить комментарий