Что такое SQL-инъекция через EXTRACTVALUE?
SQL-инъекция — один из самых распространённых способов взлома веб-приложений. Злоумышленник внедряет вредоносный код в SQL-запрос, чтобы получить доступ к базе данных. Error-based SQL-инъекция — это техника, при которой атакующий заставляет сервер выдать сообщение об ошибке, содержащее полезные данные. Функция EXTRACTVALUE в MySQL как раз используется для таких атак: она извлекает значение из XML-документа по заданному XPath-выражению. Если передать некорректный XPath, MySQL выдаст ошибку с указанием переданной строки. Это позволяет извлечь результат подзапроса.
Разбор конкретного запроса
Рассмотрим payload: )) OR EXTRACTVALUE(4809,CONCAT(0x7e,((SELECT (ELT(4809=4809,1)))),0x7e))-- -. Он состоит из нескольких частей:
- )) — закрывающие скобки, которые завершают предыдущие условия в оригинальном SQL-запросе.
- OR — логический оператор, добавляющий новое условие.
- EXTRACTVALUE(4809, ...) — вызов функции с первым аргументом 4809 (это просто число, может быть любым).
- CONCAT(0x7e, ((SELECT (ELT(4809=4809,1)))), 0x7e) — конкатенация символа ~ (0x7e), результата подзапроса и снова ~.
- -- - — комментарий, обрезающий остаток оригинального запроса.
Как работает ELT и SELECT
Выражение ELT(4809=4809,1) возвращает первый аргумент, если условие истинно. Так как 4809=4809 всегда истина, ELT вернёт 1. Подзапрос (SELECT (ELT(4809=4809,1))) вернёт 1. Затем CONCAT объединяет ~, 1 и ~, получается строка ~1~. Эта строка передаётся в EXTRACTVALUE как XPath-выражение. Поскольку ~1~ не является валидным XPath, MySQL сгенерирует ошибку: XPATH syntax error: '~1~'. В реальной атаке вместо 1 подставляется подзапрос, извлекающий данные (например, имя пользователя или хеш пароля).
Зачем нужен EXTRACTVALUE в атаках?
MySQL поддерживает функции для работы с XML: EXTRACTVALUE и UPDATEXML. Обе могут вызывать ошибки, содержащие переданные данные. Это делает их удобными для error-based инъекций. Например, запрос EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e)) выведет версию MySQL в сообщении об ошибке. Злоумышленники используют такие конструкции, чтобы пошагово извлекать информацию: имена таблиц, столбцов, данные пользователей.
Примеры эксплуатации
Вот как может выглядеть реальная атака на уязвимый параметр:
http://site.com/product.php?id=1)) OR EXTRACTVALUE(1,CONCAT(0x7e,(SELECT database()),0x7e))-- -
Если приложение уязвимо, в ответе появится ошибка с именем текущей базы данных. Аналогично можно извлечь таблицы:
... OR EXTRACTVALUE(1,CONCAT(0x7e,(SELECT table_name FROM information_schema.tables LIMIT 0,1),0x7e))-- -
Затем столбцы и сами данные. Ограничение в 1 символ? Нет, EXTRACTVALUE выводит до 32 символов, что позволяет получать целые строки.
Как защититься от таких инъекций
Главный способ — использовать параметризованные запросы (prepared statements). Они разделяют код и данные, поэтому внедрение SQL-кода становится невозможным. Если приложение написано на PHP, используйте PDO или MySQLi с подготовленными выражениями. Также необходимо:
- Проводить валидацию всех входных данных, особенно тех, что попадают в SQL.
- Ограничить права пользователя базы данных: не давать ему доступ к information_schema без необходимости.
- Отключить вывод ошибок MySQL на продакшене, чтобы атакующий не видел сообщений.
- Использовать WAF (Web Application Firewall) для фильтрации подозрительных запросов.
- Регулярно обновлять СУБД и фреймворки.
Важно понимать: даже если ошибки не выводятся, слепая SQL-инъекция всё ещё возможна. Поэтому параметризация — обязательна.
Заключение
Payload )) OR EXTRACTVALUE(4809,CONCAT(0x7e,((SELECT (ELT(4809=4809,1)))),0x7e))-- - — это учебный пример error-based SQL-инъекции. Он демонстрирует, как через функцию EXTRACTVALUE и подзапрос можно заставить MySQL выдать данные в сообщении об ошибке. Понимание таких техник помогает разработчикам и пентестерам лучше защищать веб-приложения. Никогда не используйте подобные знания во вред — только для легального тестирования на проникновение с разрешения владельца системы.
Комментарии
—Войдите, чтобы оставить комментарий