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

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

Функция EXTRACTVALUE() в MySQL используется для извлечения значения из XML-документа по заданному XPath-выражению. Однако хакеры научились применять её для вывода данных через ошибки. Синтаксис запроса, который вы видите в заголовке, — это классический пример такой атаки.

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

Рассмотрим строку: `) OR EXTRACTVALUE(5498,CONCAT(0x7e,((SELECT (ELT(5498=5498,1)))),0x7e))-- -

Она состоит из нескольких частей:

  • `) OR ... -- - — это попытка закрыть предыдущий запрос и добавить своё условие. Символы `) используются для завершения оригинального выражения, например, если уязвимый параметр вставляется в скобки. -- - — комментарий, который игнорирует остаток исходного SQL-запроса.
  • EXTRACTVALUE(5498, CONCAT(...)) — вызов функции. Первый аргумент (5498) — произвольное число, второй — XML-строка, формируемая через CONCAT.
  • 0x7e — шестнадцатеричное представление символа ~ (тильда). Он используется как разделитель, чтобы облегчить чтение выводимых данных в сообщении об ошибке.
  • SELECT (ELT(5498=5498,1)) — подзапрос, который возвращает 1, если условие 5498=5498 истинно (а оно всегда истинно). ELT — функция, возвращающая N-й элемент из списка. Здесь она возвращает 1.
  • Внешний CONCAT объединяет тильду, результат подзапроса и ещё одну тильду. Получается строка вида ~1~.

Когда MySQL пытается обработать EXTRACTVALUE с некорректным XPath (а строка ~1~ не является валидным XPath), генерируется ошибка: XPATH syntax error: '~1~'. В этом сообщении и утекают данные. В данном примере выводятся просто цифры, но если вместо ELT(5498=5498,1) подставить подзапрос, извлекающий имя пользователя, версию БД или хэши паролей, они окажутся в тексте ошибки.

Зачем нужна такая инъекция?

Error-based инъекции особенно удобны, когда приложение не выводит результаты запроса напрямую (например, при слепой инъекции), но отображает ошибки базы данных. Это позволяет атакующему по крупицам извлекать информацию: имена таблиц, колонок, логины, пароли. Функция EXTRACTVALUE — не единственная; также часто используются UPDATEXML и GTID_SUBSET.

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

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

Чтобы извлечь, например, версию базы данных, злоумышленник может заменить ELT(5498=5498,1) на SELECT version(). Запрос примет вид:

`) OR EXTRACTVALUE(5498,CONCAT(0x7e,(SELECT version()),0x7e))-- -

В ответе СУБД появится ошибка с номером версии. Аналогично можно получить имя текущего пользователя (user()), имя базы данных (database()) и другие сведения.

Как защититься от error-based SQL-инъекций?

Основные меры защиты:

  1. Использование подготовленных выражений (prepared statements). Параметризация запросов не даёт внедрить произвольный SQL-код.
  2. Экранирование специальных символов. Если по каким-то причинам нельзя использовать параметризацию, необходимо тщательно фильтровать ввод, особенно символы кавычек, скобок и комментариев.
  3. Отключение вывода ошибок СУБД в production. Сообщения об ошибках не должны попадать в браузер пользователя — их следует логировать на сервере.
  4. Регулярное обновление СУБД и фреймворков. В новых версиях MySQL некоторые опасные функции могут быть удалены или ограничены.
  5. Использование WAF (Web Application Firewall). Современные WAF умеют распознавать шаблоны SQL-инъекций, включая EXTRACTVALUE.

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

Заключение

Запрос `) OR EXTRACTVALUE(5498,CONCAT(0x7e,((SELECT (ELT(5498=5498,1)))),0x7e))-- - — это учебный пример эксплуатации error-based SQL-инъекции через функцию EXTRACTVALUE. Он демонстрирует, как с помощью ошибок СУБД можно выводить данные. Знание таких техник необходимо специалистам по информационной безопасности для защиты систем. Разработчикам же следует всегда использовать параметризованные запросы и не выводить ошибки базы данных конечным пользователям.

Источники