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

Строка вида %")) AND EXTRACTVALUE(1282,CONCAT(0x7e,((SELECT (ELT(1282=1282,1)))),0x7e))-- - — это пример error-based SQL-инъекции (SQL-инъекция, основанная на ошибках). Она предназначена для внедрения в уязвимый SQL-запрос с целью получения данных из базы через сообщения об ошибках. В данном случае используется функция MySQL EXTRACTVALUE(), которая извлекает значение из XML-строки по заданному XPath-выражению. Если XPath-выражение некорректно, MySQL генерирует ошибку, содержащую переданные данные.

Злоумышленник конструирует запрос так, чтобы в тексте ошибки вернулась интересующая его информация — например, версия СУБД, имя базы данных, логины и пароли пользователей. Это возможно, если веб-приложение не фильтрует входные данные и передаёт их напрямую в SQL-запрос.

Как работает атака: пошаговый разбор

Рассмотрим фрагмент AND EXTRACTVALUE(1282,CONCAT(0x7e,((SELECT (ELT(1282=1282,1)))),0x7e)).

  • EXTRACTVALUE(1282, ...) — первый аргумент (1282) — это XML-документ, в котором ищется значение. На самом деле он не важен, так как второй аргумент вызывает ошибку.
  • CONCAT(0x7e, ..., 0x7e) — объединяет символ ~ (0x7e) с результатом подзапроса. Символы ~ используются как маркеры, чтобы облегчить поиск данных в сообщении об ошибке.
  • (SELECT (ELT(1282=1282,1))) — это подзапрос, который возвращает 1, если условие 1282=1282 истинно. В реальной атаке вместо этого подзапроса может быть запрос к системным таблицам, например, SELECT version() или SELECT password FROM users LIMIT 1.
  • -- - — комментарий, который обрезает остаток оригинального SQL-запроса.

В результате MySQL пытается выполнить XPath-выражение, которое не является валидным, и возвращает ошибку вида: XPATH syntax error: '~5.7.33~'. В этом сообщении содержится версия СУБД. Злоумышленник может подставлять разные подзапросы, чтобы извлекать произвольные данные посимвольно или целыми строками.

Почему это опасно?

Error-based SQL-инъекции позволяют злоумышленнику:

  • Получить информацию о структуре базы данных (имена таблиц, столбцов);
  • Извлечь конфиденциальные данные: логины, пароли, персональные данные пользователей, номера кредитных карт;
  • В некоторых случаях выполнить произвольные команды на сервере (при наличии соответствующих привилегий);
  • Обойти аутентификацию и получить доступ к административной панели.

Особенность error-based инъекций в том, что они не требуют слепого перебора — результат сразу виден в ответе сервера, что делает атаку быстрой и эффективной.

Пример уязвимого кода

Предположим, на сервере выполняется следующий PHP-скрипт:

$id = $_GET['id'];
$query = "SELECT * FROM products WHERE id = '" . $id . "'";
$result = mysqli_query($conn, $query);

Если пользователь передаст в параметре id строку 1' AND EXTRACTVALUE(1282,CONCAT(0x7e,(SELECT version()),0x7e))-- -, то итоговый запрос станет:

SELECT * FROM products WHERE id = '1' AND EXTRACTVALUE(1282,CONCAT(0x7e,(SELECT version()),0x7e))-- -'

MySQL выполнит подзапрос, получит версию и попытается использовать её как XPath, что вызовет ошибку с версией в тексте. Так злоумышленник узнает версию СУБД.

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

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

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

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

Заключение

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

Источники