Insecure Deserialization

Merhaba, bugün sizlere insecure deserialization zafiyetinden bahsedeceğim. Öncelikle bu mekanizma, bir nesnenin taşınabilir bir formata dönüştürülmesini sağlar. Yani biz verilerle uğraşırken bize ciddi bir kolaylık sağlayan bir yapıdır.

Ancak sağladığı bu kolaylık, beraberinde ciddi riskler de getirir. Çünkü bu süreçte nesneler manipüle edilebilir, bu da enjeksiyon saldırılarına ve hatta RCE (Remote Code Execution) gibi kritik zafiyetlere kadar gidebilir.

Kullanım Yerleri

Birçok programlama dilinde sadece nesneler değil, veri yapıları da serileştirilir. Bu da potansiyel saldırı yüzeyini genişletir. Örneğin Python’da kullanılan pickle kütüphanesi, özellikle makine öğrenmesi modellerini kaydetmek için sıkça tercih edilir. Buna karşılık JSON gibi formatlar genellikle daha güvenli kabul edilir. Bunun sebebi, bu formatların çoğunlukla yalnızca veri taşıması ve iş mantığı içermemesidir.

Ancak burada oluşan zafiyet çoğu zaman doğrudan bir kodlama hatasından değil, geliştiricilerin daha kolay olan yolu tercih etmesinden kaynaklanır.

Serialization

Serileştirme, bir nesnenin durumunu (değişken ve değerleri) anlık bir görüntüsünü alıp kaydedebilen veya ağ üzerinden gönderebilen bir formata(byte akışı veya JSON dizesi gibi) dönüştürmek olarak düşünün. Buradaki kilit nokta veriyi kaydettiğinzidir metotları kaydetmiyorsunuz.

API endpointlerinde, caching, persistaence(cookie) bunlara örnek verilebilir.

Deserialization

Deserialization ise bunun tam tersidir. Daha önce serileştirilmiş bir veri alınır ve bellekte tekrar orijinal nesneye dönüştürülür.

Bu noktadan sonra uygulama, oluşturulan bu nesneye tamamen güvenilir bir nesne gibi davranır. Tehlike de tam olarak burada ortaya çıkar. Eğer saldırgan deserialize edilen veriyi kontrol edebiliyorsa, bu durum bir nevi truva atına dönüşür.

Serileştirme Formatları:

Binary (ikili) formatlara Java’nın yerel serileştirmesi örnek verilebilir. Genellikle Base64 formatında “rO0” ile başlayan çıktılar görülür. Bu formatlar makineler için oldukça verimlidir ancak insanlar tarafından okunamaz. Aynı zamanda en tehlikeli formatlardır çünkü çoğu zaman kötüye kullanılabilecek zengin tip bilgileri içerirler.

Metin tabanlı formatlar ise XML, JSON ve YAML gibi yapılardır. Bunlar insanlar tarafından okunabilir ve genellikle daha güvenli kabul edilir. Çünkü yalnızca veri taşımaları beklenir. Ancak yanlış yapılandırılmış kütüphaneler veya otomatik nesne dönüştürme mekanizmaları kullanıldığında, bu formatlar bile saldırı vektörüne dönüşebilir.

Zafiyet

Zafiyet genellikle güvenilir olduğu varsayılan bir nesnenin, aslında farklı bir sınıfa ait kötü niyetli bir nesne ile değiştirilmesiyle başlar. Bu nesne, sunucuda mevcut olan ancak normalde kullanıcıdan girdi olarak alınması beklenmeyen bir sınıfa ait olabilir.

Bu duruma Object Injection denir. Uygulama, gelen veriye körü körüne güvendiği için, bildiği herhangi bir nesneyi oluşturmaya çalışır. Bu süreç hata ile sonuçlansa bile, hasar çoğu zaman nesne oluşturulma aşamasında gerçekleşir.

Eğer başarılı bir deserialization saldırısı gerçekleştirilirse, sunucudaki mevcut gadget’lara ve saldırganın yaratıcılığına bağlı olarak çok farklı zafiyetler ortaya çıkabilir.

RCE (Uzaktan Kod Çalıştırma)
DoS
Privilege Escalation
Dosya Erişimi

Methods

Asıl önemli kısma geldik bunlar dillerin bir nesnenin yaşam döngüsü(oluşturmak silmek gibi) sırasında otomatik olarak çağırdığı özel metotlardır. Saldırganlar bunlara bayılır çünkü deserialization sırasında otomatik olarak tetiklenirler ve saldırı zincirleri için mükemmel bir giriş noktası sağarlar. PHP’nin ‘wakeup()’ veya Java’nın ‘readObject()’ gibi bir metodu başlatıcı gadget görevi görür.

Gadget Zincirleri(POP Property-OrientedPrograming)

İşte gerçek olay buradadır. Saldırgan tek bir kötü niyetli fonk kullanmak yerine, uygulamanın mevcut kodundan ve kütüphanelerinden bir dizi zarasız görünen metodu birbirine zincirler. Bu yeni kod enjekte etmekle iligli değil zaten orada olan kodla bir kukla ustası gibi oynamakla ilgilidir.

https://github.com/frohoff/ysoserial gibi araçlar sayesinde artık bunları bulmak daha kolaydır.

Örnek Zafiyetler

CVE-2015-7450 (Java)

CVE-2015-7450, Java dünyasında oldukça kritik bir zafiyettir. Apache Commons Collections kütüphanesinde keşfedilen bir gadget zinciri, milyonlarca uygulamayı etkiledi.

Bu kütüphane oldukça yaygın kullanıldığı için IBM WebSphere ve JBoss gibi sistemlerde çalışan birçok uygulama bir anda savunmasız hale geldi.

Bu olay, bir uygulamanın güvenliğinin yalnızca kendi koduyla sınırlı olmadığını, bağımlılıklarının da en az onun kadar kritik olduğunu açıkça göstermiştir.

.NET ViewState Zafiyeti

ASP.NET tarafında ise ViewState zafiyeti oldukça bilinen bir örnektir. ViewState, sayfa durumunu korumak için kullanılan ve aslında Base64 ile encode edilmiş serileştirilmiş bir veridir.

Bu veri bir machineKey ile korunur. Ancak geliştiriciler çoğu zaman bu anahtarları sabit kullanır ya da internetten kopyalar. Bu anahtarın ele geçirilmesi durumunda, saldırgan sahte bir ViewState oluşturup bunu imzalayabilir.

Sunucu bu veriyi deserialize ettiğinde ise saldırgan RCE elde edebilir.

Korunma Yöntemleri

Insecure deserialization zafiyetinden korunmanın en temel yolu, güvenilmeyen veriyi doğrudan deserialize etmemektir. Eğer bu işlem yapılmak zorundaysa, yalnızca güvenilir kaynaklardan gelen veriler kullanılmalı ve mümkünse whitelist yaklaşımıyla sadece izin verilen sınıflar oluşturulmalıdır.

Ayrıca serileştirilmiş verilerin imzalanması veya şifrelenmesi, veri bütünlüğünü koruyarak manipülasyonu önler. JSON gibi daha güvenli formatlar tercih edilebilir ancak burada da strict parsing ve tip kontrolü uygulanmalıdır.

Son olarak gereksiz kütüphanelerin kaldırılması ve güncel sistemlerin kullanılması, saldırı yüzeyini önemli ölçüde azaltır.

Yunus Emre
Yunus Emre
Articles: 8