Что такое ExtractValue и при чём тут SQL-инъекции?

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

Однако эта безобидная на первый взгляд функция стала популярным инструментом в арсенале злоумышленников. Дело в том, что при передаче некорректного XPath-выражения MySQL генерирует сообщение об ошибке, в которое попадает переданная строка. Это позволяет реализовать так называемую ошибко-ориентированную SQL-инъекцию (error-based SQL injection).

Как работает ошибко-ориентированная инъекция через ExtractValue

Суть метода заключается в том, чтобы заставить базу данных вывести конфиденциальную информацию в тексте ошибки. Злоумышленник формирует вредоносный SQL-запрос, в котором функция EXTRACTVALUE вызывается с заведомо неправильным XPath, содержащим результат подзапроса, например:

AND EXTRACTVALUE(1838, CONCAT(0x7e, ((SELECT (ELT(1838=1838,1)))), 0x7e))-- -

Здесь 0x7e — это шестнадцатеричное представление тильды (~), которая используется как маркер для облегчения поиска выводимых данных в сообщении об ошибке. Конструкция ELT(1838=1838,1) возвращает 1, если условие истинно. В данном примере проверяется тривиальное равенство, но на практике вместо него подставляются подзапросы, извлекающие имена таблиц, колонок или конкретные значения из базы данных.

Когда MySQL пытается вычислить XPath-выражение, содержащее недопустимые символы (например, тильду или результат подзапроса), он выдаёт ошибку вида:

XPATH syntax error: '~1~'

Таким образом, атакующий может пошагово извлекать данные, изменяя подзапрос и анализируя текст ошибок.

Пример эксплуатации на практике

Рассмотрим типичный сценарий. Предположим, на сайте есть уязвимый параметр id в URL: https://example.com/product.php?id=1. Злоумышленник может добавить к нему следующий код:

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

В ответе сервера появится сообщение об ошибке, содержащее имя текущей базы данных. Аналогично можно получить версию MySQL, имена таблиц, колонок и даже хэши паролей пользователей. Для этого используются подзапросы к information_schema.tables и другим системным таблицам.

Более сложные вариации включают ограничение вывода с помощью LIMIT и смещение OFFSET, чтобы извлекать данные по частям. Например, чтобы получить имя второй колонки, меняют значение в LIMIT 1,1 и так далее.

Какие функции MySQL ещё используют для ошибко-ориентированных инъекций?

Помимо EXTRACTVALUE, злоумышленники часто применяют:

  • UPDATEXML() — аналогичная функция для работы с XML, также генерирующая ошибки с переданной строкой.
  • FLOOR() в связке с RAND() и группировкой — вызывает ошибку дублирования ключа, в которую попадает результат подзапроса.
  • EXP() — переполнение при больших значениях приводит к ошибке с полезной нагрузкой.
  • NAME_CONST() — может использоваться для вызова ошибок с внедрёнными данными.

Однако EXTRACTVALUE и UPDATEXML считаются наиболее удобными, так как позволяют напрямую контролировать содержимое сообщения об ошибке.

Чем опасна такая инъекция?

Ошибко-ориентированная SQL-инъекция через EXTRACTVALUE даёт атакующему возможность:

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

Особенность метода в том, что он не требует вывода данных на страницу — достаточно, чтобы сообщения об ошибках отображались пользователю. Даже если ошибки скрыты, атакующий может использовать слепые техники, но это уже другой класс инъекций.

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

Основной принцип защиты — никогда не доверять пользовательскому вводу и использовать параметризованные запросы (prepared statements). Это полностью исключает возможность внедрения SQL-кода, так как данные передаются отдельно от запроса и не интерпретируются как часть SQL.

Дополнительные меры:

  1. Экранирование специальных символов — если по каким-то причинам нельзя использовать параметризацию, применяйте функции экранирования, предоставляемые драйвером базы данных.
  2. Ограничение прав пользователя БД — учётная запись, от имени которой работает веб-приложение, должна иметь минимально необходимые привилегии. Не давайте ей доступ к системным таблицам без надобности.
  3. Отключение вывода ошибок — в production-окружении сообщения об ошибках СУБД не должны показываться пользователю. Логируйте их, но не отображайте.
  4. Использование WAF — веб-приложения-экраны могут блокировать подозрительные конструкции, такие как EXTRACTVALUE, UPDATEXML и другие.
  5. Регулярное обновление MySQL — в новых версиях некоторые функции могут быть удалены или изменены, что снижает риск.

Также рекомендуется проводить регулярные аудиты кода и пентесты для выявления уязвимостей.

Заключение

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

Источники