Введение
SQL-инъекции остаются одной из самых распространённых угроз для веб-приложений. Среди множества техник особое место занимают так называемые error-based инъекции, когда злоумышленник заставляет базу данных выдать сообщение об ошибке, содержащее конфиденциальную информацию. Запрос, который вы видите в заголовке, — это классический пример такой атаки с использованием функции EXTRACTVALUE в СУБД MySQL.
В этой статье мы подробно разберём, что означает данная полезная нагрузка, как она работает, какие данные может раскрыть и, главное, как защититься от подобных атак.
Что такое EXTRACTVALUE?
EXTRACTVALUE — это встроенная функция MySQL (и MariaDB), предназначенная для извлечения значения из фрагмента XML-документа по указанному XPath-выражению. Синтаксис функции:
EXTRACTVALUE(XML_fragment, XPath_expression)
Она возвращает текст, найденный по XPath, либо вызывает ошибку, если XML некорректен или XPath не соответствует синтаксису. Именно эта особенность — генерация ошибок с текстом, содержащим переданные данные, — и используется хакерами для извлечения информации из базы.
Аналогичной функциональностью обладают функции UPDATEXML и XMLTYPE (в Oracle). В MySQL наиболее популярны EXTRACTVALUE и UPDATEXML.
Разбор полезной нагрузки
Рассмотрим строку:
" ) OR EXTRACTVALUE(1470,CONCAT(0x7e,((SELECT (ELT(1470=1470,1)))),0x7e))-- -
Она предназначена для внедрения в SQL-запрос, скорее всего, в параметр, который подставляется в условие WHERE. Разберём по частям:
- " ) — закрывает предполагаемую кавычку и скобку, чтобы «разорвать» оригинальный запрос и добавить своё условие.
- OR — логический оператор, который делает условие всегда истинным (если правая часть вернёт true) или вызывает ошибку.
- EXTRACTVALUE(1470, CONCAT(0x7e, ((SELECT (ELT(1470=1470,1)))), 0x7e)) — вызов функции, которая заведомо вызовет ошибку, так как первый аргумент (1470) не является корректным XML-документом. Второй аргумент — это XPath-выражение, которое формируется динамически с помощью CONCAT. Он начинается и заканчивается символом 0x7e (тильда ~). Внутри вставляется результат подзапроса: SELECT (ELT(1470=1470,1)).
- ELT(1470=1470,1) — функция ELT возвращает N-й элемент из списка. Здесь условие 1470=1470 всегда истинно (равно 1), поэтому ELT(1,1) вернёт 1. Это просто заглушка, которая может быть заменена на любой другой подзапрос, например, для извлечения имени пользователя или хеша пароля.
- -- - — комментарий, который отсекает оставшуюся часть оригинального запроса.
Таким образом, при выполнении этого запроса MySQL попытается вычислить EXTRACTVALUE, потерпит неудачу и выдаст сообщение об ошибке примерно такого вида:
XPATH syntax error: '~1~'
В реальной атаке вместо «1» подставляется результат подзапроса, например, версия базы данных, имя пользователя или другие данные. Тильды используются как маркеры, чтобы облегчить извлечение полезной информации из текста ошибки.
Зачем это нужно злоумышленнику?
Error-based SQL-инъекции позволяют атакующему получать данные напрямую из сообщений об ошибках, что гораздо быстрее и проще, чем слепые инъекции (blind SQLi), где приходится задавать множество вопросов и анализировать поведение приложения. Функция EXTRACTVALUE даёт возможность вывести в ошибку произвольную строку, полученную из подзапроса.
Типичные цели:
- Получение версии СУБД.
- Извлечение имён таблиц и столбцов из information_schema.
- Чтение логинов и паролей пользователей.
- В некоторых случаях — выполнение произвольных команд, если у пользователя есть соответствующие привилегии.
Пример эксплуатации
Предположим, уязвимый запрос выглядит так:
SELECT * FROM users WHERE id = '$_GET[id]'
Злоумышленник передаёт в параметр id следующее:
1' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT database()), 0x7e))-- -
В результате MySQL вернёт ошибку: XPATH syntax error: '~mydb~', где mydb — имя текущей базы данных. Подставляя вместо database() другие подзапросы, можно постепенно извлечь всю структуру и содержимое базы.
Как защититься?
Основной способ защиты от SQL-инъекций любого типа — использование параметризованных запросов (prepared statements). Это гарантирует, что пользовательские данные никогда не будут интерпретированы как SQL-код.
Дополнительные меры:
- Применение ORM (например, Doctrine, Hibernate, SQLAlchemy).
- Экранирование специальных символов с помощью функций типа mysqli_real_escape_string (но это менее надёжно, чем prepared statements).
- Ограничение привилегий пользователя базы данных: не давайте веб-приложению прав на чтение information_schema или выполнение опасных функций.
- Отключение вывода подробных ошибок СУБД в production-окружении.
- Использование WAF (Web Application Firewall) для фильтрации подозрительных запросов.
- Регулярное обновление СУБД и фреймворков.
Заключение
Полезная нагрузка с EXTRACTVALUE — это мощный инструмент в руках злоумышленника, позволяющий извлекать данные через сообщения об ошибках. Понимание принципов её работы помогает разработчикам и специалистам по безопасности лучше защищать свои приложения. Помните: лучшая защита — это параметризованные запросы и минимизация привилегий базы данных.
Комментарии
—Войдите, чтобы оставить комментарий