Что такое SQL-инъекция через ExtractValue?
SQL-инъекция — один из самых распространённых способов взлома веб-приложений. Злоумышленник внедряет вредоносный SQL-код в запрос, чтобы получить доступ к базе данных. В MySQL существует функция ExtractValue, которая извлекает значение из XML-строки. Однако её можно использовать и для проведения так называемых error-based инъекций: при ошибке MySQL выводит сообщение, содержащее результат внедрённого выражения.
Рассматриваемый запрос: %'))) AND EXTRACTVALUE(8167,CONCAT(0x7e,((SELECT (ELT(8167=8167,1)))),0x7e))-- - — это классический пример такой инъекции. Давайте разберём его по частям.
Анатомия запроса
Начнём с начала. Символы %'))) — это попытка закрыть предыдущие кавычки и скобки в оригинальном запросе, чтобы внедрить свой код. Далее идёт AND EXTRACTVALUE(8167, CONCAT(0x7e, ((SELECT (ELT(8167=8167,1)))), 0x7e)). Наконец, -- - — это комментарий, который отсекает оставшуюся часть оригинального запроса.
Функция EXTRACTVALUE(XML, XPath) принимает два аргумента: XML-документ и выражение XPath. Если XPath-выражение некорректно, MySQL генерирует ошибку, в тексте которой отображается переданный XML-фрагмент. Это и используется для извлечения данных.
Роль CONCAT и 0x7e
CONCAT(0x7e, ..., 0x7e) объединяет строки. 0x7e — это шестнадцатеричное представление символа ~ (тильда). Тильда используется как маркер, чтобы в сообщении об ошибке было легко найти извлечённые данные. Например, если результат выражения — 1, то в ошибке появится ~1~.
Функция ELT и условие 8167=8167
ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В нашем случае ELT(8167=8167, 1) — условие 8167=8167 всегда истинно, что даёт 1. Значит, ELT вернёт первый элемент — 1. Это простейший пример; на практике вместо 1 может быть подзапрос, извлекающий имя пользователя, версию базы данных или хэши паролей.
Как это работает на практике
Предположим, уязвимый запрос выглядит так:
SELECT * FROM users WHERE id = '$id';
Если передать в параметр $id наш payload, запрос превратится в:
SELECT * FROM users WHERE id = '%'))) AND EXTRACTVALUE(8167,CONCAT(0x7e,((SELECT (ELT(8167=8167,1)))),0x7e))-- -';
MySQL выполнит EXTRACTVALUE, и поскольку второй аргумент не является корректным XPath, возникнет ошибка вида:
XPATH syntax error: '~1~'
Таким образом, атакующий видит результат выполнения вложенного запроса. Меняя содержимое ELT или добавляя подзапросы, можно извлекать произвольные данные: версию MySQL, текущего пользователя, имена таблиц и колонок, а затем и сами данные.
Какие данные можно извлечь?
- Версия СУБД:
SELECT version(). - Текущий пользователь:
SELECT user(). - Имя базы данных:
SELECT database(). - Список таблиц: через
information_schema.tables. - Данные из таблиц: например, логины и пароли.
Для этого вместо 1 в ELT подставляется соответствующий подзапрос. Например: ELT(1, (SELECT version())).
Меры защиты
Чтобы предотвратить такие атаки, необходимо:
- Использовать подготовленные выражения (prepared statements) с параметризацией. Это самый надёжный способ.
- Экранировать специальные символы при динамическом построении запросов.
- Ограничить права пользователя БД: не давать прав на чтение information_schema и лишних таблиц.
- Отключить вывод ошибок MySQL на продакшене, чтобы атакующий не видел сообщения.
- Использовать WAF (Web Application Firewall) для фильтрации подозрительных запросов.
Важно понимать, что EXTRACTVALUE — не единственная функция для error-based инъекций. Аналогично работают UPDATEXML, GTID_SUBSET и другие. Поэтому защита должна быть комплексной.
Заключение
Запрос %'))) AND EXTRACTVALUE(8167,CONCAT(0x7e,((SELECT (ELT(8167=8167,1)))),0x7e))-- - — это учебный пример SQL-инъекции, демонстрирующий возможности error-based атак в MySQL. Он показывает, как с помощью функций EXTRACTVALUE, CONCAT и ELT можно заставить базу данных выдать свои данные в сообщении об ошибке. Понимание таких техник необходимо для разработки безопасных приложений и проведения пентестов.
Комментарии
—Войдите, чтобы оставить комментарий