XXE (XML External Entity Injection) è una vulnerabilità che colpisce le applicazioni che elaborano input XML usando parser configurati per risolvere le entità esterne dichiarate nel documento. Un’entità esterna XML è un meccanismo del linguaggio XML che permette di includere contenuto da una fonte esterna — un file locale, un URL remoto — all’interno del documento. Se il parser risolve queste entità senza restrizioni e su input controllato dall’utente, l’attaccante può leggere file arbitrari del filesystem del server, effettuare richieste verso risorse interne (SSRF) o causare Denial of Service.
Meccanismo
XML supporta la dichiarazione di entità nel DTD (Document Type Definition):
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>
<dato>&xxe;</dato>
</root>
Se il parser risolve l’entità &xxe;, sostituisce il riferimento con il contenuto di /etc/passwd e lo restituisce nell’output XML. L’attaccante legge il file di sistema attraverso la risposta dell’applicazione.
Varianti di attacco
File disclosure: lettura di file sensibili del server — /etc/passwd, /etc/shadow, chiavi private SSH in ~/.ssh/id_rsa, file di configurazione con credenziali, codice sorgente dell’applicazione.
SSRF via XXE: invece di file://, usare http:// per effettuare richieste verso servizi interni:
<!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/">
Stessa superficie di rischio della SSRF classica — metadata service AWS, servizi interni non autenticati.
Billion Laughs (XXE DoS): entità che si espandono ricorsivamente consumando esponenzialmente memoria:
<!DOCTYPE bomb [
<!ENTITY a "lol">
<!ENTITY b "&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;">
<!ENTITY c "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
...
]>
<root>&z;</root>
Pochi kilobyte di XML causano l’espansione di gigabyte in memoria — crash del parser per OOM.
Blind XXE: l’applicazione non restituisce l’output dell’entità nella risposta, ma l’attaccante può estrarre dati out-of-band: l’entità esterna effettua una richiesta HTTP verso un server controllato dall’attaccante con il contenuto del file codificato nell’URL.
Superfici colpite
XXE colpisce qualsiasi applicazione che processa XML da input utente senza hardening del parser:
- Upload di file XML, SVG, DOCX (formato basato su XML), XLSX, PDF (alcuni parser)
- API SOAP (basate su XML)
- Parser SAML — una SAML Response è un documento XML; se il parser dell’SP risolve entità esterne, XXE è possibile sull’endpoint ACS
- RSS/Atom feed parser
- Librerie di configurazione che leggono XML
Difesa
La difesa è semplice e definitiva: disabilitare la risoluzione delle entità esterne nel parser XML. In ogni linguaggio principale esistono configurazioni specifiche:
# Python (lxml)
parser = etree.XMLParser(resolve_entities=False, no_network=True)
# Java (DocumentBuilderFactory)
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
In alternativa, per applicazioni che non necessitano di DTD, disabilitare completamente il processing dei DTD. Le librerie moderne tendono ad avere queste opzioni disabilitate per default — il rischio è nelle librerie legacy o nei parser custom.