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

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

ExtractValue — это встроенная функция MySQL, предназначенная для извлечения значения из XML-строки по заданному XPath-выражению. Синтаксис: ExtractValue(xml_frag, xpath_expr). Если XPath-выражение некорректно, MySQL возвращает ошибку с фрагментом переданного выражения. Эту особенность эксплуатируют для вывода данных.

Разбор конкретного запроса

Рассмотрим запрос: %" AND EXTRACTVALUE(6407,CONCAT(0x7e,((SELECT (ELT(6407=6407,1)))),0x7e))-- -. Он состоит из нескольких частей:

  • %" — закрывает предыдущее строковое значение в уязвимом параметре.
  • AND EXTRACTVALUE(...) — добавляет условие, которое вызывает ошибку, если инъекция успешна.
  • 6407 — произвольное число, первый аргумент ExtractValue (XML-фрагмент).
  • CONCAT(0x7e, ((SELECT (ELT(6407=6407,1)))), 0x7e) — формирует XPath-выражение. 0x7e — это тильда (~), используемая как маркер начала и конца выводимых данных.
  • ELT(6407=6407,1) — возвращает 1, если условие истинно (6407=6407 всегда истинно).
  • -- - — комментарий, обрезающий остаток запроса.

В результате MySQL пытается выполнить ExtractValue с XPath-выражением, содержащим тильды и число. Это вызывает ошибку вида: XPATH syntax error: '~1~'. В сообщении об ошибке отображается результат подзапроса — в данном случае 1. Злоумышленник может заменить ELT(6407=6407,1) на любой другой подзапрос, чтобы извлечь данные из базы.

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

Error-based SQL-инъекция основана на том, что база данных возвращает детализированные сообщения об ошибках, которые могут содержать полезную информацию. В MySQL функции ExtractValue и UpdateXML часто используются для этих целей. При передаче некорректного XPath-выражения сервер возвращает ошибку с указанием проблемного фрагмента.

Пример простого запроса:

SELECT ExtractValue(1, CONCAT(0x7e, (SELECT version()), 0x7e));

Этот запрос вызовет ошибку: XPATH syntax error: '~5.7.23~', где 5.7.23 — версия MySQL. Таким образом, атакующий может получать произвольные данные.

Ограничения и особенности

Функция ExtractValue имеет ограничение на длину выводимой строки — около 32 символов. Для извлечения длинных данных приходится использовать подзапросы с SUBSTRING или LIMIT. Также важно, чтобы приложение выводило сообщения об ошибках базы данных пользователю. Если ошибки скрыты, метод не сработает.

В приведённом запросе используется ELT(6407=6407,1) — это демонстрация. На практике вместо этого подзапроса внедряют выборку из системных таблиц, например: (SELECT table_name FROM information_schema.tables LIMIT 1).

Защита от SQL-инъекций

Чтобы предотвратить подобные атаки, необходимо:

  1. Использовать параметризованные запросы (prepared statements) — это самый надёжный способ.
  2. Применять хранимые процедуры с параметрами.
  3. Экранировать все пользовательские данные, попадающие в SQL-запросы.
  4. Ограничить права пользователя базы данных, чтобы он не имел доступа к системным таблицам.
  5. Отключить вывод подробных сообщений об ошибках в production-среде.
  6. Регулярно проводить аудит кода и использовать сканеры уязвимостей.

Важно понимать, что никакая фильтрация не даёт 100% гарантии, если она не основана на параметризации. Поэтому разработчикам следует всегда использовать подготовленные выражения.

Заключение

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

Источники