Что такое ExtractValue и при чём тут SQL-инъекция?
Функция ExtractValue в СУБД MySQL предназначена для извлечения значения из XML-документа по указанному XPath-выражению. Синтаксис: ExtractValue(XML_document, XPath_expression). Однако при некорректном использовании она может стать инструментом для проведения error-based SQL-инъекций. Злоумышленники передают в функцию специально сформированные XPath-выражения, которые вызывают ошибки, содержащие результаты выполнения вложенных SQL-запросов. Это позволяет извлекать данные из базы, даже если прямой вывод информации заблокирован.
Рассматриваемый запрос: %")) AND EXTRACTVALUE(3432,CONCAT(0x7e,((SELECT (ELT(3432=3432,1)))),0x7e))-- - — типичный пример такой инъекции. Давайте разберём его по частям.
Анатомия вредоносного запроса
Разберём приведённую строку:
%"))— попытка закрыть предыдущие кавычки и скобки, чтобы внедрить свой код.AND EXTRACTVALUE(3432,CONCAT(0x7e,((SELECT (ELT(3432=3432,1)))),0x7e))— вызов уязвимой функции. Первый аргумент (3432) — произвольное число, второй — конкатенация тильды (0x7e), результата подзапроса и снова тильды.SELECT (ELT(3432=3432,1))— возвращает 1, так как условие 3432=3432 истинно. ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь список состоит из одного элемента '1'.-- -— комментарий, обрезающий остаток оригинального запроса.
В результате MySQL попытается вычислить XPath-выражение, содержащее символ ~ (0x7e), что вызовет ошибку вида XPATH syntax error: '~1~'. В текст ошибки попадёт результат подзапроса — в данном случае '1'. Злоумышленник может заменить ELT(3432=3432,1) на любой другой подзапрос, например, (SELECT password FROM users LIMIT 1), и получить его результат в сообщении об ошибке.
Как работает error-based SQL-инъекция через ExtractValue
Error-based инъекции эксплуатируют вывод сообщений об ошибках СУБД на страницу. Если приложение не подавляет ошибки, атакующий может заставить базу данных вернуть нужные данные в тексте ошибки. ExtractValue — один из классических векторов для MySQL (наряду с UpdateXML и GeometryCollection).
Механизм прост: функция ExtractValue при невалидном XPath генерирует ошибку, в которую включает часть переданного выражения. Если в это выражение встроить подзапрос, его результат окажется в сообщении об ошибке.
Для успешной атаки необходимо, чтобы:
- Приложение было уязвимо к SQL-инъекции (например, не использует параметризованные запросы).
- Выводились сообщения об ошибках MySQL (или они логировались и были доступны атакующему).
- Версия MySQL поддерживала функцию ExtractValue (доступна с 5.1).
Последствия успешной эксплуатации
Если злоумышленник может выполнить такую инъекцию, он способен:
- Извлечь содержимое базы данных: логины, пароли, персональные данные, номера карт.
- Получить доступ к административной панели.
- Изменить или удалить данные.
- В некоторых случаях — выполнить команды на сервере (при наличии соответствующих привилегий).
По данным OWASP, SQL-инъекции остаются одной из самых распространённых и опасных уязвимостей веб-приложений.
Как защититься от инъекций через ExtractValue
Основной метод — параметризованные запросы (prepared statements). Они разделяют код SQL и данные, поэтому внедрение произвольного SQL-кода становится невозможным. Дополнительные меры:
- Использовать ORM (например, Hibernate, Entity Framework) с правильной настройкой.
- Экранировать все пользовательские данные, попадающие в SQL-запросы (но это менее надёжно, чем параметризация).
- Отключить вывод ошибок СУБД на продакшене — это затруднит error-based инъекции.
- Применять принцип наименьших привилегий для учётной записи БД: не давать прав на чтение системных таблиц, если они не нужны.
- Регулярно обновлять СУБД и использовать WAF (Web Application Firewall) для фильтрации подозрительных запросов.
Важно понимать: ExtractValue — не единственная функция, уязвимая к подобным атакам. UpdateXML, EXTRACTVALUE, GeometryCollection и другие могут быть использованы аналогично. Поэтому защита должна быть комплексной.
Пример безопасного кода на PHP
Вместо уязвимого запроса:
$id = $_GET['id'];
$query = "SELECT * FROM products WHERE id = $id";
Следует использовать подготовленные выражения:
$stmt = $pdo->prepare('SELECT * FROM products WHERE id = :id');
$stmt->execute(['id' => $_GET['id']]);
Такой подход полностью исключает возможность инъекции, включая сложные конструкции с ExtractValue.
Заключение
Запрос %")) AND EXTRACTVALUE(3432,CONCAT(0x7e,((SELECT (ELT(3432=3432,1)))),0x7e))-- - — это попытка эксплуатации error-based SQL-инъекции через функцию ExtractValue в MySQL. Понимание механизма таких атак помогает разработчикам и администраторам своевременно закрывать уязвимости. Главный совет: никогда не подставляйте пользовательские данные в SQL-запросы напрямую, используйте параметризацию и следите за обновлениями безопасности.
Комментарии
—Войдите, чтобы оставить комментарий