Apa itu XXE?
XML External Entity (XXE) adalah serangan terhadap aplikasi yang mem-parsing XML dari input user. Jika parser mengizinkan external entities, attacker bisa membaca file di server, melakukan DoS, atau bahkan SSRF.
Recap: XML Entities
XML punya konsep &entity; untuk referensi nilai yang didefinisikan di DTD (Document Type Definition). Yang normal: < = <. Yang berbahaya: entity bisa didefinisikan untuk membaca file dari URL.
Payload Klasik: File Disclosure
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY>
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<foo>&xxe;</foo>
<!-- Kalau parser merender &xxe;, isi /etc/passwd muncul di response -->
BURUK: PHP yang Vulnerable
// PHP lama/mis-konfigurasi
$xml = file_get_contents("php://input");
$doc = new DOMDocument();
$doc->loadXML($xml, LIBXML_NOENT | LIBXML_DTDLOAD); // ← bahaya!
echo $doc->saveXML();
BAIK: PHP yang Aman
// PHP 8+ default aman, tapi jangan tambahkan flag berbahaya
$doc = new DOMDocument();
$doc->loadXML($xml); // tanpa LIBXML_NOENT / LIBXML_DTDLOAD
// Untuk PHP <8, eksplisit matikan:
libxml_disable_entity_loader(true); // di PHP lama
BURUK: Node.js dengan xml2js Lama
const xml2js = require("xml2js");
// Beberapa parser lama / default tidak aman — cek dokumentasi versi
// Gunakan library modern dengan opsi eksplisit disable DTD
BAIK: Python defusedxml
# Jangan pakai xml.etree.ElementTree langsung untuk input user
from defusedxml.ElementTree import fromstring
tree = fromstring(user_input) # otomatis block DTD/entity
Varian Serangan XXE
- In-band XXE — hasil muncul di response (seperti payload di atas)
- Blind XXE — response kosong, tapi attacker exfiltrate data lewat out-of-band (DNS/HTTP ke server attacker)
- Billion Laughs (DoS) — entity bersarang yang meledak secara eksponensial
- XXE → SSRF —
SYSTEM "http://169.254.169.254/..."untuk hit cloud metadata
Payload Billion Laughs
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!-- dst sampai lol9 → 1 miliar "lol" dalam memori -->
]>
<lolz>&lol9;</lolz>
Pencegahan
- Disable DTD processing — hampir semua use case aplikasi web tidak butuh DTD
- Pilih parser aman by default — defusedxml (Python), lxml dengan
resolve_entities=False - Ganti ke JSON kalau memungkinkan — XML jarang benar-benar dibutuhkan untuk API modern
- Validasi schema — tolak XML yang tidak match schema whitelist
- WAF rule — block request body yang mengandung
<!DOCTYPEatau<!ENTITYkalau aplikasi tidak perlu
Real-World
XXE pernah ada di SAP, Siemens, bahkan Microsoft Word (docx pada dasarnya ZIP berisi XML). Lenovo System Update pernah kena XXE. Google Accounts service pernah membayar bounty $10.000 untuk laporan XXE blind.