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

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

В запросе пользователя мы видим классический пример такой инъекции: ') AND EXTRACTVALUE(5149,CONCAT(0x7e,((SELECT (ELT(5149=5149,1)))),0x7e))-- -. Давайте разберём его по частям.

Разбор полезной нагрузки

Начнём с синтаксиса:

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

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

Как работает ExtractValue в MySQL

Функция ExtractValue принимает два аргумента: XML-документ и выражение XPath. Если XPath-выражение некорректно, MySQL возвращает ошибку с указанием проблемного фрагмента. Например:

ERROR 1105 (HY000): XPATH syntax error: '~1~'

В нашем случае из-за добавления тильд вокруг результата подзапроса возникает ошибка, и в тексте ошибки отображается значение ~1~. Злоумышленник может заменить 1 на любой другой запрос, например, (SELECT user()), чтобы получить имя пользователя базы данных.

Этот метод известен как error-based SQL injection. Он особенно опасен тем, что не требует вывода данных на страницу — достаточно, чтобы приложение показывало ошибки SQL.

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

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

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

Если приложение уязвимо, в ответе появится ошибка вида XPATH syntax error: '~имя_базы~'.

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

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

Чтобы предотвратить подобные атаки, необходимо соблюдать следующие правила:

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

Также рекомендуется регулярно обновлять СУБД и проводить аудит кода на наличие уязвимостей.

Заключение

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

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

Источники