Что такое SQL-инъекция через ExtractValue?
SQL-инъекция остаётся одной из самых опасных уязвимостей веб-приложений и стабильно входит в топ OWASP. Среди множества техник особое место занимает error-based SQL-инъекция, при которой злоумышленник заставляет базу данных выдать содержимое ошибки, содержащей полезные данные. Функция EXTRACTVALUE в MySQL — классический инструмент для таких атак.
Запрос %') OR EXTRACTVALUE(8829,CONCAT(0x7e,((SELECT (ELT(8829=8829,1)))),0x7e))-- - — это типичный пример внедрения, которое пытается вызвать ошибку XPath и вытащить через неё информацию. Давайте разберём его по частям.
Разбор вредоносного запроса
Строка начинается с %' — это попытка закрыть кавычку и, возможно, скобку в исходном SQL-запросе приложения. Символ % часто используется как подстановочный знак в LIKE-запросах, поэтому атакующий предполагает, что ввод подставляется в условие с LIKE. Далее идёт ), закрывающая скобку, затем OR — логический оператор, чтобы внедряемое условие выполнилось, даже если основное ложно. После этого вызывается EXTRACTVALUE(8829, CONCAT(0x7e, ((SELECT (ELT(8829=8829,1)))), 0x7e)).
В MySQL функция EXTRACTVALUE(XML_document, XPath_expression) извлекает значение из XML-документа по XPath-выражению. Если XPath-выражение некорректно, MySQL генерирует ошибку вида XPATH syntax error: '...', в которой отображается переданная строка. Это и используется для извлечения данных: в CONCAT подставляется результат подзапроса, а тильды 0x7e служат маркерами начала и конца полезной нагрузки в сообщении об ошибке.
Подзапрос SELECT (ELT(8829=8829,1)) — это простейшая проверка. ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь N — результат сравнения 8829=8829, то есть истина (1). Функция вернёт первый элемент — 1. Это демонстрационный пример: в реальной атаке на месте 1 был бы подзапрос, извлекающий имя пользователя, версию БД, хэши паролей и т.д.
Завершают строку -- - — комментарий, который отсекает оставшуюся часть оригинального SQL-запроса. Пробел после двух дефисов обязателен в MySQL, иначе комментарий не сработает.
Почему ExtractValue работает для извлечения данных
MySQL до версии 8.0 включительно поддерживает функции EXTRACTVALUE и UPDATEXML, которые при ошибке выводят переданное XPath-выражение в тексте ошибки. Это позволяет атакующему «прочитать» результат подзапроса. Например:
ERROR 1105 (HY000): XPATH syntax error: ':1'
В примере из документации MySQL видно, что в ошибке отображается значение, переданное в XPath. Если вместо 1 подставить (SELECT user()), в ошибке появится имя текущего пользователя БД. Так пошагово извлекаются любые данные: имена таблиц, колонок, содержимое полей.
Однако есть нюанс: EXTRACTVALUE возвращает не более 32 символов. Для длинных строк атакующие используют SUBSTRING или MID, извлекая данные по частям. Также в некоторых конфигурациях (например, при использовании подготовленных выражений) вывод ошибок может быть подавлен, что требует других техник, таких как updatexml или blind SQLi.
Как защититься от error-based SQL-инъекций
Главная рекомендация — никогда не конкатенировать пользовательский ввод в SQL-запросы. Используйте параметризованные запросы (prepared statements) с плейсхолдерами. Это полностью исключает возможность внедрения, так как данные передаются отдельно от кода SQL.
Дополнительные меры:
- Валидация и фильтрация ввода — проверяйте типы данных, длины, допустимые символы. Но не полагайтесь только на это.
- Экранирование спецсимволов — используйте функции экранирования, предоставляемые драйвером БД (например,
mysqli_real_escape_stringв PHP). - Ограничение прав пользователя БД — веб-приложение должно работать под учётной записью с минимально необходимыми привилегиями. Не используйте root.
- Отключение вывода ошибок БД на продакшене — сообщения об ошибках не должны попадать в ответ клиенту. Логируйте их на сервере.
- Использование WAF — веб-приложения firewall могут блокировать известные шаблоны атак, но это не замена правильному коду.
- Регулярное обновление MySQL — в версии 8.0.19+ функции EXTRACTVALUE и UPDATEXML удалены, что снижает риск, но не устраняет другие векторы.
Пример безопасного кода
Вместо уязвимого запроса:
$query = "SELECT * FROM users WHERE name LIKE '%" . $_GET['name'] . "%'";
Используйте подготовленные выражения:
$stmt = $pdo->prepare("SELECT * FROM users WHERE name LIKE ?");
$stmt->execute(["%" . $_GET['name'] . "%"]);
Такой подход гарантирует, что ввод пользователя не будет интерпретирован как SQL-код.
Заключение
Запрос %') OR EXTRACTVALUE(8829,CONCAT(0x7e,((SELECT (ELT(8829=8829,1)))),0x7e))-- - — это учебный пример error-based SQL-инъекции через функцию EXTRACTVALUE. Он показывает, как атакующий может использовать ошибки XPath для извлечения данных из базы. Понимание механики таких атак помогает разработчикам и администраторам правильно выстраивать защиту: параметризованные запросы, ограничение привилегий, скрытие ошибок и регулярные аудиты безопасности.
Комментарии
—Войдите, чтобы оставить комментарий