В статье рассказываем, как устроена XXE-уязвимость, как ее распознать и что сделать, чтобы защитить сервер и данные.
XXE-уязвимость превращает XML-документ в инструмент для кражи данных и атак на сервер. Небезопасная обработка XML позволяет злоумышленнику загружать файлы, делать запросы от имени сервера и вызывать сбои в работе системы.
24 февраля 2024

XXE-уязвимость: что такое и как предотвратить

20 минут
эксперт в информационной безопасности в Start X
Андрей Жаркевич
автор, дипломированный айтишник, люблю объяснять сложное простыми словами
Никита Барышников
автор, дипломиро­ванный айтишник, люблю объяснять сложное простыми словами
Никита Барышников
эксперт в информационной безопасности в Start X
Андрей Жаркевич
Обучение навыкам безопасного поведения

Что такое XXE-уязвимость и чем она опасна

XXE (XML External Entity Attack) — уязвимость, которая возникает при обработке XML-документов с использованием внешних сущностей (External Entities).

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

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

Как работает XXE-атака

XXE-атака происходит в четыре этапа:

  1. Злоумышленник определяет внешнюю сущность в XML. Создает вредоносный XML-документ, содержащий определение внешней сущности, которая ссылается на запрещенные или чувствительные ресурсы, например файлы на сервере или удаленные URL.
  2. Злоумышленник отправляет XML в уязвимое приложение. Он передает документ на обработку — через веб-форму, API или другой механизм взаимодействия.
  3. Сервер обрабатывает XML. Если поддержка внешних сущностей не отключена, XML-парсер автоматически загружает указанные ресурсы.
  4. Злоумышленник эксплуатирует уязвимость. В зависимости от цели атаки, он может прочитать конфиденциальные файлы, выполнить запросы от имени сервера или вызвать отказ в обслуживании. В некоторых случаях атака позволяет взаимодействовать с внутренними сервисами или даже выполнять произвольный код.

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

  • Вставить ссылку на конфиденциальный файл, например, на файл с паролями на сервере.
  • Заставить сервер прочитать этот файл и включить его содержимое в ответ или отправить данные на сервер.
  • Получить доступ к секретной информации.
  • Вызвать переполнение памяти и остановку сервера: отказ в обслуживании, DoS.
  • Выполнить запрос к внутренним сетевым сервисам, скрытым за файрволом, и получить ответ (Server-Side Request Forgery, SSRF).
  • Добиться удаленного выполнения кода (RCE, Remote Code Execution).

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

Примеры XXE-атак

Вот три примера, которые показывают, как злоумышленник может использовать XXE-уязвимость:

Чтение локальных файлов
Злоумышленник может создать XML-документ, который пытается прочитать содержимое файла /etc/passwd — файла, содержащего информацию о пользователях в Linux:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
  <!ELEMENT foo ANY >
  <!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<foo>&xxe;</foo>
Если приложение обрабатывает этот XML без защитных мер, злоумышленник получит содержимое файла /etc/passwd.

Отказ в обслуживании (DoS)
Злоумышленник может использовать атаку Billion Laughs, при которой создаются рекурсивные ссылки на сущности, что приводит к переполнению памяти:
<?xml version="1.0"?>
<!DOCTYPE lolz [
  <!ENTITY a "lol">
  <!ENTITY b "&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;">
  <!ENTITY c "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
  <!ENTITY d "&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;">
]>
<lolz>&d;</lolz>
Этот XML создает экспоненциально растущее количество данных, что может привести к исчерпанию памяти на сервере.

Выполнение команд через SSRF (Server-Side Request Forgery)
Злоумышленник может использовать внешние сущности для отправки запросов к внутренним службам, недоступным напрямую извне:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
  <!ELEMENT foo ANY >
  <!ENTITY xxe SYSTEM "http://internal-service:8080/" >]>
<foo>&xxe;</foo>

Телеграм-канал Start X

Подписаться
Наши разборы мошеннических схем поймет даже бабушка

Почему возникают XXE-уязвимости

Чаще всего XXE-уязвимости возникают по трем причинам:

1. Небезопасные настройки XML-парсеров
XML-парсер — инструмент, который преобразует XML-документы в структуру, понятную для приложения.

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

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

2. Устаревшие или неправильно настроенные библиотеки
Если ваша система использует старые версии библиотек, она может быть уязвима для XXE-атак.

Раньше многие библиотеки поддерживали внешние сущности, не уведомляя об этом разработчика. Сейчас поддержку внешних сущностей по умолчанию можно найти в некоторых версиях Apache Xerces или MSXML, а также в старых версии Java XML-парсеров, например, DOM или SAX. Если вы используете один из этих парсеров, убедитесь, что обработка внешних сущностей отключена.

Например, для Java-парсеров DOM и SAX внимательно проверьте параметры setExpandEntityReferences (false) или XMLConstants. FEATURE_SECURE_PROCESSING, чтобы запретить раскрытие внешних сущностей.

3. Недостаточная обработка входных данных
Основная причина XXE-уязвимостей — доверие к пользовательскому вводу.

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

Вот типичные ошибки в обработке входных данных, которые могут привести к XXE-уязвимостям:

  • доверие к данным из внешних источников;
  • отсутствие валидации структуры XML на этапе загрузки;
  • неправильная обработка данных, переданных через REST API, SOAP или загрузку файлов.

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

Как выявить XXE-уязвимости

Определить XXE-уязвимости можно через анализ работы с XML и тестирование. Чаще всего они возникают в таких сценариях:

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

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

Попробуйте отправить вредоносный файл с внешней сущностью так, как это мог бы сделать хакер. Например, с кодом, запрашивающим содержимое файла /etc/passwd, или с атакой Billion Laughs.

Качественно провести ручное тестирование довольно сложно, более целесообразно воспользоваться готовыми инструментами, чтобы быстро проверить приложение на XXE. Вот несколько популярных и бесплатных решений:

  • Burp Suite. Инструмент для тестирования веб-приложений, с помощью которого можно отправить вредоносные XML-запросы и сразу увидеть реакцию сервера.
  • OWASP ZAP. Бесплатный инструмент для поиска уязвимостей, который работает как прокси между пользователем и сервером, перехватывая запросы и анализируя их.
  • XXE Injector. Специальная утилита для поиска XXE, которая генерирует вредоносные запросы, чтобы посмотреть, как реагирует сервер.

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

Как предотвратить уязвимости и защититься от XXE-атак

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

На платформе Start EDU на примерах реального кода показываем, как эксплуатируют XXE-уязвимости и как от них защититься. А еще даем задания на поиск уязвимостей в приложениях с учетом разных языков программирования и фреймворков. Запишитесь на бесплатное демо, и наш эксперт расскажет, как Start EDU помогает продуктовым командам писать безопасный код и выпускать защищенные продукты.

Вот как можно предотвратить появление XXE-уязвимостей:

Отключите поддержку внешних сущностей в XML-парсере
Самый эффективный способ предотвратить XXE — полностью отключить возможность обработки внешних сущностей. Большинство современных парсеров позволяют это сделать с помощью внутренних настроек.

Вот как такие настройки будут выглядеть в Java с использованием DocumentBuilder:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
factory.setXIncludeAware(false);factory.setExpandEntityReferences(false);
А вот как они будут выглядеть в Python с использованием lxml:
from lxml import etree

parser = etree.XMLParser(resolve_entities=False, no_network=True, dtd_validation=False)tree = etree.parse("file.xml", parser)
Эти настройки запрещают использование внешних сущностей и DTD (Document Type Definition), что практически полностью исключает возможность проведения XXE-атаки.

Используйте для работы с XML проверенные безопасные библиотеки
Вместо низкоуровневых парсеров выбирайте библиотеки, которые изначально настроены безопасным образом.

Например в Python это библиотека defusedxml, в JavaScript — пакеты для работы с XML, которые не поддерживают обработку DTD по умолчанию. Также можно использовать актуальные версии библиотек javax.xml.parsers или XmlReader, если вы используете .NET.

Всегда проверяйте документацию библиотеки или парсера, которую вы используете — возможно, они уже имеют встроенные методы защиты от XXE.

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

Фильтруйте входные данные, проверяйте структуру документа, запрещая подозрительные конструкции (например, <!DOCTYPE> или <!ENTITY>).

Также ограничьте максимальный размер входного файла, чтобы предотвратить атаки типа Billion Laughs.

Минимизируйте доступ к файловой системе и сети
Даже если по какой-то причине внешняя сущность обработается, злоумышленник не получит доступ к важной информации при правильной настройке ограничений.

Вот как это сделать:

  • Запустите ваш XML-парсер в изолированной среде, например, в песочнице или контейнере, где у него нет прав на чтение важных системных файлов или доступа к сети.
  • Используйте механизм ограничения прав, например, SELinux или AppArmor для процессов, работающих с XML.
  • Убедитесь, что серверы, в которых расположен ваш основной код, не имеют ненужного доступа к интернету или внешним ресурсам.

Обновляйте библиотеки и программное обеспечение
XXE-атаки часто работают на устаревших парсерах XML. Регулярно обновляйте библиотеки и фреймворки, чтобы снизить вероятность атаки.

Внедрите процесс регулярного мониторинга обновлений для всех используемых библиотек и зависимостей или используйте инструменты автоматического сканирования зависимостей, такие как Snyk, Dependabot или OWASP Dependency-Check.

Используйте межсетевые экраны и правила WAF
Если вы хотите усилить защиту, установите межсетевой экран веб-приложений WAF, который будет фильтровать подозрительные запросы. Большинство современных решений, например, ModSecurity с базовыми правилами OWASP CRS, уже умеют обнаруживать и блокировать попытки XXE-атак.

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

Подпишитесь на дайджест Start X

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