Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 31

.NET XML Güvenliği: XXE ve DTD Zafiyetleri

Merhaba! Bir önceki dersimizde, Java'nın parçalı ve tutarsız XML kütüphaneleri ekosisteminde XXE zafiyetlerini nasıl tespit edeceğimizi derinlemesine inceledik. Farklı ayrıştırıcıların farklı güvenlik yapılandırmaları gerektirdiğini ve tek bir "doğru" çözüm olmadığını gördük. Bu ders, bu analizi bir adım ileri taşıyarak, teknoloji yığınını değiştiriyor ve .NET dünyasına odaklanıyor.

Bu dersimizde, Java'daki deneyimlerimizle bir karşılaştırma yaparak .NET çatısının XML işlemeye yaklaşımını analiz edeceğiz. System.Xml isim alanı altındaki XmlReader, XmlDocument ve XslTransform gibi temel sınıfların XXE ve güvensiz DTD işleme bağlamında nasıl davrandığını inceleyeceğiz. Amacımız, bir kod denetçisi olarak C# kod tabanındaki tehlikeli desenleri hızlı ve etkin bir şekilde tespit etmenizi sağlayacak "uzman gözünü" geliştirmektir. .NET'in genellikle daha güvenli varsayılanlara sahip olmasına rağmen, geliştiricilerin kasıtlı olarak veya farkında olmadan bu korumaları nasıl devre dışı bırakabileceğini göreceksiniz.

.NET'in XML İşleme Felsefesi: Daha Merkezi, Daha Güvenli Varsayılanlar

Java'daki dağınık kütüphane yapısının aksine, .NET'in XML işleme yetenekleri büyük ölçüde System.Xml isim alanı altında merkezileştirilmiştir. Bu durum, güvenlik kontrollerini daha öngörülebilir kılar. Ancak bu merkezileşme, tehlikenin ortadan kalktığı anlamına gelmez; sadece aranması gereken yerleri daha belirgin hale getirir.

.NET Framework'ün eski sürümlerinde (4.5.2 öncesi), DTD işleme varsayılan olarak daha gevşekti ve bu da XXE saldırılarına zemin hazırlıyordu. Ancak modern .NET (.NET Core dahil olmak üzere tüm güncel sürümler), güvenlik odaklı bir "varsayılan olarak güvenli" (secure by default) prensibini benimsemiştir.

Varsayılan olarak, modern .NET XML ayrıştırıcıları DTD'leri işlemeyi yasaklar. Bir DOCTYPE bildirimi içeren bir XML belgesini işlemeye çalıştığınızda, ayrıştırıcı bir System.Xml.XmlException fırlatır. Bu davranış, bir kod denetçisi için kritik bir başlangıç noktasıdır.

Bu hata mesajı, .NET'in varsayılan güvenlik duruşunu mükemmel bir şekilde özetler: "Güvenlik nedenleriyle bu XML belgesinde DTD yasaklanmıştır." Hata, geliştiriciye DTD işlemeyi etkinleştirmek için `DtdProcessing` özelliğini ayarlaması gerektiğini de söyler. Bu, bir güvenlik denetçisi için potansiyel zafiyetin başlangıç noktasını işaret eden bir ipucudur.

Bu istisna, geliştiricinin DTD desteğini etkinleştirmek için bilinçli bir adım atması gerektiği anlamına gelir. İşte bu "bilinçli adım", bizim kod denetimi sırasında arayacağımız kırmızı bayraktır.


Zafiyetin Anahtarı: DtdProcessing.Parse

.NET'te XXE zafiyetini etkinleştirmenin en yaygın yolu, XmlReaderSettings nesnesindeki DtdProcessing özelliğini DtdProcessing.Parse olarak ayarlamaktır. Bu ayar, ayrıştırıcıya DTD'leri okumasını ve işlemesini söyler, bu da harici varlıkların çözümlenmesini tetikler.

Aşağıdaki kod parçası, bir denetçinin dikkat etmesi gereken tipik bir güvensiz deseni göstermektedir.

Bu kod örneğinde, bir `XmlReaderSettings` nesnesi oluşturulmuş ve `settings.DtdProcessing` özelliği `DtdProcessing.Parse` olarak ayarlanmıştır. Bu tek satır, ayrıştırıcıyı XXE saldırılarına karşı savunmasız hale getirir. Kodda bir `ValidationEventHandler` bulunsa bile, bu genellikle DTD'nin yapısını doğrulamak içindir ve harici varlıkların getirilmesini engellemez. Gözünüz `DtdProcessing.Parse` satırında olmalıdır.

Farklı .NET XML API'lerinde XXE Tespiti

Şimdi bu bilgiyi kullanarak .NET'in farklı XML işleme API'lerinde zafiyetleri nasıl arayacağımızı inceleyelim.

1. XmlReader: Temel Ayrıştırıcı

XmlReader, ileri yönlü, salt okunur ve düşük bellek tüketimiyle çalışan temel XML ayrıştırıcısıdır. Güvenliği, kendisine verilen XmlReaderSettings nesnesi tarafından belirlenir.

Güvensiz Kod Deseni:

using System.Xml;

public class VulnerableXmlParser
{
    public void Parse(string xmlContent)
    {
        // 1. XmlReaderSettings oluşturulur.
        XmlReaderSettings settings = new XmlReaderSettings();
        
        // 2. KIRMIZI BAYRAK: DTD işlemeye izin verilir.
        settings.DtdProcessing = DtdProcessing.Parse;
        
        // 3. Güvensiz ayarlarla bir XmlReader oluşturulur.
        using (XmlReader reader = XmlReader.Create(new StringReader(xmlContent), settings))
        {
            // XML işlenirken harici varlıklar çözümlenir.
            while (reader.Read()) { }
        }
    }
}

Kod denetimi sırasında DtdProcessing = DtdProcessing.Parse atamasını gördüğünüzde, bu kodun kullanıcıdan gelen bir XML'i işleyip işlemediğini hemen kontrol etmelisiniz. Eğer öyleyse, bu yüksek olasılıkla bir XXE zafiyetidir.

Güvenli Alternatif ve XmlSecureResolver:
En güvenli yapılandırma, DtdProcessing özelliğini varsayılan değeri olan Prohibit'te bırakmaktır. Eğer DTD işleme bir iş gereksinimi ise, daha güvenli bir alternatif XmlSecureResolver kullanmaktır. Bu sınıf, harici kaynaklara erişimi belirli bir izin verilen URL listesiyle kısıtlamanıza olanak tanır.

// Daha güvenli bir yaklaşım (tamamen güvenli değil, dikkatli kullanılmalı)
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Parse;

// Sadece güvenilen bir etki alanından kaynaklara izin verir.
settings.XmlResolver = new XmlSecureResolver(new XmlUrlResolver(), "https://trusted.domain.com/");

new XmlSecureResolver(...) görmek, geliştiricinin en azından bir güvenlik önlemi düşündüğünü gösterir, ancak izin verilen etki alanının yapılandırmasını yine de incelemeniz gerekir.

2. XmlDocument: DOM Tabanlı Ayrıştırıcı

XmlDocument, XML'i bir ağaç yapısı olarak belleğe yükleyen DOM (Document Object Model) ayrıştırıcısıdır. XmlDocument'ın güvenliği, veriyi nasıl yüklediğine bağlıdır.

  • Doğrudan Yükleme: doc.Load(string_or_stream) gibi bir metot kullanıldığında, altta yatan ayrıştırıcının varsayılan ayarları geçerli olur. Modern .NET'te bu güvenlidir.
  • XmlReader ile Yükleme: doc.Load(XmlReader) kullanıldığında, XmlDocument'ın güvenliği tamamen XmlReader'a sağlanan XmlReaderSettings'e bağlıdır. Yukarıdaki XmlReader için anlattığımız güvensiz desen burada da geçerlidir.

Güvensiz Kod Deseni (XmlTextReader ile - Eski Kod):
Eski kod tabanlarında XmlTextReader sınıfına rastlayabilirsiniz. Bu sınıfın kendi DtdProcessing özelliği vardır.

using System.Xml;

public class LegacyVulnerableParser
{
    public void Parse(string xmlContent)
    {
        // XmlTextReader doğrudan DTD işlemeyi etkinleştirebilir.
        XmlTextReader reader = new XmlTextReader(new StringReader(xmlContent));
        reader.DtdProcessing = DtdProcessing.Parse; // ZAFİYET

        XmlDocument doc = new XmlDocument();
        doc.Load(reader);
        // ...
    }
}

XmlTextReader ve üzerinde DtdProcessing.Parse ayarını gördüğünüz her yer potansiyel bir zafiyettir.

3. XslCompiledTransform: Gizli Bir Vektör (XSLT)

XSLT (Extensible Stylesheet Language Transformations) işlemleri, XXE için daha az bilinen ancak oldukça tehlikeli bir saldırı yüzeyi sunar. XslCompiledTransform sınıfı, bir XML belgesini bir XSLT stil sayfası kullanarak dönüştürür. Tehlike, bu işlem sırasında hem XML belgesinin hem de XSLT dosyasının harici varlıkları çözümleyebilmesidir.

Güvenlik, transform.Load() metoduna sağlanan XmlResolver nesnesine bağlıdır.

  • Güvenli (Varsayılan): Modern .NET'te, Load metoduna bir resolver sağlamazsanız, varsayılan olarak harici kaynakları çözümlemeyen bir XmlNullResolver kullanılır.
  • Güvensiz: Geliştirici, eski davranışları taklit etmek veya harici şemalara erişmek için new XmlUrlResolver() örneğini Load metoduna açıkça geçirirse, zafiyet ortaya çıkar. XmlUrlResolver, file://, http:// gibi protokoller dahil olmak üzere her türlü harici kaynağı çözümleyecektir.

Güvensiz Kod Deseni:

using System.Xml;
using System.Xml.Xsl;

public class VulnerableXslt
{
    public void Transform(string xml, string xslt)
    {
        XslCompiledTransform transform = new XslCompiledTransform();
        
        // KIRMIZI BAYRAK: XmlUrlResolver kullanımı, harici kaynak çözümlemeyi etkinleştirir.
        transform.Load(new XmlTextReader(new StringReader(xslt)), XsltSettings.Default, new XmlUrlResolver());

        // Dönüşüm sırasında hem XML hem de XSLT içindeki harici varlıklar işlenebilir.
        transform.Transform(new XmlTextReader(new StringReader(xml)), null, Console.Out);
    }
}

Kodda new XmlUrlResolver() ifadesini, özellikle XslCompiledTransform ile birlikte aramak, kritik bir denetim adımıdır.

4. LINQ to XML (XDocument, XElement): En Güvenli Seçenek

System.Xml.Linq isim alanı altındaki LINQ to XML (XDocument, XElement), XXE'ye karşı doğal olarak en dirençli API'dir. Tasarımı gereği, XDocument.Parse() ve XDocument.Load() metotları DTD'leri işlemez. Bu nedenle, bir kod tabanında XML işleme için LINQ to XML kullanıldığını görmek genellikle iyi bir işarettir. Ancak, bir XDocument nesnesinin daha sonra XslCompiledTransform gibi güvensiz yapılandırılmış başka bir sürece girdi olarak verilmediğinden emin olmalısınız.


.NET Kodunda XXE İçin Denetim Stratejisi

.NET projesinde XXE zafiyeti ararken, aşağıdaki adımları sistematik olarak izleyebilirsiniz:

  1. DtdProcessing.Parse Araması: Kod tabanında DtdProcessing.Parse ifadesini arayın. Bu, en bariz ve en yaygın zafiyet göstergesidir.
  2. XmlUrlResolver Araması: new XmlUrlResolver() ifadesini arayın. Bu ifadenin XslCompiledTransform.Load veya diğer XML API'leriyle kullanılması yüksek risklidir.
  3. XmlReaderSettings Kullanımını İnceleyin: XmlReaderSettings nesnelerinin nerede oluşturulduğunu ve nasıl yapılandırıldığını bulun. DtdProcessing veya XmlResolver özelliklerine yapılan atamalara özellikle dikkat edin.
  4. Eski API'leri Kontrol Edin: XmlTextReader gibi eski sınıfların kullanımını ve DtdProcessing özelliklerinin nasıl ayarlandığını kontrol edin.
  5. Bağlamı Değerlendirin: Güvensiz bir desen bulduğunuzda, işlenen XML'in kaynağını belirleyin. Eğer girdi tamamen kullanıcı kontrolündeyse (örneğin bir API isteğinin gövdesi, yüklenen bir dosya), zafiyetin etkisi kritiktir. Eğer girdi, uygulama içinde güvenilir bir kaynaktan geliyorsa, risk daha düşüktür.

Özet ve Sonraki Adımlar

Bu derste, .NET ekosisteminin XML ayrıştırma güvenliğine yaklaşımını ve bir denetçi olarak odaklanmamız gereken kilit noktaları öğrendik.

Anahtar Çıkarımlar:

  • Modern .NET, DTD işlemeyi varsayılan olarak yasaklayarak Java'nın eski sürümlerine göre daha güvenli bir başlangıç noktası sunar.
  • XXE zafiyeti genellikle geliştiricinin DtdProcessing.Parse ayarını bilinçli olarak etkinleştirmesiyle ortaya çıkar. Bu, kod denetimindeki birincil hedeftir.
  • XmlReaderSettings, XmlReader ve XmlDocument gibi temel ayrıştırıcıların güvenlik davranışını kontrol eden merkezi mekanizmadır.
  • XslCompiledTransform, new XmlUrlResolver() ile birlikte kullanıldığında XXE için gizli ve tehlikeli bir vektör haline gelir.
  • LINQ to XML (XDocument), DTD'leri işlemeyen tasarımı sayesinde XXE'ye karşı doğal bir koruma sağlar.

XML gibi yapılandırılmış verilerin ayrıştırılmasındaki riskleri inceledik. Bir sonraki modülde, daha genel ve genellikle daha tehlikeli bir veri işleme biçimine, yani nesne serileştirme ve serileştirmenin tersine çevrilmesine (deserialization) geçeceğiz. Gelecek dersimizde Java, Python, .NET ve Node.js gibi çeşitli ekosistemlerde güvensiz deserialization giriş noktalarını nasıl tespit edeceğimizi keşfedecek ve uzaktan kod çalıştırma (RCE) gibi kritik zafiyetlere giden yolları analiz edeceğiz.