Что такое SQL-инъекция через EXTRACTVALUE?

SQL-инъекция — один из самых распространённых способов взлома веб-приложений. Злоумышленники вставляют вредоносный код в SQL-запросы, чтобы получить доступ к данным, изменить их или выполнить произвольные команды. Один из методов основан на функции EXTRACTVALUE в СУБД MySQL. Эта функция предназначена для извлечения данных из XML-документов с помощью XPath-выражений, но при неправильной обработке пользовательского ввода она может стать инструментом атаки.

В запросе пользователя мы видим классический пример эксплуатации: ') AND EXTRACTVALUE(3443,CONCAT(0x7e,((SELECT (ELT(3443=3443,1)))),0x7e))-- -. Здесь злоумышленник пытается вызвать ошибку, которая выведет результат подзапроса. Разберём этот механизм подробно.

Как работает функция EXTRACTVALUE в MySQL

EXTRACTVALUE принимает два строковых аргумента: фрагмент XML-разметки и XPath-выражение (локатор). Функция возвращает текст (CDATA) первого текстового узла, который является дочерним для элемента, соответствующего XPath. Если XPath-выражение некорректно, MySQL генерирует ошибку.

Пример корректного использования:

SELECT EXTRACTVALUE('<a>текст</a>', '/a');
-- Результат: 'текст'

Однако если второй аргумент содержит недопустимые символы, например, тильду (~) или другие специальные знаки, MySQL выдаёт ошибку вида: XPATH syntax error: '~...'. Эта ошибка содержит фрагмент переданного XPath, что позволяет злоумышленнику извлечь данные.

Разбор вредоносного запроса

Рассмотрим запрос: ') AND EXTRACTVALUE(3443,CONCAT(0x7e,((SELECT (ELT(3443=3443,1)))),0x7e))-- -.

  • ') — закрывает предыдущий оператор и строковый литерал, внедряясь в исходный SQL-запрос.
  • AND — добавляет логическое условие, чтобы запрос оставался синтаксически верным.
  • EXTRACTVALUE(3443, ...) — первый аргумент 3443 — это просто число, которое преобразуется в строку. Второй аргумент — результат CONCAT.
  • CONCAT(0x7e, (SELECT ...), 0x7e) — объединяет тильды (0x7e — шестнадцатеричный код символа ~) с результатом подзапроса.
  • (SELECT (ELT(3443=3443,1))) — подзапрос, который возвращает 1, если условие 3443=3443 истинно (а оно всегда истинно), с помощью функции ELT (возвращает N-й элемент списка).
  • -- - — комментарий, обрезающий остаток исходного запроса.

В результате MySQL пытается выполнить EXTRACTVALUE с XPath, содержащим тильды и значение 1. Так как XPath невалиден, возникает ошибка, в тексте которой отображается переданная строка, например: XPATH syntax error: '~1~'. Это позволяет атакующему узнать результат подзапроса — в данном случае число 1.

Цели и последствия атаки

Основная цель таких инъекций — извлечение конфиденциальных данных из базы: имён пользователей, паролей, номеров кредитных карт и т.д. Используя ошибки EXTRACTVALUE, злоумышленник может посимвольно вытаскивать информацию, подставляя в подзапрос функции вроде SUBSTRING, ASCII и другие. Например, чтобы узнать имя пользователя, можно сформировать запрос, который вернёт первый символ имени, и так далее.

Последствия успешной атаки могут быть катастрофическими: утечка данных, компрометация учётных записей, полный контроль над базой данных и даже над сервером.

Как защититься от SQL-инъекций через EXTRACTVALUE

Главный принцип — никогда не доверять пользовательскому вводу. Вот ключевые меры защиты:

  1. Используйте параметризованные запросы (prepared statements). Это самый надёжный способ: данные передаются отдельно от SQL-кода, и СУБД не интерпретирует их как часть запроса.
  2. Применяйте хранимые процедуры. Они также позволяют отделить код от данных, если внутри них используются параметры.
  3. Экранируйте специальные символы. Если параметризация невозможна, используйте функции экранирования, предоставляемые драйвером БД (например, mysqli_real_escape_string в PHP).
  4. Ограничьте права пользователя БД. Учётная запись веб-приложения должна иметь минимально необходимые привилегии: только SELECT, INSERT, UPDATE, DELETE для нужных таблиц, без прав на выполнение опасных функций и доступ к системным таблицам.
  5. Отключите вывод ошибок MySQL в продакшене. Ошибки не должны показываться пользователю, чтобы не давать подсказок атакующему. Логируйте их на сервере.
  6. Регулярно обновляйте СУБД и библиотеки. В новых версиях MySQL функция EXTRACTVALUE помечена как устаревшая (deprecated), и её использование не рекомендуется. Переходите на современные методы работы с XML, например, функцию XMLQUERY.
  7. Проводите аудит кода и сканирование уязвимостей. Используйте инструменты статического анализа и пентесты.
Помните: безопасность — это процесс, а не разовое действие. Регулярно проверяйте свои приложения на уязвимости и следите за обновлениями безопасности.

Заключение

SQL-инъекция через EXTRACTVALUE — яркий пример того, как даже безобидная функция может стать оружием в руках злоумышленника. Понимание механизмов атаки помогает разработчикам и администраторам баз данных эффективно защищаться. Используйте параметризованные запросы, ограничивайте права и не выводите ошибки СУБД пользователю — это сведёт риск к минимуму.

Источники