Что такое SQL-инъекция через ExtractValue?
SQL-инъекция — один из самых распространённых способов атаки на веб-приложения, при котором злоумышленник внедряет вредоносный SQL-код в запросы к базе данных. Существует несколько разновидностей таких атак, и одна из них основана на использовании функции ExtractValue в СУБД MySQL. Эта функция предназначена для извлечения значения из XML-документа по заданному XPath-выражению. Однако при неправильной обработке пользовательского ввода она может стать инструментом для извлечения данных из базы через механизм ошибок.
Запрос, который мы рассматриваем: %" AND EXTRACTVALUE(1383,CONCAT(0x7e,((SELECT (ELT(1383=1383,1)))),0x7e))-- - — является классическим примером error-based SQL-инъекции. Давайте разберём его по частям.
Анатомия запроса
Начнём с начала. Символ %" — это, вероятно, часть исходного запроса, куда внедряется инъекция. Например, в приложении может быть поиск по шаблону: SELECT * FROM users WHERE name LIKE '%".... Злоумышленник закрывает кавычку и добавляет логическое условие AND, за которым следует вызов функции EXTRACTVALUE.
Функция EXTRACTVALUE(XML_document, XPath_expression) принимает два аргумента: XML-документ и выражение XPath. Если XPath-выражение некорректно, MySQL генерирует ошибку, содержащую часть переданного XPath. Это и используется для извлечения данных: злоумышленник конструирует XPath так, чтобы в тексте ошибки появились нужные ему сведения.
В нашем случае первым аргументом идёт число 1383. Это не XML-документ, а просто число. MySQL автоматически преобразует его в строку '1383', что не является валидным XML. Но это не важно — функция всё равно попытается выполнить XPath-выражение, переданное вторым аргументом.
Второй аргумент: CONCAT(0x7e,((SELECT (ELT(1383=1383,1)))),0x7e). Здесь 0x7e — это шестнадцатеричное представление символа тильды (~). Функция CONCAT объединяет тильду, результат подзапроса и ещё одну тильду. Подзапрос SELECT (ELT(1383=1383,1)) использует функцию ELT(N, str1, str2, ...), которая возвращает N-ю строку из списка. Выражение 1383=1383 всегда истинно, что в MySQL равно 1. Таким образом, ELT(1, 1) вернёт '1'. То есть подзапрос возвращает строку '1'.
Итоговое XPath-выражение будет выглядеть как ~1~. Это синтаксически некорректный XPath, поэтому MySQL выдаст ошибку вида: XPATH syntax error: '~1~'. В тексте ошибки появятся данные, которые злоумышленник поместил между тильдами. В данном примере это просто '1', но в реальной атаке вместо ELT(1383=1383,1) может быть подзапрос, извлекающий, например, имя пользователя или хеш пароля.
Зачем нужны тильды и ELT?
Символ ~ используется как маркер, чтобы легко найти извлечённые данные в сообщении об ошибке. Функция ELT с условием 1383=1383 — это простейший способ вернуть константу. В более сложных атаках вместо неё применяются подзапросы к системным таблицам, например INFORMATION_SCHEMA.COLUMNS, для получения имён таблиц и колонок. Так, в одном из примеров из поисковой выдачи используется запрос:
+AND+ (SELECT+1+FROM+ (SELECT+COUNT (*),CONCAT ( (SELECT (SELECT+CONCAT (CAST (column_name+AS+CHAR),0x7e))+FROM+INFORMATION_SCHEMA.COLUMNS+WHERE+table_name=0x757365726e616d65+AND+table_schema=0x6c69746f666c6578+LIMIT 0,1),FLOOR (RAND (0)*2))x+FROM+INFORMATION ...
Здесь для извлечения имён колонок используется INFORMATION_SCHEMA.COLUMNS, а результат конкатенируется с тильдой. Подобные техники позволяют пошагово вытащить всю структуру базы данных и её содержимое.
Как работает error-based инъекция?
Error-based SQL-инъекция — это метод, при котором атакующий заставляет базу данных вернуть данные в сообщении об ошибке. Это возможно, когда веб-приложение отображает ошибки СУБД пользователю. Если ошибки скрыты, метод не сработает, и злоумышленник переключится на blind-инъекции.
Функция EXTRACTVALUE — не единственная, подверженная такой проблеме. Аналогично работают UPDATEXML и некоторые другие функции, работающие с XML. Они появились в MySQL 5.1 и стали популярны среди пентестеров благодаря простоте использования.
Важно понимать: сам по себе вызов EXTRACTVALUE с некорректным XPath не является уязвимостью. Уязвимость возникает, когда приложение позволяет пользователю влиять на SQL-запрос без должной очистки. В нашем примере инъекция внедряется через параметр, который, вероятно, подставляется в LIKE или WHERE.
Меры защиты
Чтобы предотвратить подобные атаки, необходимо следовать проверенным практикам:
- Использовать параметризованные запросы (prepared statements). Это самый надёжный способ, при котором данные пользователя передаются отдельно от SQL-кода и не могут изменить структуру запроса.
- Экранировать специальные символы. Если по каким-то причинам параметризация невозможна, следует применять функции экранирования, например
mysqli_real_escape_stringв PHP. - Ограничить права пользователя БД. Учётная запись, от имени которой работает приложение, не должна иметь прав на чтение системных таблиц
INFORMATION_SCHEMAбез необходимости. - Отключить вывод ошибок СУБД. Настройте приложение так, чтобы детали ошибок не показывались пользователю, а записывались в лог.
- Использовать WAF. Веб-application firewall может блокировать подозрительные запросы, содержащие сигнатуры SQL-инъекций.
Также рекомендуется регулярно проводить аудит кода и пентесты для выявления уязвимостей.
Заключение
Запрос %" AND EXTRACTVALUE(1383,CONCAT(0x7e,((SELECT (ELT(1383=1383,1)))),0x7e))-- - — это учебный пример эксплуатации error-based SQL-инъекции через функцию EXTRACTVALUE. Он демонстрирует, как злоумышленник может извлечь данные, используя ошибки СУБД. Понимание таких техник необходимо разработчикам и специалистам по безопасности для построения надёжной защиты. Помните: лучшая защита — это параметризованные запросы и минимизация привилегий базы данных.
Комментарии
—Войдите, чтобы оставить комментарий