ТестированиеТестирование безопасностиИнженер по тестированию безопасности приложений

Приложение принимает XML от пользователя. Как установить, разрешает ли парсер внешние сущности?

Приложение принимает XML от пользователя. Как установить, разрешает ли парсер внешние сущности?

Проходите собеседования с ИИ помощником Hintsage

Краткий ответ

Нужно отправить XML с внешней сущностью, указывающей на контролируемый тестировщиком ресурс, и проверить, обращается ли приложение к этому ресурсу или подставляет его содержимое в результат. Если такое обращение происходит, парсер разрешает внешние сущности, что создаёт риск XXE.

Безопасным результатом считается явный отказ от внешних сущностей либо полное отклонение конструкции DTD. Проверка не должна извлекать реальные секреты: достаточно контролируемого сетевого запроса или безопасного маркера.

Исторический контекст

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

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

Постановка проблемы

Атакующий может передать XML, который заставит сервер обратиться к внутреннему адресу, прочитать локальный файл или отправить наружу результат обработки. В зависимости от среды это приводит к SSRF, раскрытию конфиденциальных данных или отказу в обслуживании.

Обычная проверка только ответа приложения недостаточна: сервер может выполнить исходящий запрос, но не вернуть его результат пользователю. Поэтому нужно контролировать также DNS-, HTTP- или иной безопасный канал взаимодействия с тестовой инфраструктурой.

Подробное решение

Тестировщик размещает на контролируемом ресурсе уникальный маркер и отправляет XML, содержащий объявление внешней сущности:

<?xml version="1.0"?> <!DOCTYPE request [ <!ENTITY probe SYSTEM "https://test.example/unique-marker"> ]> <request>&probe;</request>

Затем проверяются несколько признаков: обращение к тестовому ресурсу, появление маркера в ответе, ошибка парсера и различие поведения при отключённых сущностях. Сетевой запрос доказывает разрешение внешнего обращения, даже если содержимое не возвращается клиенту.

Защита должна отключать обработку DTD, внешних общих сущностей и внешних параметрических сущностей. Если приложению действительно нужны отдельные XML-возможности, их следует разрешать минимально и ограничивать сетевые выходы на уровне инфраструктуры; одна настройка парсера не должна быть единственным барьером.

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

Ситуация из практики

Сервис импорта документов не возвращал пользователю результат внешней сущности, но во время теста выполнял DNS-запрос к контролируемому домену. Рассматривались три варианта: ограничить список разрешённых URL, фильтровать XML-текст или изменить настройки парсера.

Фильтрация текста была отвергнута из-за хрупкости: разные парсеры и варианты представления XML могут обходить строковые правила. Ограничение URL снижало риск SSRF, но не решало чтение локальных ресурсов. Выбрали отключение внешних сущностей и DTD в парсере, дополнительно запретив исходящие соединения из сервиса без явной необходимости.

После исправления тестовый XML отклонялся или обрабатывался без сетевого обращения, а функциональные документы без внешних сущностей продолжили импортироваться. Результат подтвердили отдельной проверкой исходящего трафика.

Что кандидаты часто упускают

1. Достаточно ли проверить, что приложение не вернуло содержимое локального файла?

Нет. Это проверяет только один наблюдаемый результат. Уязвимость может быть слепой: сервер прочитает ресурс или обратится к внутреннему адресу, но не включит данные в HTTP-ответ. Поэтому нужно наблюдать исходящие обращения и использовать уникальный безопасный маркер.

2. Устраняет ли XXE запрет доступа приложения к файловой системе?

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

3. Можно ли оставить DTD включённым, если внешние сущности запрещены?

Это зависит от конкретного парсера и его настроек. Раздельные параметры могут управлять внешними общими сущностями, параметрическими сущностями, загрузкой внешних схем и обработкой DTD не одинаково. Для недоверенного XML наиболее надёжная стратегия — полностью отключить DTD и внешние обращения, а при необходимости подтвердить безопасное поведение тестами именно используемой библиотеки.