Siber güvenlik dünyasında, bir sistemi çökertecek tehditlerin çoğu zaman kendi kendini kopyalayan karmaşık virüslerden oluştuğunu düşünürüz ancak durum her zaman böyle değildir. Bazen, çok küçük boyutlu ve ilk bakışta tamamen sorunsuz görünen bir metin girdisi (payload), koca bir sistemi saniyeler içinde çökertecek bir saldırı vektörüne dönüşebilir.

Bu yazıda, sunucu kaynaklarını tüketerek sistemi felç eden ve literatürde Billion Laughs veya XML Bombası olarak bilinen zekice kurgulanmış saldırı türünü inceleyeceğiz.

XML, DTD ve XXE Bağlamı

Billion Laughs saldırısı, aslında web güvenliğinde çok daha geniş ve tehlikeli bir aile olan XXE (XML External Entity) zafiyetlerinin bir alt türüdür. XXE açıkları sadece sistemleri çökertmekle kalmaz; aynı zamanda sunucudaki hassas dosyaların okunmasına veya SSRF (Sunucu Taraflı İstek Sahteciliği) gibi kritik sonuçlara da yol açabilir.

Bu saldırıyı anlamak için öncelikle XML'in yapısına göz atmamız gerekiyor. XML, verileri yapılandırmak için DTD (Document Type Definition) adında bir özellik sunar. Bu yapı sayesinde, tanımladığımız bir veriyi (entity), XML belgesi içinde defalarca bir kısayol gibi kullanabiliriz. XML parser (ayrıştırıcı) belgeyi okuduğunda bu kısayolu görür ve asıl metinle genişleterek (entity expansion) değiştirir.

Şimdi bu "genişleme" mantığının nasıl bir silaha dönüştüğünü sadeleştirilmiş bir örnek üzerinden inceleyelim:

<?xml version="1.0"?>
<!DOCTYPE lolz [
 <!ENTITY lol "lol">
 <!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>

Kodu incelediğimizde tehlikenin nasıl üstel olarak büyüdüğünü görebiliriz: En başta tanımladığımız lol değişkeninde sadece bir tane "lol" metni var. Onun altındaki lol1 değerine 10 tane lol yerleştiriyoruz. Ardından lol2'ye 10 tane lol1 koyduğumuzda toplam 100 tane "lol" elde ediyoruz. İşlem lol3'e geldiğinde elimizde 1000 tane "lol" oluyor ve bu katlanarak devam ediyor.

En altta <lolz>&lol9;</lolz> çağrıldığında, ortaya tam 1 milyar adet "lol" metni çıkar! Eğer sistemdeki XML parser bu büyümeyi kontrol etmeden ayrıştırıp metne dönüştürmeye çalışırsa, sunucunun belleği (RAM) ve işlemcisi saniyeler içinde tükenir. Belleği tamamen dolan ve başka hiçbir meşru işleme yanıt veremeyen sunucu, başarılı bir DoS (Denial of Service) saldırısına kurban giderek çöker.

None
Photo by John Cardamone on Unsplash

Peki Bu Saldırıdan Nasıl Korunuruz?

Günümüzde, 2020 sonrası güncellenen popüler birçok XML kütüphanesi (örneğin Java'daki JAXP veya .NET'teki XmlReader) bu tür saldırılara karşı varsayılan olarak korumalı gelse de, eski sistemler, yanlış yapılandırılmış parser'lar veya spesifik kütüphaneler hala büyük risk taşımaktadır.

Sistemlerinizi bu "milyarlık kahkahalardan" ve genel XXE zafiyetlerinden korumak için uygulayabileceğiniz temel adımlar şunlardır:

  • DTD'leri Tamamen Kapatın: Eğer uygulamanızın dışarıdan gelen XML verilerini işlerken DTD kullanımına ihtiyacı yoksa, parser ayarlarından bu özelliği tamamen devre dışı bırakın (Disable DTDs). Modern web ve API sistemlerinin çoğunda DTD'ye ihtiyaç duyulmaz; en kesin ve temiz çözüm budur.
  • Derinlik ve Genişletme Limitlerini Birlikte Belirleyin: Mimariniz gereği DTD kullanmak zorundaysanız, kontrolleri iki katmanlı yapmalısınız. Sadece bellekte kaplayacağı toplam boyutu sınırlamak yetmez; ayrıştırıcınızın iç içe geçme derinliğine (entity expansion depth) de katı bir sınır getirmelisiniz. Aksi takdirde, recursive (kendi kendini çağıran) farklı entity varyantları sisteminizi yine yorabilir.
  • Güvenli Kütüphaneler Tercih Edin: Geliştirme yaptığınız dildeki standart XML kütüphanelerinin dökümanlarını mutlaka okuyun. Örneğin Python kullanıyorsanız, standart xml modülü bu tür saldırılara açık olabilir. Bunun yerine, güvenlik odaklı ve bu saldırılara karşı özel korumalar içeren defusedxml kütüphanesini kullanmak endüstri standardı bir yaklaşımdır.

Küçük ve zararsız görünen veri girdilerinin (input), sistem mimarisindeki mantıksal zafiyetleri kullanarak devasa yıkımlara yol açabileceğini unutmayın. Girdi doğrulaması yapmak ve parser yapılandırmalarınızı "güvenli varsayılanlar" (secure defaults) prensibiyle gözden geçirmek en iyi savunmanızdır.

Güvenli kodlamalar!