XML Entities

Web uygulamalarında güvenlik testleri yaparken çoğunlukla SQL Injection, XSS veya SSRF gibi zafiyetlerle karşılaşıyoruz. Ancak özellikle XML kullanan uygulamalarda karşımıza çıkabilecek önemli güvenlik açıklarından biri de XXE (XML External Entity Injection).
XXE zafiyetini anlayabilmek için öncelikle XML'in nasıl çalıştığını, entity kavramını ve DTD yapısını bilmemiz gerekiyor.
Bu yazıda XML'in temel yapısından başlayarak internal ve external entity'leri örneklerle inceleyeceğiz. Sonrasında bu yapıların nasıl bir güvenlik problemine dönüşebildiğini ele alacağız.
XML Nedir?
XML (Extensible Markup Language), verileri saklamak, düzenlemek ve farklı sistemler arasında taşımak amacıyla geliştirilmiş bir işaretleme dilidir.
HTML ile benzer bir yapıya sahiptir. Her ikisi de verileri etiketler (tags) aracılığıyla düzenler. Ancak aralarında önemli bir fark bulunur.
HTML'de <p>, <div> ve <h1> gibi önceden tanımlanmış etiketler vardır. XML'de ise etiket isimlerini ihtiyacımıza göre kendimiz belirleyebiliriz.
Örneğin bir kullanıcının bilgilerini XML formatında saklamak istediğimizi düşünelim.
<?xml version="1.0" encoding="UTF-8"?>
<user>
<id>101</id>
<username>admin</username>
<role>administrator</role>
</user>Bu XML belgesini incelediğimizde:
<?xml version="1.0" encoding="UTF-8"?> XML sürümünü ve karakter kodlamasını belirtir.
<user> belgenin kök (root) elementidir.
<id>, <username> ve <role> kullanıcıya ait bilgileri temsil eder.
Etiketlerin arasındaki ifadeler ise verilerin kendisidir.
XML geçmişte web uygulamalarında veri alışverişi amacıyla oldukça yaygın kullanılıyordu. Hatta AJAX (Asynchronous JavaScript and XML) ifadesindeki X harfi de XML'den gelmektedir.
Günümüzde JSON daha yaygın olsa da XML tamamen ortadan kalkmış değil. SOAP servisleri, çeşitli yapılandırma dosyaları ve XML tabanlı belge formatlarında kullanılmaya devam ediyor.
Dolayısıyla web uygulamalarında sızma testi yaparken XML ile karşılaşmamız oldukça normal.
XML Entities Nedir?
XML Entities, XML belgesi içerisinde belirli karakterlerin veya verilerin doğrudan yazılması yerine özel referanslar kullanılarak temsil edilmesini sağlayan yapılardır.
İlk bakışta biraz karmaşık görünebilir ancak basit bir örnek üzerinden anlamak oldukça kolay.
XML'de < ve > karakterleri etiketleri tanımlamak için kullanılır.
Peki bu karakterleri bir etiket oluşturmak için değil, normal metin olarak kullanmak istersek ne olacak?
Örneğin aşağıdaki ifadeyi XML içerisinde göstermek istediğimizi düşünelim:
5 < 10< karakteri XML açısından özel bir anlam taşıdığı için metin içerisinde doğrudan kullanılması ayrıştırma hatasına neden olabilir.
Bunun yerine XML'in önceden tanımlanmış entity referanslarını kullanabiliriz.
<message>5 < 10</message>XML parser bu ifadeyi işlediğinde < referansını < karakterine dönüştürür.
Sonuç:
5 < 10XML içerisinde kullanılabilen bazı standart entity'ler şunlardır:
Entity | Karşılığı |
< | < |
> | > |
& | & |
" | " |
' | ' |
Burada önemli olan nokta, entity referanslarının XML parser tarafından çözümlenmesidir.
Bu mantığı anladıktan sonra kendi entity'lerimizi nasıl oluşturabileceğimize geçebiliriz.
DTD (Document Type Definition) Nedir?
DTD, yani Document Type Definition, bir XML belgesinin yapısını ve içerisinde kullanılabilecek öğeleri tanımlamak amacıyla kullanılan kurallar bütünüdür.
DTD aracılığıyla XML belgesinde hangi elementlerin bulunabileceğini, bu elementlerin nasıl bir yapıya sahip olacağını ve hangi entity'lerin kullanılacağını belirleyebiliriz.
DTD bildirimleri XML belgesinde DOCTYPE aracılığıyla tanımlanır.
DTD'ler temel olarak iki şekilde kullanılabilir:
1. Internal DTD (Dahili DTD)
Internal DTD, XML belgesinin içerisinde tanımlanır.
Örneğin:
<?xml version="1.0"?>
<!DOCTYPE user [
<!ELEMENT user (#PCDATA)>
]>
<user>Songul</user>Burada DOCTYPE bildirimi içerisinde user elementi için bir tanımlama yapıyoruz.
#PCDATA, ilgili elementin ayrıştırılan metin verisi içerebileceğini belirtir.
2. External DTD (Harici DTD)
External DTD'de ise tanımlamalar XML belgesinin dışında bulunan başka bir kaynaktan alınır.
<?xml version="1.0"?>
<!DOCTYPE user SYSTEM
"https://example.com/user.dtd">
<user>Songul</user>Bu örnekte XML belgesi, harici bir DTD dosyasına referans veriyor.
SYSTEM anahtar kelimesi, belirtilen harici kaynağın konumunu tanımlamak için kullanılır.
XML parser'ın yapılandırmasına bağlı olarak bu dosya yüklenebilir.
Ayrıca XML belgelerinde dahili ve harici DTD tanımlamaları birlikte de kullanılabilir.
Peki DTD'nin XXE açısından önemi ne?
Çünkü XML içerisinde kendi entity'lerimizi tanımlamak için de DTD kullanabiliyoruz.
Custom XML Entities (Özel XML Varlıkları)
XML, standart entity'lerin dışında kendi entity'lerimizi oluşturmamıza da izin verir.
Bu işlemi DTD içerisinde ENTITY bildirimi kullanarak gerçekleştirebiliriz.
Örneğin:
<?xml version="1.0"?>
<!DOCTYPE user [
<!ENTITY username "Songul">
]>
<user>
<name>&username;</name>
</user>Burada şu satıra dikkat edelim:
<!ENTITY username "Songul">Bu ifadeyle username adında bir entity tanımladık ve değerini Songul olarak belirledik.
XML belgesi içerisinde:
&username;referansını kullandığımızda XML parser bu ifadeyi tanımladığımız değerle değiştirir.
Yani işlenmiş veri şu şekilde olur:
<user>
<name>Songul</name>
</user>Buraya kadar yaptığımız işlem oldukça basit. Bir değer tanımladık ve XML içerisinde o değere referans verdik.
Ancak entity'lerin değerlerini her zaman DTD içerisinde doğrudan belirtmek zorunda değiliz.
İşte External Entity kavramı burada devreye giriyor.
XML External Entities Nedir?
XML External Entities, değerleri harici kaynaklar üzerinden alınabilen özel XML entity'leridir.
Custom Entity örneğinde değeri doğrudan kendimiz belirlemiştik.
<!ENTITY username "Songul">External Entity'de ise bir değer yazmak yerine harici bir kaynağın adresini belirtebiliriz.
Örneğin:
<!DOCTYPE user [
<!ENTITY external SYSTEM
"https://example.com/data.txt">
]>Bu tanımlamada:
ENTITY, yeni bir entity tanımlar.
external, entity'nin ismidir.
SYSTEM, harici bir kaynak belirtir.
URL ise erişilmek istenen kaynağın adresidir.
Entity'yi XML içerisinde kullanmak istediğimizde yine aynı yöntemi uygularız.
<user>
<data>&external;</data>
</user>Eğer XML parser harici entity çözümlemesine izin veriyorsa belirtilen URL'deki içeriği almaya çalışabilir.
Burada güvenlik açısından önemli olan başka bir ayrıntı daha var.
External Entity'ler yalnızca HTTP veya HTTPS adreslerine referans vermek için kullanılmaz.
Yerel dosya yollarını da gösterebilirler.
Örneğin:
<!DOCTYPE user [
<!ENTITY external SYSTEM
"file:///path/to/file">
]>file:// protokolü, yerel dosya sistemindeki bir kaynağı belirtmek için kullanılır.
Bu durum özellikle güvenilmeyen XML verilerini işleyen uygulamalarda ciddi bir güvenlik problemine dönüşebilir.
Çünkü XML parser uygun şekilde sınırlandırılmamışsa uygulamanın çalıştığı sunucudaki dosyalara erişmeye çalışabilir.
External Entity Nasıl XXE Zafiyetine Dönüşür?
Şimdiye kadar XML'in yapısını, DTD'yi ve entity tanımlamalarını öğrendik.
Bu bilgileri bir araya getirerek XXE zafiyetinin nasıl ortaya çıkabileceğini inceleyelim.
Bir alışveriş uygulamasında ürün stok kontrolü yapıldığını düşünelim.
Kullanıcı bir ürünün stok durumunu kontrol etmek istediğinde sunucuya aşağıdaki XML isteği gönderiliyor olsun.
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck>
<productId>381</productId>
</stockCheck>Normal şartlarda uygulama 381 ürün numarasını okuyarak stok bilgisini kontrol edecektir.
Ancak uygulamanın XML parser'ı harici entity'leri güvenli olmayan şekilde çözümlemeye izin veriyorsa farklı bir durum ortaya çıkabilir.
Örneğin yalnızca yetkili bir laboratuvar ortamında aşağıdaki XML verisini ele alalım:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE stockCheck [
<!ENTITY xxe SYSTEM "file:///etc/hostname">
]>
<stockCheck>
<productId>&xxe;</productId>
</stockCheck>Burada normal ürün numarası yerine &xxe; referansını kullandık.
Aynı zamanda DTD içerisinde xxe adında bir external entity tanımladık.
<!ENTITY xxe SYSTEM "file:///etc/hostname">Bu satır, XML parser'a sunucunun dosya sistemi üzerindeki /etc/hostname dosyasını harici kaynak olarak gösterir.
Eğer parser bu işleme izin veriyorsa dosyanın içeriğini okumaya çalışabilir.
Daha da önemlisi, uygulama çözümlenen değeri HTTP yanıtında kullanıcıya yansıtıyorsa dosyanın içeriği de yanıtta görüntülenebilir.
Örneğin laboratuvar ortamında şöyle bir cevapla karşılaşabiliriz:
Invalid product ID: lab-serverBuradaki lab-server değeri örnek olarak verilmiştir.
Bu senaryoda dikkat etmemiz gereken nokta, sunucunun dosya sistemindeki bir bilginin XML isteği aracılığıyla uygulama yanıtına taşınabilmesidir.
Elbette yalnızca XML gönderilebiliyor olması uygulamanın XXE zafiyetine sahip olduğu anlamına gelmez.
Bunun gerçekleşebilmesi için XML parser'ın ilgili harici kaynakları çözümleyebilmesi ve uygulamanın bu verileri uygun şekilde sınırlandırmaması gerekir.
XXE Zafiyetinin Olası Etkileri
XXE yalnızca yerel dosya okuma ile sınırlı değildir.
Uygulamanın XML verilerini nasıl işlediğine ve sunucunun hangi kaynaklara erişebildiğine bağlı olarak farklı güvenlik problemleri ortaya çıkabilir.
1. Local File Disclosure
Harici entity çözümlemesi aracılığıyla sunucudaki dosyaların içeriğine erişilmesi mümkün olabilir.
2. Server-Side Request Forgery (SSRF)
XML parser, bir URL'yi çözümlemek için sunucu üzerinden HTTP isteği oluşturabilir.
Bu özellik kötüye kullanıldığında uygulamanın erişebildiği dahili servislere istek yapılmasına neden olabilir.
3. Blind XXE
Bazı uygulamalarda external entity çözümlense bile elde edilen veri HTTP yanıtında görüntülenmez.
Bu durum Blind XXE olarak adlandırılır.
Blind XXE zafiyetleri, uygulamanın oluşturduğu ağ etkileşimleri veya XML ayrıştırma hataları üzerinden tespit edilebilir. Bazı durumlarda hassas verilerin açığa çıkmasına da neden olabilir.
Bu teknikler normal XXE'ye göre daha farklı test yöntemleri gerektirir.
XXE Zafiyetleri Nasıl Önlenebilir?
XXE zafiyetlerinin temelinde çoğunlukla XML parser'ın uygulama için gerekli olmayan tehlikeli özelliklerinin etkin olması yer alır.
Bu nedenle güvenlik açısından en önemli adımlardan biri, harici entity çözümlemesini ihtiyaç olmadığı sürece devre dışı bırakmaktır.
Ayrıca harici DTD yüklemesinin sınırlandırılması, XInclude gibi harici kaynak kullanımına olanak tanıyan özelliklerin gerekli değilse kapatılması ve güvenli XML parser yapılandırmalarının tercih edilmesi gerekir.
Burada önemli bir ayrım var: Her DTD kullanımı veya her entity tanımı doğrudan güvenlik açığı değildir.
Asıl problem, güvenilmeyen XML verilerinin harici kaynaklara kontrolsüz erişebilecek şekilde işlenmesidir.







