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