Что такое EXTRACTVALUE и зачем он в SQL-инъекции
Строка ')) AND EXTRACTVALUE(4203,CONCAT(0x7e,((SELECT (ELT(4203=4203,1)))),0x7e))-- - — это классический пример error-based SQL-инъекции, использующей функцию MySQL EXTRACTVALUE. Эта функция предназначена для работы с XML: она извлекает значение из XML-документа по заданному XPath-выражению. Однако злоумышленники научились применять её для вывода данных через сообщения об ошибках.
Функция EXTRACTVALUE(XML, XPath) принимает два аргумента: XML-строку и XPath-выражение. Если XPath-выражение синтаксически некорректно, MySQL генерирует ошибку, в тексте которой отображается переданное значение. Это позволяет атакующему «вытащить» результат подзапроса, если поместить его в XPath-выражение.
Разбор полезной нагрузки
Рассмотрим строку по частям:
'))— закрывает ранее открытые скобки и кавычки в уязвимом SQL-запросе. Два символа)и одна кавычка'подобраны под конкретный контекст (например, запрос видаSELECT ... WHERE id = ('...')).AND— логический оператор, добавляющий условие к оригинальному запросу.EXTRACTVALUE(4203, CONCAT(0x7e, ((SELECT (ELT(4203=4203,1)))), 0x7e))— вызов функции с заведомо некорректным XPath, чтобы вызвать ошибку и вывести результат подзапроса.-- -— комментарий, обрезающий остаток оригинального запроса (пробел после--обязателен в MySQL).
Зачем нужен ELT и выражение 4203=4203
Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В нашем случае ELT(4203=4203, 1) — первым аргументом идёт логическое выражение 4203=4203, которое всегда истинно (равно 1). Значит, ELT(1, 1) вернёт строку '1'. Это простейший тест: если инъекция работает, в ошибке появится символ 1, обёрнутый в тильды (0x7e — это шестнадцатеричный код символа ~). Тильды служат маркерами, чтобы легко найти выведенное значение в тексте ошибки.
В реальной атаке вместо ELT(4203=4203,1) подставляют подзапросы, например SELECT version() или SELECT password FROM users LIMIT 1, чтобы извлечь конфиденциальные данные.
Как работает error-based инъекция через EXTRACTVALUE
MySQL при вызове EXTRACTVALUE с некорректным XPath возвращает ошибку вида:
XPATH syntax error: '~1~'
Таким образом, всё, что было передано в XPath (в нашем случае CONCAT(0x7e, результат_подзапроса, 0x7e)), отображается в сообщении об ошибке. Это позволяет атакующему получать данные посимвольно или целыми строками, если хватает длины сообщения.
Подобные техники описаны в практических руководствах по SQL-инъекциям, например в «MySQL SQL Injection Practical Cheat Sheet» (Pentester Skills). Также известны случаи успешного применения EXTRACTVALUE на пентестах.
Другие функции для error-based атак
Помимо EXTRACTVALUE, в MySQL существуют аналогичные функции:
UPDATEXML(XML, XPath, new_value)— также вызывает ошибку XPath и выводит данные.GTID_SUBSET(),JSON_KEYS()и другие — в зависимости от версии MySQL.EXP()— переполнение, но не выводит данные напрямую.
С выходом MySQL 8.0 некоторые из этих функций были ограничены, но EXTRACTVALUE всё ещё доступна (хотя и помечена как устаревшая).
Пример уязвимого запроса
Предположим, на сервере выполняется такой код:
$id = $_GET['id'];
$query = "SELECT * FROM products WHERE category = ('$id')";
$result = mysqli_query($link, $query);
Если передать id=1')) AND EXTRACTVALUE(4203,CONCAT(0x7e,((SELECT (ELT(4203=4203,1)))),0x7e))-- -, то итоговый запрос станет:
SELECT * FROM products WHERE category = ('1')) AND EXTRACTVALUE(4203,CONCAT(0x7e,((SELECT (ELT(4203=4203,1)))),0x7e))-- -')
СУБД выполнит подзапрос, сформирует ошибку и вернёт её клиенту (если вывод ошибок включён).
Последствия успешной инъекции
Эксплуатация error-based SQL-инъекции позволяет:
- Получить версию СУБД, имя базы данных, текущего пользователя.
- Извлечь содержимое таблиц: логины, пароли, персональные данные.
- В некоторых случаях выполнить произвольные SQL-команды (если привилегии позволяют).
По данным OWASP, SQL-инъекции остаются одной из самых критичных уязвимостей веб-приложений.
Как защититься от EXTRACTVALUE-инъекций
Основной метод — использование параметризованных запросов (prepared statements). Например, на PHP с MySQLi:
$stmt = $link->prepare("SELECT * FROM products WHERE category = ?");
$stmt->bind_param('s', $id);
$stmt->execute();
Дополнительные меры:
- Отключить вывод ошибок СУБД на продакшене (display_errors = Off).
- Использовать ORM или query builder, которые экранируют данные.
- Применять WAF с сигнатурами для EXTRACTVALUE, UPDATEXML и подобных функций.
- Регулярно обновлять MySQL и применять принцип наименьших привилегий для пользователя БД.
Важно понимать, что фильтрация только слова EXTRACTVALUE неэффективна — злоумышленник может использовать другие функции или обфускацию.
Заключение
Строка ')) AND EXTRACTVALUE(4203,CONCAT(0x7e,((SELECT (ELT(4203=4203,1)))),0x7e))-- - — это учебный пример error-based SQL-инъекции. Она демонстрирует, как небрежная обработка пользовательского ввода и вывод ошибок СУБД могут привести к утечке данных. Разработчикам следует всегда использовать параметризованные запросы и не полагаться на чёрные списки. Понимание таких атак помогает строить надёжную защиту веб-приложений.
Комментарии
—Войдите, чтобы оставить комментарий