Cross Site Request Forgery (CSRF)

Cross Site Request Forgery (CSRF) Zafiyeti Nedir?

CSRF zafiyeti saldırganın bir kullanıcıyı kandırarak bir linki açması, bir butona tıklaması ya da bir bağlantıya tıklaması aracılığıyla o kullanıcının hesabı üzerinde kullanıcı istememesine rağmen bazı şeyleri değiştirme ya da işlem yapılmasına izin veren zafiyete denir.

Bir saldırganın, farklı web sitelerinin birbirine müdahale etmesini önlemek için tasarlanmış olan same origin policy’i kısmen atlatmasına olanak tanır.

CSRF Zafiyetinin Etkileri

Başarılı bir CSRF Zafiyetin saldırganın bir kullanıcının şifresini değiştirmesine, hesabına para aktarmasına, e-mail hesabını değiştirip daha sonra hesabını ele geçirmesine ve saldırı yaptığı kullanıcı application üzerinde yüksek yetkilere sahip ise tüm app’in kontrolünü ele geçirmeye kadar ulaşan geniş ve derin çaplı etkileri bulunmaktadır.

Önce Teorik olarak zafiyetin nasıl meydana geldiğini ele aldığımıza göre biraz daha pratik uygulamalar eşliğinde konuya devam edelim. Pratik uygulamaları PortSwigger lab’ları üzerinden gösteriyor olacağım.

Lab 1: CSRF vulnerability with no defenses

Lab’ı açtıktan sonra bize verilen login bilgileri ile giriş yapıyoruz. Daha sonra karşımıza aşağıdaki ekran görüntüsündeki gibi bir e-mail değiştirme fonksiyonu çıkmakta.

Burada öylesine bir mail güncelleme işlemi yapıp giden isteği inceliyoruz. İstek aşağıdaki ekran görüntüsünde görülmektedir.

 

 

Daha sonra aşağıdaki ekran görüntüsündeki gibi sağ tıklayıp “engagement tool” seçeneğinin üstüne gelip oradan “Generate CSRF PoC” seçeneğini seçiyoruz bu şekilde bize otomatize olarak bir CSRF saldırısında kullanılabilecek HTML script’i oluşturuyor.

 

 

Oluşturulan HTML script’i aşağıdaki ekran görüntüsünde görülmektedir.

 

 

Buradaki yazılanları kısaca açıklayacak olursak.

5. satırdaki “from action” hangi “url” üzerinde işlem yapılacağını belirtiyor ve devamındaki “method” kısmında ise hangi method’u kullanacağımızı belirtiyoruz burada bir güncelleme işlemi var yani sunucuya bir “POST” isteği gideceğinden dolayı “POST” “method” kullanıyoruz.

Altındaki satırdaki “input type” kısmında ise giden değeri kurbanın görmemesi için “hidden” şeklinde seçiyoruz değiştireceğimiz değer “email” olduğu için değiştireceğimiz değişkenin adını “name=email” yapıyoruz ve “value” kısmında ise hangi değer ile değiştireceğimizi belirtiyoruz.

7. satırda ise isteği “sumbit” edeceğimiz için “type” olarak “submit” ve “value” olarak da “submit request” olarak ayarlıyoruz.

 Oluşturulan script’in son hali aşağıdaki ekran görüntüsünde olduğu gibidir ve buna önce “store” butonuna tıklayarak kaydediyoruz ve  daha sonra “deliver exploit to victim” butonu ile kurbana göndererek lab’ın çözümünü sağlıyoruz.

 

 

Lab 2: CSRF where token validation depends on request method

Bu lab’da yine üstteki ile benzer işlemleri farklı bir senaryo üzerinden yapacağız. Önce login olduk ve yine mail değiştirme fonksiyonunu kullandık, sunucuya giden istek aşağıdaki ekran görüntüsünde verilmiştir.

 

 

İsteği inceliyoruz ve görüldüğü gibi bir csrf token bilgisi eklemiş giden istekte, bu demektir ki bu token bilgisi olmadan istenilen değişiklik yapılmaz bu nedenle bu token’i de giden istekte bulundurmalıyız. Yine üstteki lab’da olduğu gibi bir HTML script oluştuyoruz. Oluşturduğumuz script aşağıdaki ekran görüntüsünde verilmiştir ve bunu “store” ve “deliver exploit to victim” ile gönderiyoruz fakat lab’ın çözümü sağlanmıyor.

 

 

Kullanılan “POST” method’u ile istenilen işlemin gerçekleşmediği anlaşılıyor, farklı bir “method” deneyerek bu engeli aşmayı deniyoruz ve aşağıdaki ekran görüntüsünde de görüldüğü gibi “method” bilgisini “GET” olarak değiştirip deniyoruz ve lab’ın çözümü sağlanmış oluyor.

 

 

Lab 3: CSRF where token validation depends on token being present

Üstteki lab’lar ile benzer adımları izleyip önce bir mail değiştirme işlemi yapıp isteği inceliyoruz.

 

 

Bir HTML script oluşturup aşağıdaki gibi bunu göndermeyi deniyoruz ama işlem başarılı olmuyor. Yani bir csrf token değeri var ve bizdeki token değeri ile işlem gerçekleştirilemiyor.

 

 

Daha sonra csrf değerini silerek yeniden deniyoruz. Aslında şunu deniyoruz arka planda csrf token değerini kontrol eden bir sistem var elindeki token’i kontrol ediyor doğru mu yanlış mı diye. Bizdeki yanlış ama silerek gönderdiğimizde token’in olmadığı durumunu sağlıklı şekilde kontrol etmediği için aşağıdaki ekran görüntüsündeki gibi bir script gönderdiğimizde lab’ın çözümünü sağlamış oluyoruz.

 

 

Lab 4: CSRF where token is not tied to user session

Bu lab’da zafiyetin nedenleri arasında bahsettiğimiz token’in kullanıcı session’u ile bağlantısının olmadığı bir senaryoyu inceleyeceğiz.

İki farklı kullanıcı bilgisi var görüldüğü üzere ilk önce carlos kullanıcısı ile giriş yapıyoruz. Burada bir mail değiştirme işlemi yapıyoruz ve giden istek aşağıdaki ekran görüntüsünde görülmektedir.

 

 

Burada csrf token bilgisini kopyalıyoruz ve isteği drop ediyoruz. Bu işlemin gerçekleşmemesi bu token’i hala kullanabilir kıldığı için bunu yapıyoruz.

Peki neden buradaki token bilgisini kopyaladık? Bunu yaptık çünkü buradaki senaryo üzerinde uygulamada bir token havuzu var ve gelen istekteki token bilgisi havuzda var mı diye bakıyor. Mevcut işlem yapan kullanıcıya ait mi diye kontrol etmiyor. Bizde başka bir hesaptan edindiğimiz token bilgisi ile başka bir kullanıcı üzerinde CSRF saldırısı yapabiliyoruz.

Token’i aldıktan sonra gizli pencere açıp buradan wiener kullanıcısına girip mail değiştirme isteği üzerinden yine bir HTML script oluşturuyoruz. Ardından carlos kullanıcısından edindiğimiz token’i mevcut token ile değiştiriyoruz. Bu şekilde isteği “store” edip deliver ettiğimizde lab’ın çözümü sağlanmış oluyor.

 

 

Lab 5: CSRF where token is tied to non-session cookie

Bu lab’da yine başka bir kullanıcının mailini değiştirmeye çalışacağız ilk önce carlos hesabına giriş yapıyoruz ve giden isteği inceliyoruz.

 

 

İstekte görüldüğü üzere hem csrf hem de crsfKey değeri var şimdi bunlar birbirine bağlı mı nasıl bağlı arasında bir açıklık var mı onu denememiz gerekli. Bunun için wiener hesabına geçiş yapıp mail değiştirme isteğini yakalayıp repeater’a gönderiyoruz.

 

 

Arasındaki bağlantıyı anlamak için önce sadece carlos hesabında csrf değeri ile buradaki değer değiştirip bu isteği gönderiyoruz sonuç alamadık. Daha sonra csrfKey değerini değiştiriyoruz ama yine sonuç alamadık. Fakat iki değeri birden değiştirir isek o zaman istek başarılı şekilde gidiyor. Demek ki göndereceğimiz CSRF isteğinde her iki değer de bulunmalı çünkü bunlar da birbirine bağlı şekilde kontrol edilmektedir.

Wiener’in isteği üzerinden bir HTML script oluşturuyoruz. Aşağıdaki ekran görüntüsünde görüldüğü gibi bir csrf değeri var fakat csrfKey değeri yok bu istek bu şekilde işe yaramaz bizim bu script’in içine bir de csrfKey değeri eklememiz gerekli.

 

 

Bu ekleme işlemini nasıl yapacağımız araştırıyoruz ve site üzerinden arama yapıyoruz. Görüldüğü gibi arama yapılırken search parametresinin yanına bir değer gelmekte yani biz bunu yanına başka değerler eklersek aslında bir sonuç alabiliriz. Aşağıdaki ekran görüntüsünde de görüldüğü gibi csrfKey değerini ekliyoruz ve dönen cevapta bize yansıtıldığını görüyoruz yani bir şekilde bizde gönderdiğimiz istekte bunu yapmalıyız.

 

 

Oluşturduğumuz HTML script’ine aşağıdaki ekran görüntüsündeki gibi img src= ile csrfKey değerini ekliyoruz burada img tag’i kullanmamızın nedeni bir img tag’i resim yüklemek için kullanılmakta. İçinde bulunan resmi göstermesi için belirtilen adrese bir istek yapacağından dolayı bizim csrfKey değerini kullanmamızı sağlamaktadır o nedenle bu şekilde onu ekliyoruz.

 

 

“Store” edip “deliver” ettiğimizde lab’ın çözümünü sağlamış oluyoruz.

 Lab 6: CSRF where token is duplicated in cookie

Buradaki lab’da iki tane csrf değeri göndererek başarılı olacağımız bir senaryo bulunmakta. Önce arama kısmından bir arama yaparak isteği inceliyoruz.

 

 

İstek içerisine bir önceki lab’da olduğu gibi csrf değeri ekleyip gönderiyoruz yansıtılıp yansıtılmadığını anlamak için yaptığımızdan anlamsız bir değer girip gönderdik.

Aşağıdaki ekran görüntüsünde olduğu gibi bu değer geri yansıtıldı.

 

 

Daha sonra bir HTML script üretiyoruz ve yine img tag’i içerisine search yapıyormuş gibi bir satır ekleyip devamına duplicate olarak göndermek istenilen csrf token değeri eklenir ve bu halde gönderilir.

 

 

Yukarıdaki script deliver edildikten sonra lab’ın çözümü sağlanmış oluyor.

Lab 7: CSRF where Referer validation depends on header being present

Bazı uygulamalar referer header’in olup olmaması ile kontrollerini gerçekleştirmektedir. Bu yöntem pek etkili olmasa da kullanıldığı senaryolar da mevcuttur, bu lab’da bu senaryo üzerinden bir çözüm gerçekleştireceğiz.

Mail değiştirmek için giden isteği repeater’a gönderip üzerinde zafiyetin tespiti için denemeler yapıyoruz.

İlk önce referer parametresinin değerini değiştirip bunu gönderiyoruz ve aşağıdaki ekran görüntüsünde görüldüğü üzere başarılı olmuyor.

 

 

Daha sonra aşağıdaki ekran görüntüsündeki gibi referer header’ini silip gönderdiğimizde başarılı bir sonuç alıyoruz yani göndereceğimiz istekte referer header’i olmaz ise istenilen sonucu alabileceğimizi görüyoruz.

 

 

Aşağıdaki gibi bir HTML script oluşturuyoruz ve daha sonra head başlığı açıp burada referer başlığının bulunmamasını sağlayacak satırı ekliyoruz.

 

 

Yukarıdaki script’i deliver ettikten sonra lab’ın çözümünü sağlamış oluyoruz.

 Lab 8: CSRF with broken Referer validation

Bu senaryoda uygulama referer header’in olması durumunu da kontrol etmekte fakat devamına başka bir domain eklediğimizde buna bir engel bulunmamakta. Yani kendi domain adresi var mı diye bakıyor sadece başka bir şeyin eklenmiş olması durumunu kontrol etmiyor.

İlk önce referer header üzerinde değişiklikler yapıp ne sonuç alacağımızı görüyoruz.

Aşağıdaki ekran görüntüsünde görüldüğü gibi ilk önce değiştirmeyi deniyoruz ama başarılı bir sonuç alınmadı.

 

 

Daha sonra silip yeniden isteği gönderiyoruz ama yine sonuç alamıyoruz.

 

 

Bunun ardından aşağıdaki ekran görüntüsünde olduğu gibi istenilen url bilgisini silmeden kendi üstüne ekstra bir url ekliyorum ve 302 dönüyor sonuç aldık.

 

 

Bir HTML script’i oluşturuyoruz ve aşağıdaki gibi script’i düzenliyoruz.

history.pushState fonksiyonu tarayıcı oturum geçmişi stack’ine bir giriş eklemek için kullanılır. 3 tane parametresi vardır bunlar; ilk parametre: state object, ikinci parametre: title ve üçüncü parametre: url bilgisini içerir.

Bu nedenle oraya istenilen domain bilgisini yazarak yolluyoruz.

Referrer-Policy:unsafe-url satırını ekliyoruz.

Bunun nedeni bazı browser’lar güvenlik mekanizmaları nedeni ile gelen referer header ile birlikte gelen query parameter değerlerini görmezden gelmektedirler. Bunu ekleyerek bizim sonradan eklediğimiz query string değerini görmezden gelip ya da silmek yerine işletecektir.

 

 

Yukarıdaki şekilde store edip deliver ettiğimizde lab’ın çözümünü başarılı şekilde sağlamış oluyoruz.

Zafiyetin Nasıl Engellenir?

Bu zafiyeti engellemenin en sağlam yolu ilgili isteklerin içine bir CSRF token’ı eklenmesidir.

Bu token bilgisi şu şekilde olmalıdır:

  • Tahmin edilmesi çok zor olarak üretilen bir değer olmalı
  • Kullanıcının oturumuna bağlı olmalı
  • İlgili bir eylem gerçekleşmeden önce her seferinde sağlam bir kontrolden geçilmeli

 

Emin FİDAN tarafından hazırlanmıştır.



Yorum Yaz

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

*
*

Mail listemize üye olarak eğitim fırsatlarını kaçırmayın!
Eğitim ve ücretsiz etkinliklerizden haberdar olmak için e-posta listesimize üye olun!.