Что такое SQL-инъекция через EXTRACTVALUE?
SQL-инъекция — один из самых распространённых и опасных видов атак на веб-приложения. Злоумышленник внедряет вредоносный SQL-код в запрос, который приложение отправляет базе данных, и получает доступ к данным, которые не должен видеть. Один из классических методов эксплуатации — error-based SQL-инъекция, при которой хакер заставляет базу данных выдать сообщение об ошибке, содержащее конфиденциальную информацию.
Функция EXTRACTVALUE в MySQL и MariaDB предназначена для работы с XML-документами: она извлекает значение из XML по заданному XPath-выражению. Однако при неправильном использовании она становится инструментом атаки. Запрос ` OR EXTRACTVALUE(9635,CONCAT(0x7e,((SELECT (ELT(9635=9635,1)))),0x7e))-- - — это типичный пример такой инъекции.
Разбор вредоносного запроса
Давайте разберём этот запрос по частям.
`— обратный апостроф, который закрывает исходное поле или строку в уязвимом запросе. Это позволяет выйти за пределы ожидаемого ввода.OR— логический оператор, который делает условие всегда истинным или добавляет дополнительное выражение.EXTRACTVALUE(9635, CONCAT(0x7e, ((SELECT (ELT(9635=9635,1)))), 0x7e))— вызов функции, которая должна вызвать ошибку с внедрёнными данными.-- -— комментарий, который отсекает оставшуюся часть оригинального SQL-запроса.
Внутри EXTRACTVALUE используется CONCAT для формирования строки, которая передаётся как XPath-выражение. Символ 0x7e — это шестнадцатеричное представление тильды (~). Тильда используется как маркер, чтобы потом легко найти внедрённые данные в сообщении об ошибке.
Выражение (SELECT (ELT(9635=9635,1))) — это подзапрос, который возвращает число 1. ELT(9635=9635,1) — функция, возвращающая N-й элемент из списка. Поскольку условие 9635=9635 всегда истинно (равно 1), ELT(1,1) возвращает первый элемент — 1. Таким образом, подзапрос возвращает 1.
Итоговое XPath-выражение, которое попадает в EXTRACTVALUE, выглядит как ~1~. Поскольку это невалидный XPath, MySQL генерирует ошибку: XPATH syntax error: '~1~'. В реальной атаке вместо 1 подставляются имена таблиц, колонок или другие данные, которые хакер хочет извлечь. Ошибка выводится на экран (если включён вывод ошибок), и атакующий получает информацию.
Почему это работает?
MySQL при выполнении EXTRACTVALUE сначала вычисляет все аргументы. XPath-выражение должно быть корректным, иначе функция выбрасывает ошибку. Хитрость в том, что MySQL включает в текст ошибки первые 32 символа переданного XPath. Это позволяет злоумышленнику «вытащить» до 32 байт данных за один запрос, если поместить их в XPath.
В нашем примере внедряется константа 1, но в реальной атаке на её место ставят подзапрос, например: (SELECT table_name FROM information_schema.tables LIMIT 1). Тогда ошибка покажет имя первой таблицы. Поскольку выводится только 32 символа, для длинных строк используют посимвольное извлечение или функции вроде SUBSTRING.
Важно: EXTRACTVALUE удалена в MySQL 8.0.17 и выше, но во многих устаревших системах и MariaDB она всё ещё доступна.
Пошаговый пример эксплуатации
Предположим, есть уязвимый параметр id в URL: http://example.com/product.php?id=1. Запрос в приложении может выглядеть так:
SELECT * FROM products WHERE id = '1';
Атакующий подставляет:
1' OR EXTRACTVALUE(9635,CONCAT(0x7e,(SELECT database()),0x7e))-- -
В результате MySQL выполнит:
SELECT * FROM products WHERE id = '1' OR EXTRACTVALUE(9635,CONCAT(0x7e,(SELECT database()),0x7e))-- -';
Если имя базы данных, например, shop_db, то ошибка будет: XPATH syntax error: '~shop_db~'. Так хакер узнаёт имя текущей базы.
Далее можно извлекать таблицы:
1' OR EXTRACTVALUE(9635,CONCAT(0x7e,(SELECT table_name FROM information_schema.tables WHERE table_schema=database() LIMIT 0,1),0x7e))-- -
И так далее, пока не будут получены все нужные данные.
Меры защиты
Чтобы предотвратить error-based SQL-инъекции, необходимо:
- Использовать подготовленные выражения (prepared statements). Это самый надёжный способ, при котором данные не смешиваются с кодом SQL.
- Отключить вывод ошибок СУБД на продакшене. Сообщения об ошибках не должны попадать в браузер.
- Применять принцип наименьших привилегий. Учётная запись БД для веб-приложения не должна иметь прав на чтение системных таблиц.
- Регулярно обновлять СУБД и фреймворки. В новых версиях MySQL опасные функции удалены или исправлены.
- Использовать WAF (Web Application Firewall). Он может блокировать подозрительные запросы, содержащие
EXTRACTVALUEилиCONCATс тильдами.
Также рекомендуется проводить аудит кода и пентесты для выявления уязвимостей.
Заключение
Запрос ` OR EXTRACTVALUE(9635,CONCAT(0x7e,((SELECT (ELT(9635=9635,1)))),0x7e))-- - — это учебный пример error-based SQL-инъекции, демонстрирующий, как ошибки базы данных могут стать каналом утечки информации. Понимание механики таких атак помогает разработчикам и специалистам по безопасности правильно защищать свои приложения. Никогда не доверяйте пользовательскому вводу и всегда используйте параметризованные запросы.
Комментарии
—Войдите, чтобы оставить комментарий