Что такое ExtractValue и при чём тут SQL-инъекции?
Функция ExtractValue в MySQL предназначена для извлечения данных из XML-документа по заданному XPath-выражению. Синтаксис прост: ExtractValue(XML_document, XPath_expression). Однако злоумышленники нашли способ использовать эту функцию для проведения так называемых error-based SQL-инъекций (инъекций, основанных на ошибках). Если приложение не фильтрует пользовательский ввод и передаёт его в SQL-запрос, атакующий может внедрить вызов ExtractValue с подзапросом, чтобы заставить сервер вернуть данные в тексте ошибки.
Классический пример: )))) AND EXTRACTVALUE(5912,CONCAT(0x7e,((SELECT (ELT(5912=5912,1)))),0x7e))-- -. Здесь символы )))) закрывают скобки предыдущего запроса, затем идёт AND EXTRACTVALUE(...), а -- - комментирует остаток. Внутри ExtractValue передаётся число 5912 (некорректный XPath) и конкатенация тильды (0x7e), результата подзапроса и снова тильды. MySQL попытается вычислить XPath-выражение, потерпит неудачу и выведет сообщение об ошибке, содержащее результат подзапроса. Так хакер узнаёт, например, версию БД или имя пользователя.
Как работает error-based инъекция через ExtractValue
Механизм основан на том, что MySQL при ошибке в XPath возвращает подробное сообщение. Если в XPath подставить конкатенацию с полезной нагрузкой, сервер включит её в текст ошибки. Рассмотрим пошагово:
- Приложение выполняет запрос вида
SELECT * FROM users WHERE id = '$input'. - Злоумышленник передаёт
$input = 1 AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT database()), 0x7e)). - MySQL вычисляет
EXTRACTVALUE(1, ...), но первый аргумент — не XML, поэтому возникает ошибка:XPATH syntax error: '~имя_базы~'. - В ответе сервера (если вывод ошибок включён) появляется имя текущей базы данных.
Таким образом, ExtractValue позволяет извлекать произвольные данные: версию MySQL, имена таблиц, логины и пароли. Ограничение — длина вывода не более 32 символов. Для обхода используют функцию SUBSTRING() или MID(), по частям считывая длинные строки.
Примеры полезных нагрузок
Вот несколько типичных конструкций, которые применяют пентестеры и злоумышленники:
AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e))— версия СУБД.AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT user()), 0x7e))— текущий пользователь MySQL.AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT group_concat(schema_name) FROM information_schema.schemata), 0x7e))— список всех баз данных (обрезается до 32 символов).AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT table_name FROM information_schema.tables WHERE table_schema=database() LIMIT 0,1), 0x7e))— первая таблица в текущей БД.
Аналогичный результат даёт функция UpdateXML(), также основанная на XPath. Обе функции опасны, если приложение возвращает ошибки СУБД пользователю.
Ограничения и обход защиты
Главное ограничение — 32 символа. Чтобы получить больше данных, атакующий использует SUBSTRING((SELECT ...), 1, 32), затем SUBSTRING(..., 33, 32) и так далее. Также можно применять LIMIT для перебора строк. Ещё одна сложность — необходимость включать вывод ошибок. Если приложение скрывает ошибки, error-based инъекция не сработает, и хакер переключится на blind-инъекции.
Как защититься от инъекций через ExtractValue
Основной метод — параметризованные запросы (prepared statements). Они не позволяют пользовательскому вводу влиять на структуру SQL. Дополнительные меры:
- Экранирование специальных символов (но лучше параметризация).
- Отключение вывода ошибок СУБД в production-окружении.
- Использование ORM или query builder, которые автоматически экранируют данные.
- Регулярный аудит кода и пентесты.
- Применение WAF для блокировки подозрительных конструкций.
Важно понимать: ExtractValue — не уязвимость сама по себе, а инструмент. Опасность возникает при беспечной разработке.
Заключение
Функция ExtractValue в MySQL может стать мощным оружием в руках злоумышленника, если приложение уязвимо к SQL-инъекциям. Понимание механизма error-based атак помогает разработчикам и специалистам по безопасности своевременно закрывать бреши. Помните: лучшая защита — параметризованные запросы и минимизация вывода технической информации.
Комментарии
—Войдите, чтобы оставить комментарий