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

SQL-инъекция — один из самых распространённых способов взлома веб-приложений. Злоумышленники внедряют вредоносный SQL-код в поля ввода, URL-параметры или cookie, чтобы получить доступ к базе данных. Среди множества техник особое место занимает error-based SQL-инъекция, при которой хакер заставляет сервер выдать сообщение об ошибке, содержащее конфиденциальные данные. Функция EXTRACTVALUE в MySQL — классический инструмент для такой атаки.

EXTRACTVALUE — это встроенная функция MySQL, предназначенная для извлечения значения из XML-документа по заданному XPath-выражению. Она принимает два аргумента: фрагмент XML и путь XPath. Если XPath-выражение синтаксически неверно, MySQL генерирует ошибку, в тексте которой отображается переданный фрагмент. Этим и пользуются злоумышленники: они подставляют в XPath результат подзапроса, и сервер сам «печатает» украденные данные в сообщении об ошибке.

Синтаксис и принцип работы EXTRACTVALUE

Официальное описание функции:

EXTRACTVALUE(XML_frag, XPath_expr)

Функция возвращает текст первого текстового узла, соответствующего XPath-выражению. Если совпадений нет или XPath некорректен, возвращается пустая строка или возникает ошибка. Ключевая особенность: при ошибке в XPath MySQL выводит сообщение вида XPATH syntax error: '...', где ... — это часть переданного XPath. Именно туда внедряется полезная нагрузка.

Пример уязвимого запроса:

SELECT * FROM users WHERE id = '$_GET[id]';

Если параметр id не фильтруется, злоумышленник может передать:

1' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e))-- -

В результате MySQL попытается вычислить XPath ~версия_MySQL~, что вызовет ошибку с текстом, содержащим версию СУБД. Так хакер узнаёт информацию о сервере.

Разбор конкретного запроса: "))) AND EXTRACTVALUE(2937,CONCAT(0x7e,((SELECT (ELT(2937=2937,1)))),0x7e))-- -

Этот запрос — типичный пример error-based инъекции, адаптированный под конкретные условия. Рассмотрим его по частям:

  • "))) — закрывающие кавычки и скобки, завершающие оригинальный SQL-запрос, чтобы внедрить свой код.
  • AND EXTRACTVALUE(2937, ...) — добавляет условие с вызовом функции. Первый аргумент (2937) — произвольный XML-фрагмент, он не важен.
  • CONCAT(0x7e, ((SELECT (ELT(2937=2937,1)))), 0x7e) — формирует XPath-строку. 0x7e — это тильда (~), используется как маркер начала и конца выводимых данных.
  • (SELECT (ELT(2937=2937,1))) — подзапрос, возвращающий 1, если условие 2937=2937 истинно. ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь список — просто 1. Это демонстрационный пример; на практике вместо ELT подставляют имена таблиц, столбцов или хеши паролей.
  • -- - — комментарий, обрезающий остаток оригинального запроса.

При выполнении MySQL попытается интерпретировать строку ~1~ как XPath. Поскольку это недопустимое выражение, возникнет ошибка: XPATH syntax error: '~1~'. В реальной атаке вместо 1 подставляется результат подзапроса, например, (SELECT password FROM users LIMIT 1), и в ошибке отобразится пароль.

Пошаговый пример эксплуатации

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

1' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT database()), 0x7e))-- -

Сервер вернёт ошибку: XPATH syntax error: '~mydb~'. Аналогично можно извлечь версию, пользователя, список таблиц и любые данные. Если приложение не выводит ошибки на экран, хакер может использовать слепую инъекцию, анализируя поведение страницы.

Меры защиты от SQL-инъекций

Главный способ предотвратить атаку — использовать параметризованные запросы (prepared statements). Они разделяют код и данные, поэтому внедрённый SQL не выполняется. Дополнительные меры:

  • Экранирование специальных символов с помощью функций вроде mysqli_real_escape_string.
  • Валидация и фильтрация входных данных по белому списку.
  • Отключение вывода подробных ошибок БД в продакшене.
  • Использование ORM и современных фреймворков, которые по умолчанию защищают от инъекций.
  • Регулярное обновление СУБД и веб-приложений.

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

Заключение

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

Источники