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

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

В запросе, который мы анализируем, используется следующая конструкция:

%")) AND EXTRACTVALUE(2464,CONCAT(0x7e,((SELECT (ELT(2464=2464,1)))),0x7e))-- -

Этот фрагмент предназначен для внедрения в уязвимый параметр веб-приложения. Давайте разберём его по частям.

Разбор структуры инъекции

Начнём с начала:

  • %")) — это попытка закрыть существующий SQL-запрос. Символ % может быть частью URL-кодирования, а ")) закрывает кавычку и скобки, чтобы вставить свой код.
  • AND EXTRACTVALUE(2464,CONCAT(0x7e,((SELECT (ELT(2464=2464,1)))),0x7e)) — это основная часть инъекции. Функция EXTRACTVALUE принимает два аргумента: XML-документ и XPath-выражение. В данном случае первый аргумент — число 2464 (некорректный XML), а второй — конкатенация тильды (0x7e), результата подзапроса и ещё одной тильды.
  • -- - — это комментарий, который обрезает оставшуюся часть оригинального запроса, чтобы не возникло синтаксической ошибки.

Подзапрос SELECT (ELT(2464=2464,1)) возвращает 1, если условие 2464=2464 истинно (а это всегда так). Функция ELT возвращает N-й элемент из списка; здесь список состоит из одного элемента 1, поэтому результат — 1. Таким образом, CONCAT(0x7e, 1, 0x7e) даёт строку ~1~.

Функция EXTRACTVALUE(2464, '~1~') пытается применить XPath-выражение ~1~ к числу 2464, что вызывает ошибку XPath. MySQL выдаст сообщение об ошибке, содержащее переданное XPath-выражение, то есть ~1~. Это позволяет атакующему увидеть результат выполнения подзапроса.

Зачем это нужно злоумышленнику?

Основная цель — извлечь данные из базы. Вместо 1 в подзапрос можно подставить вызов любой функции или поля, например, SELECT user() или SELECT password FROM users LIMIT 1. Тогда в сообщении об ошибке отобразится имя пользователя или пароль. Поскольку ошибка выводится на страницу (если приложение не подавляет ошибки), атакующий получает конфиденциальную информацию.

Это классический пример error-based SQL-инъекции, который работает в MySQL версий 5.1 и выше, где функция EXTRACTVALUE доступна и генерирует подробные ошибки.

Пример работы в реальных условиях

Рассмотрим упрощённый пример. Предположим, есть уязвимый параметр id, и запрос выглядит так:

SELECT * FROM products WHERE id = '$id'

Если передать 1' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e))-- -, то база данных выполнит подзапрос, получит версию MySQL, например 5.7.23, и попытается использовать её как XPath. Возникнет ошибка вида:

XPATH syntax error: '~5.7.23~'

Таким образом, атакующий узнаёт версию СУБД. Аналогично можно извлечь имена таблиц, колонок и сами данные.

Модификации и обход фильтров

В приведённом запросе используется ELT(2464=2464,1) — это, по сути, проверка на истинность, которая всегда возвращает 1. Такая конструкция может применяться для тестирования уязвимости или для обхода простых фильтров, которые блокируют определённые ключевые слова. Например, если фильтр запрещает слово SELECT сразу после EXTRACTVALUE, можно использовать вложенные запросы или функции.

Также часто применяют CONCAT с шестнадцатеричными литералами (0x7e — это тильда ~), чтобы избежать использования кавычек, которые могут экранироваться.

Как защититься от таких атак?

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

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

Также рекомендуется использовать WAF (Web Application Firewall), который может блокировать подозрительные запросы, содержащие EXTRACTVALUE или другие функции, часто используемые в атаках.

Заключение

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

Источники