Uygulama Güvenliği
Insecure Deserialization Saldırıları
Günümüz modern web uygulamalarında hemen her işlevde verilerin depolanması ve bu verilerin bilgisayar ağları içerisinde taşınması ihtiyacı bulunur. Verilerin işlenmesi için önemli noktalardan birisi de aynı veri formatının kullanılması açısından standart bir veri formatı oluşturulmasıdır. Bu veri formatlarının işlenmesi sırasında ise “insecure deserialization” zafiyetleri ortaya çıkabilir.
Insecure deserialization zafiyetini incelemeden önce zafiyetin temelini oluşturan “serialization” ve “deserialization” kavramları hakkında bilgi sahibi olmamız gerekiyor.
Serialization
Türkçe olarak “serileştirme” olarak adlandırabileceğimiz bu kavram, bazı nesneleri daha sonra geri yüklenebilecek bir veri biçimine dönüştürme işlemidir. Bu işlem sırasında nesneler “bytestream” yapılarına dönüştürülür. Uygulamalar, genellikle depolama veya iletişimin bir parçası olarak gönderilmek üzere nesneleri seri hale getirir. Verileri seri hale getirilirken, nesnenin nitelikleri ve aldığı değerler kaydedilir. “Ali/Veli adında 25 yaşında bir erkek”, {male|25|Ali|Veli} gibi bir formata dönüşür.
Örneğin PHP’de aşağıdaki gibi bir kullanıcı nesnemiz olsun;
$user->name = "carlos";
$user->isLoggedIn = true;
Bu nesne serileştirildiğinde aşağıdaki gibi görünür.
O:4:"User":2:{s:4:"name":s:6:"carlos"; s:10:"isLoggedIn":b:1;}
Bu veriyi aşağıdaki gibi yorumlayabiliriz.
- O:4:"User" – 4 karakterli “User” isimli bir sınıfa ait bir nesne (object)
- 2 – Nesneye ait olan iki nitelik olduğu belirtiliyor.
- s:4:"name" – İlk nitelikteki veriye ait key değerinin 4 karakter dizesinin (string) "name" olduğu belirtiliyor.
- s:6:"carlos" – İlk nitelikteki veriye ait value değerinin 6 karakter dizesinin (string) "carlos" olduğu belirtiliyor.
- s:10:"isLoggedIn" - İkinci nitelikteki veriye ait key değerinin 10 karakter dizesinin (string) "isLoggedIn" olduğu belirtiliyor.
- b:1 - İkinci nitelikteki veriye ait value değerinin “boolean true” olduğu belirtiliyor.
Deserialization
Türkçe olarak “seriden çıkarma” olarak adlandırabileceğimiz bu kavram, serileştirme işleminin tersidir. Bir formattan yapılandırılmış verileri alır ve tekrar bir nesne olarak yeniden oluşturur. Bugün, verileri seri hale getirmek için en popüler veri formatı JSON'dur.
https://portswigger.net/web-security/deserialization adresinden alınmıştır.
Birçok programlama dili, nesneleri serileştirmek için kendi içerisinde bir yetenek sunar. Bu yerel biçimler, genellikle serileştirme sürecinin özelleştirilebilirliği de dahil olmak üzere JSON veya XML'den daha fazla özellik sunar.
https://infosecwriteups.com/insecure-deserialization-its-super-hard-or-is-it-94d89e2847 adresinden alınmıştır.
Ne yazık ki bu yerel seriden çıkarma mekanizmalarının özellikleri, güvenilmeyen veriler üzerinde çalışırken kötü amaçlı etkilere olanak sağlayabilir. Seriden çıkarma sırasında, güvenilmeyen bir kaynaktan veri okuma, kullanıcı girdisini doğrulamadan geçirmeden işleme, dijital imzaları doğrulanmamış sınıflardan veri okuma gibi işlemler ile insecure deserialization zafiyeti ortaya çıkabilir. Insecure deserialization saldırıları, hizmet reddi (DoS), erişim denetimi ve uzaktan kod yürütme (RCE) gibi etkiler ortaya çıkarabilir. Deserialization saldırıları çoğunlukla tespit edilmesi zor ve sebep oldukları etki açısından büyük saldırılardır. Temelde kullanıcının gönderdiği özel hazırlanmış seri halindeki (serialized) verilerin seriden çıkarılması (deserialization) sırasında ortaya çıkan saldırılardır.
Serialization/deserialization işlemleri ile karşılaşılabilecek bazı alanlar aşağıdaki gibidir;
- HTTP Parametreleri (ViewState), Cookie, Bileşenler
- XML
- JSON
- Veri tabanı, Mesaj Kuyrukları
Nasıl Oluşur
Java ile yazılmış bir uygulamaya yönelik senaryo üzerinden zafiyeti daha detaylı inceleyelim.
1. Uygulamamızda kullanıcıları tanımlayan sınıfımız aşağıdaki gibi olsun.
Kullanıcı adı ve şifre özniteliklerini içeren “User” sınıfı
2. Kullanıcı sınıfından bir nesne üretip bunu user.txt içerisine yazalım.
Kullanıcı nesnesini dosya içerisine serileştirme
3. Bytestream verisini user.txt dosyasından okuyalım ve kullanıcı sınıfını tekrar oluşturmak için deserialization yapalım.
Kullanıcı nesnesinin dosyadan okunarak seriden çıkarılması
Bu uygulama akışında sorun, programın herhangi bir doğrulama yapmadan verileri seriden çıkarmaya çalışmasıdır. Saldırgan serileştirilmiş verileri değiştirerek herhangi bir saldırgan eylemi gerçekleştirmek için uygulamaya gönderebilir.
Örnek Saldırı Senaryoları
Bu bölümde PortSwigger Web Security Academy üzerinde yer alan “Lab: Modifying Serialized Objects” uygulaması üzerinden örnek bir saldırı senaryosu inceleyeceğiz. Bu uygulamada bizden yetkilerimizi yükseltmemiz ve Carlos kullanıcısına ait kullanıcıyı silmemiz isteniyor.
Öncelikle uygulamaya kendi kullanıcımız ile giriş yapalım.
Uygulamaya başarılı bir şekilde giriş yapıldığında “session” isimli bir cookie atandığını görüyoruz.
Set-Cookie: session=Tzo0OiJVc2VyIjoyOntzOjg6InVzZXJuYW1lIjtzOjY6IndpZW5lciI7czo1OiJhZG1pbiI7YjowO30%3d; Secure; HttpOnly; SameSite=None
Cookie verisi Base64 Encode ve URL Encode edilmiş. Bu veriyi öncelikle URL Decode, sonrasında da Base64 Decode ettiğimizde karşımıza aşağıdaki gibi bir veri çıkıyor.
O:4:"User":2:{s:8:"username";s:6:"wiener";s:5:"admin";b:0;}
Bu veriyi anlamlandırmaya çalışalım. Veri içerisinde 4 karakteli “User” isimli nesne bulunuyor ve bu nesnenin 2 nitelik içerdiği belirtiliyor. İlk niteliğimiz 8 karakterli “username” niteliği ve bu niteliğe karşılık 6 karakterli “wiener” değeri atanmış. İkinci niteliğimizde ise 5 karakterli “admin” niteliği bulunuyor ve karşılığında da “boolean false” değeri atanmış.
Bu aşamada saldırgan olarak, “admin” niteliğinin yönetici haklarını temsil ettiğini ve bu niteliği “boolean true” olarak değiştirerek yönetim paneline erişim durumunu test etmeye çalışabiliriz. Cookie içerisindeki veri değiştirilerek aşağıdaki formatta hazırlanabilir.
O:4:"User":2:{s:8:"username";s:6:"wiener";s:5:"admin";b:1;}
Gerekli encoding işlemlerini de yaptıktan sonra uygulama içerisinde oturumumuzu temsil eden session cookie değerini aşağıda hazırlamış olduğumuz “admin” session verisi ile değiştirebiliriz.
Tzo0OiJVc2VyIjoyOntzOjg6InVzZXJuYW1lIjtzOjY6IndpZW5lciI7czo1OiJhZG1pbiI7YjoxO30%3d
Session cookie’sini değiştirdiğimizde artık yönetim paneline erişim sağlayıp Carlos kullanıcısını silebildiğimizi görüyoruz.
Önlemler
Deserialization saldırılarını önlemek için genel kurallar aşağıdaki gibidir.
- Dilden bağımsız formatlar kullanımı: “Native Binary” formatlar yerine standart JSON, YAML gibi formatlar kullanılmalıdır.
- Bütünlük kontrolleri: Eğer mümkünse, serileştirilmiş veriler için dijital imza doğrulaması yapılmalıdır. Bu kontrollerle birlikte kullanıcı tarafından sağlanan zararlı girdilerden kaçınılabilir.
- Girdi denetimleri: Kullanıcı tarafından sağlanan verilere asla güvenilmemelidir ve mümkünse serileştirme işlemlerinde kullanıcı girdilerine yer verilmemelidir.
- Düşük yetkili ortam: Seriden çıkarma işlemleri en az yetki barındıran ortamlarda, en az yetki çalıştırabilen kullanıcılar ile yapılmalıdır.
Referanslar
https://portswigger.net/web-security/deserialization
https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html
https://medium.com/blog-blog/insecure-deserialization-e5398e83defe
https://gupta-bless.medium.com/exploiting-insecure-deserialization-2ccaa7cfea68
https://hdivsecurity.com/bornsecure/insecure-deserialization-attack-examples-mitigation/
https://www.youtube.com/watch?v=jwzeJU_62IQhttps://www.youtube.com/watch?v=nkTBwbnfesQ
Son derece başarılı ve bilgilendirici bir makale. Teşekkür ediyorum.