Введение в SQL-инъекции через ExtractValue
SQL-инъекции остаются одной из самых распространённых уязвимостей веб-приложений. Среди них выделяется класс error-based инъекций, когда злоумышленник заставляет базу данных выдать сообщение об ошибке, содержащее полезные данные. Функция EXTRACTVALUE в MySQL — один из инструментов, который часто используется для таких атак. В этой статье мы детально разберём конкретную полезную нагрузку: %") OR EXTRACTVALUE(8694,CONCAT(0x7e,((SELECT (ELT(8694=8694,1)))),0x7e))-- -.
Что такое функция EXTRACTVALUE?
Функция EXTRACTVALUE() в MySQL предназначена для работы с XML-документами. Она принимает два строковых аргумента: фрагмент XML-разметки и выражение XPath (локатор). Функция возвращает текст (CDATA) первого текстового узла, который является дочерним для элемента или элементов, соответствующих XPath-выражению. Например, запрос SELECT EXTRACTVALUE('<a>текст</a>', '/a') вернёт строку 'текст'.
Однако при некорректном XPath-выражении MySQL генерирует ошибку, которая может содержать переданные данные. Это и используется в error-based SQL-инъекциях: злоумышленник конструирует такой XPath, чтобы в тексте ошибки появилась информация из базы данных.
Разбор полезной нагрузки
Рассмотрим по частям запрос %") OR EXTRACTVALUE(8694,CONCAT(0x7e,((SELECT (ELT(8694=8694,1)))),0x7e))-- -.
- %") — это начало, которое часто используется для закрытия предыдущего выражения в SQL-запросе. Символ
%может быть частью LIKE-условия, а")закрывает кавычку и скобку. Точная интерпретация зависит от контекста исходного запроса. - OR EXTRACTVALUE(...) — логический оператор OR, за которым следует вызов уязвимой функции. Если предыдущее условие ложно, выполнится правая часть.
- 8694 — первый аргумент EXTRACTVALUE, который должен быть XML-фрагментом. Здесь передано число, что приведёт к ошибке, но это не важно, так как цель — вызвать ошибку с полезной нагрузкой.
- CONCAT(0x7e,((SELECT (ELT(8694=8694,1)))),0x7e) — второй аргумент, XPath-выражение. Функция CONCAT объединяет символ
~(0x7e в шестнадцатеричном виде), результат подзапроса и ещё один~. Символ~используется как маркер, чтобы легко найти данные в сообщении об ошибке. - SELECT (ELT(8694=8694,1)) — подзапрос, который возвращает 1, если 8694=8694 (всегда истина), и NULL в противном случае. ELT — это функция, возвращающая N-й элемент из списка. Здесь список состоит из одного элемента 1. Фактически это заглушка, но в реальной атаке вместо неё был бы запрос к базе, например,
(SELECT user()). - -- - — комментарий, который обрезает оставшуюся часть исходного SQL-запроса, чтобы не вызвать синтаксическую ошибку.
Как работает эксплуатация
Когда MySQL выполняет EXTRACTVALUE с некорректным XPath, он возвращает ошибку вида: XPATH syntax error: '~1~'. В нашем случае XPath будет содержать ~1~, и эта строка попадёт в сообщение об ошибке, которое затем отобразится на странице (если приложение не подавляет ошибки). Таким образом, атакующий может извлечь данные из базы, подставляя вместо ELT(8694=8694,1) произвольные подзапросы, например, (SELECT version()) или (SELECT password FROM users LIMIT 1).
Важно отметить, что для успешной атаки необходимо, чтобы приложение возвращало ошибки базы данных пользователю. В противном случае злоумышленник может использовать слепые методы.
Пример реальной атаки
Предположим, есть уязвимый параметр id в URL: http://example.com/product.php?id=1. Запрос в коде может выглядеть так: SELECT * FROM products WHERE id = '$id'. Если передать 1' OR EXTRACTVALUE(1,CONCAT(0x7e,(SELECT database()),0x7e))-- -, то база вернёт ошибку с именем текущей базы данных. Это классический пример error-based SQL-инъекции.
В нашем разбираемом запросе используется более сложная конструкция с % и "), что говорит о том, что исходный запрос, вероятно, был частью LIKE-поиска или имел закрывающую скобку и кавычку. Например: SELECT * FROM table WHERE name LIKE '%" + input + "%'. Тогда полезная нагрузка закрывает кавычку и скобку, добавляет OR и комментарий.
Защита от SQL-инъекций
Основной способ защиты — использование параметризованных запросов (prepared statements). Это гарантирует, что пользовательский ввод никогда не интерпретируется как SQL-код. Также рекомендуется:
- Экранировать специальные символы с помощью функций типа
mysqli_real_escape_string. - Использовать ORM или query builder, которые автоматически параметризуют запросы.
- Ограничить права пользователя базы данных, чтобы даже при инъекции нельзя было получить лишние данные.
- Отключить вывод ошибок базы данных на продакшене, чтобы не давать атакующему информацию.
- Регулярно обновлять СУБД и применять патчи безопасности.
Кроме того, полезно проводить аудит кода и использовать сканеры уязвимостей, такие как SQLMap, для тестирования собственных приложений.
Заключение
Функция EXTRACTVALUE — мощный инструмент для error-based SQL-инъекций, если приложение не фильтрует ввод и выводит ошибки. Разобранная полезная нагрузка демонстрирует типичный подход: закрытие предыдущего выражения, вызов уязвимой функции с подзапросом и комментарий. Понимание таких атак помогает разработчикам писать более безопасный код и защищать данные пользователей.
Комментарии
—Войдите, чтобы оставить комментарий