RCE, RCE (Remote Code Execution), XML External Entity (XXE)

XXE: от чтения файлов до full RCE через Expect

Привет, друг!

XXE (XML External Entity) — это атака на небезопасно сконфигурированный XML-парсер, которая позволяет злоумышленнику вмешиваться в обработку XML-данных приложением. Звучит скучно? А теперь представь, что через обычную форму загрузки файлов ты можешь читать /etc/passwd, делать SSRF на внутренние сервисы и даже выполнять команды на сервере. Вот это уже интереснее.​

Как работает механизм

XML поддерживает внешние сущности (entities), которые могут быть определены через URI. Парсер обрабатывает этот URI и подставляет содержимое в документ. Если приложение не отключает эту фичу — у тебя есть вектор атаки.​

Базовый пример чтения файлов

При обработке этого XML парсер подставит вместо &xxe; содержимое файла /etc/passwd. Если приложение возвращает обработанные данные в ответе — ты получаешь содержимое файла.

Python пример уязвимого кода:

Эскалация до SSRF

XXE позволяет делать запросы к любым URL, включая внутренние сервисы. Это превращает уязвимость в SSRF (Server-Side Request Forgery).​

Теперь сервер сделает запрос к внутреннему API от своего имени. Можно сканировать внутреннюю сеть, читать метадату AWS (169.254.169.254), атаковать Redis/Memcached.

Сканирование внутренней сети:

Blind XXE: когда ответа нет

Часто приложение не возвращает обработанные данные. Тогда используем Out-of-Band (OOB) технику.​

Классический OOB XXE:

Файл evil.dtd на сервере атакующего:

Парсер загрузит твой DTD, подставит содержимое файла в параметр и отправит GET-запрос с данными. Смотришь логи веб-сервера — получаешь файл.

Python сервер для приема данных:

PHP Expect wrapper: переход к RCE

Вот где начинается магия. PHP поддерживает expect:// wrapper, который позволяет выполнять команды. Если на сервере установлен модуль PHP Expect — у тебя RCE.​

Парсер выполнит команду id и вернет результат. Это полноценное удаленное выполнение кода.

Reverse shell через XXE+Expect:

Проверка наличия Expect на целевом сервере:

Продвинутые техники обхода

Обход фильтрации keywords:

Обход через UTF-7 encoding:

XXE через SVG upload:

Многие приложения принимают SVG как «безопасные изображения», но внутри это XML.

Атака через SOAP API

SOAP использует XML, что делает его идеальной целью.

Читаешь конфиг с кредами от БД — дальше lateral movement.

Error-based XXE

Когда нет ни OOB, ни отражения данных — используй ошибки парсера.​

Парсер попытается открыть /nonexistent/root:x:0:0:... и выдаст ошибку с содержимым файла в пути.

XXE через docx/xlsx

Office файлы — это ZIP-архивы с XML внутри.

Когда жертва откроет файл в веб-приложении для просмотра — XXE сработает.

Защита от XXE

Python (lxml):

Python (defusedxml):

PHP:

Java:

Checklist эксплуатации

  1. Найди точки ввода XML: API endpoints, file uploads, SOAP services
  2. Проверь базовый XXE: чтение /etc/hostname
  3. Blind XXE: используй OOB, если нет отражения
  4. SSRF: сканируй внутреннюю сеть
  5. RCE через Expect: проверь expect://id
  6. Альтернативные wrappers: php://filterdata://ftp://
  7. Эксфильтрация через DNS: если HTTP заблокирован

Реальные кейсы

Facebook в 2014 была уязвима к XXE через загрузку Office документов. Google в 2013 имела XXE в некоторых внутренних сервисах. Уязвимость есть даже в современных приложениях, потому что XML всё ещё используется в SOAP, RSS, SVG и старых корпоративных системах.

Итого

XXE — это не просто чтение файлов. Это SSRF, это RCE через Expect, это эксфильтрация через DNS, это доступ к облачным метаданным. Современные парсеры по умолчанию часто уязвимы. Твоя задача как разработчика — явно отключать external entities. Твоя задача как пентестера — проверять каждую точку обработки XML на эту уязвимость.​

XXE: от чтения файлов до full RCE через Expect

На этом все. Всем хорошего дня!