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

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

Рассматриваемый запрос:

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

Это классический пример полезной нагрузки (payload) для error-based SQL-инъекции. Давайте разберём его по частям.

Анатомия полезной нагрузки

Начнём с начала строки:

  • '))) — закрывающие кавычка и скобки. Они используются для завершения оригинального SQL-запроса, в который внедряется код. Количество скобок зависит от структуры уязвимого запроса.
  • AND — логический оператор, позволяющий присоединить дополнительное условие.
  • EXTRACTVALUE(7343, CONCAT(...)) — вызов функции EXTRACTVALUE. Первый аргумент (7343) — произвольное число, второй — XPath-выражение, которое мы формируем динамически.
  • CONCAT(0x7e, ((SELECT (ELT(7343=7343,1)))), 0x7e) — конкатенация символа ~ (0x7e), результата подзапроса и ещё одного ~.
  • -- - — комментарий, отсекающий оставшуюся часть оригинального запроса.

Функция EXTRACTVALUE

EXTRACTVALUE(XML_frag, XPath_expr) возвращает текст первого текстового узла, найденного по XPath-выражению. Если XPath-выражение синтаксически неверно, MySQL выдаёт ошибку вида XPATH syntax error: '...', где ... — часть переданного выражения. Это и есть канал утечки данных.

Подзапрос с ELT

ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В нашем случае ELT(7343=7343, 1) — условие 7343=7343 всегда истинно, поэтому возвращается 1. Это простейший пример; на практике вместо 1 подставляется подзапрос, извлекающий нужные данные, например, имя пользователя или хэш пароля.

Как это работает на практике

Предположим, уязвимый запрос выглядит так:

SELECT * FROM users WHERE id = '))) AND EXTRACTVALUE(7343,CONCAT(0x7e,((SELECT (ELT(7343=7343,1)))),0x7e))-- -';

После подстановки полезной нагрузки СУБД выполнит:

  1. Закроет исходные кавычки и скобки.
  2. Вычислит CONCAT(0x7e, 1, 0x7e), получив строку ~1~.
  3. Передаст эту строку в EXTRACTVALUE как XPath-выражение. Поскольку ~1~ не является корректным XPath, возникнет ошибка: XPATH syntax error: '~1~'.
  4. Текст ошибки вернётся в ответе сервера, и атакующий увидит значение 1.

Заменив 1 на подзапрос, например (SELECT user FROM mysql.user LIMIT 1), злоумышленник получит имя пользователя базы данных в сообщении об ошибке.

Какие данные можно извлечь?

С помощью этой техники атакующий может постепенно извлекать любую информацию из базы:

  • имена таблиц и столбцов из INFORMATION_SCHEMA;
  • учётные данные пользователей (логины, пароли, хэши);
  • персональные данные клиентов;
  • номера кредитных карт и другую финансовую информацию.

Ограничение — длина вывода в сообщении об ошибке (обычно 32 символа), поэтому данные извлекаются посимвольно с использованием функций SUBSTRING и LIMIT.

Пример из реальной практики

В отчётах по пентесту часто приводится похожий вектор: ' AND (SELECT 1 FROM (SELECT COUNT(*), CONCAT((SELECT CONCAT(0x7e, (SELECT user FROM data LIMIT 1,1), 0x7e)), FLOOR(RAND(0)*2))x FROM information_schema.tables GROUP BY x)a) AND '1'='1. Здесь используется GROUP BY с RAND() для вызова ошибки дублирования ключа, но цель та же — вытащить данные через сообщение об ошибке.

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

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

  • Экранирование специальных символов (функция mysqli_real_escape_string).
  • Валидация и фильтрация входных данных на стороне сервера.
  • Отключение вывода подробных ошибок БД в production-среде.
  • Использование ORM и современных фреймворков, которые автоматически применяют параметризацию.
  • Регулярное обновление СУБД и применение WAF для блокировки подозрительных запросов.

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

Заключение

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

Источники