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

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

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

Разбор структуры запроса

Рассмотрим каждый элемент подробнее:

  • %" — закрывающая кавычка и процент, которые завершают исходное строковое значение в уязвимом параметре. Символ % часто используется в LIKE-запросах, а кавычка разрывает строку.
  • OR — логический оператор, добавляющий условие к исходному запросу.
  • EXTRACTVALUE(7460, CONCAT(...)) — функция MySQL, предназначенная для извлечения значения из XML-документа по XPath-выражению. Если XPath-выражение некорректно, MySQL генерирует ошибку, содержащую переданный фрагмент. Это и есть канал утечки.
  • CONCAT(0x7e, ((SELECT (ELT(7460=7460,1)))), 0x7e) — конкатенация тильды (0x7e — шестнадцатеричный код символа ~), результата подзапроса и ещё одной тильды. Тильды служат маркерами, чтобы облегчить извлечение данных из сообщения об ошибке.
  • SELECT (ELT(7460=7460,1)) — подзапрос, который возвращает 1, если условие 7460=7460 истинно. В реальной атаке вместо этого подзапроса подставляется запрос к системным таблицам, например SELECT table_name FROM information_schema.tables LIMIT 0,1.
  • -- - — комментарий, который отсекает оставшуюся часть оригинального SQL-запроса, чтобы не вызвать синтаксическую ошибку.

Таким образом, при выполнении запроса MySQL попытается обработать EXTRACTVALUE с заведомо неверным XPath (начинающимся с тильды), что приведёт к ошибке вида: XPATH syntax error: '~1~'. В этом сообщении и окажутся данные, полученные из подзапроса.

Как работает error-based инъекция

Основная идея заключается в том, чтобы заставить базу данных выдать результат подзапроса в тексте ошибки. Функция EXTRACTVALUE принимает два аргумента: XML-документ и XPath-выражение. Если XPath невалиден, MySQL возвращает ошибку с указанием проблемного фрагмента. Передавая в качестве XPath результат подзапроса, атакующий добивается того, что этот результат попадает в сообщение об ошибке.

Конкатенация с символами 0x7e (тильда) помогает ограничить выводимые данные: тильды служат разделителями, по которым потом легко вычленить полезную нагрузку. В приведённом примере подзапрос возвращает просто 1, но в реальной атаке на его месте может быть запрос, извлекающий имя пользователя базы, версию СУБД, имена таблиц и т.д.

Для пошагового извлечения данных используются LIMIT и OFFSET. Например, чтобы получить первую таблицу из information_schema.tables, подзапрос будет таким: SELECT table_name FROM information_schema.tables LIMIT 0,1. Затем LIMIT 1,1 для следующей и так далее.

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

Предположим, уязвимый параметр id в URL: http://example.com/product?id=1. Исходный SQL-запрос может выглядеть так: SELECT * FROM products WHERE id = '1'. Атакующий подставляет:

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

В ответе сервера появится ошибка: XPATH syntax error: '~mydb~', где mydb — имя текущей базы данных. Аналогично можно извлечь версию MySQL (SELECT version()), текущего пользователя (SELECT user()) и любые другие данные, к которым имеет доступ учётная запись приложения.

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

  • Имя текущей базы данных (database())
  • Версию СУБД (version())
  • Текущего пользователя (user(), current_user())
  • Список таблиц и колонок из information_schema
  • Логины и пароли пользователей из пользовательских таблиц
  • Другие конфиденциальные сведения, хранящиеся в базе

Ограничение лишь в правах доступа учётной записи, от имени которой выполняется запрос. Если приложение использует привилегированного пользователя (например, root), последствия могут быть катастрофическими.

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

Основная причина успеха таких атак — отсутствие параметризации запросов и вывод ошибок базы данных пользователю. Вот ключевые меры защиты:

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

Также рекомендуется проводить регулярные аудиты безопасности и сканирования кода на уязвимости.

Заключение

Запрос %" OR EXTRACTVALUE(7460,CONCAT(0x7e,((SELECT (ELT(7460=7460,1)))),0x7e))-- - — это учебный пример error-based SQL-инъекции в MySQL. Он демонстрирует, как через функцию EXTRACTVALUE можно заставить базу данных выдать произвольные данные в сообщении об ошибке. Понимание механизма таких атак необходимо разработчикам и специалистам по безопасности для построения надёжной защиты. Помните: лучшая защита — параметризованные запросы и скрытие деталей ошибок от конечных пользователей.

Источники