Cookie replay attack geçerli bir cookie değerinin çalınması sonucu, kurbanın oturumunu kullanarak, yetkisiz işlemler yapılmasına denir. Oturum çalma işlemi birden fazla yolla yapılabilir. Bu yazımızın konusu bunlar olmayacak. Eğer oturum çalma işlemlerinin nasıl yapıldığını merak ediyorsanız Session Hijacking, Session Fixation ve XSS konularını araştırıp bulduğunuz kaynaklardan ilerleyebilirsiniz.

Cookie replay attack, konsept olarak çok basit bir saldırı yöntemi. Bu yöntemde ele geçirilmiş çalışan oturumu kullanıyoruz. “Bunu blog yazısı ile anlatmaya ne gerek vardı Alperen?” dediğinizi duyar gibiyim :) Zaten benim de amacım bu konuyu karşılaştığım bir örnekten yola çıkarak irdelemek. Belki günlük testlerimizde çok işimize yaramayacak, sebebini yazının sonunda açıklayacağım, fakat güvenlik bakış açısı ile çok sık kullanılan Logout yani oturum sonlandırma özelliğinde yapılan bir yanlışı ele alacağız.

Geçtiğimiz aylarda “Cookie replay attacks in ASP.NET when using forms authentication” başlıklı blog yazısını okudum. Bu blog eski bir blog yazısıydı ve bahsettiği konu ise çok çok daha eskiydi. Özetle asp.net kütüphanesinde FormsAuthentication.SignOut methodu cookie replay attack vektörünün oluşmasına sebep oluyordu. Açıkçası günümüzde bunu kötüye kullanmak zor fakat uygulama geliştirme kütüphanesinde böyle bir açıklığın olması bende ilgi uyandırdı. Hadi oradaki olayı bir örnekle inceleyelim:

Düşünün ki okulunuzun öğrenci bilgi sistemine giriş yaptınız. Notlarınızı, duyuruları kontrol ettiniz işiniz bitti ve Logout butonuna tıklayarak sistemden çıkışınızı yaptınız. Muhtemelen karşınıza tekrardan giriş yapma sayfası geldi. Buraya kadar her şey çok güzel fakat gerçekten oturumunuz sonlandı mı?

Gelin bu süreci adım adım inceleyelim:

  • Öğrenci sisteminize giriş yapmak için ilgili sayfayı yüklediniz. Herhangi bir oturumunuz olmadığı için /Login.aspx sayfasına yönlendirildiniz.
  • Siteye henüz giriş yapmadığımız için sunucu bizi tanımıyor. Kullanıcı bilgilerimizi doldurup login butonuna tıkladığımızda sunucu bu bilgileri kontrol ediyor ve doğruysa bizi daha sonrasında tanımak için bize oturum anahtarımızı içeren cookie set ediyor. (Burada örneğinimiz dotNet ile ilgili olduğu için muhtemelen cookie adı “ASP.NET_SessionId” olacaktır.)
  • Artık isteklerimizde aşağıdaki şekilde cookie gittiği için sistem bizi tanıyor ve ona göre kullanıcımız ile ilgili işlemleri gerçekleştirebiliriz.
GET http://localhost:60850/Manage HTTP/1.1

Host: localhost:60850

Cookie: ASP.NET_SessionId=eOmKoD1gqF1kiREWxG
  • İşlemlerimiz bittikten sonra Logout butonuna bastık ve çıkış yapmak istedik. Bildiğiniz gibi cookieler tanımlanırken expires değeri olarak verdiğiniz tarihe kadar cookie geçerliliğini korur ve bir cookie silmek istediğinizde expires tarihini geçmiş bir tarih verirsiniz. (Eğer cookie konusunda eksik bilginiz varsa buradaki yazıyı okumanızı öneririm.) Burada da expires alanına geçmiş bir tarih verilerek cookienin browser belleğinden silinmesi sağlanıyor.

Şimdi tekrar başa dönelim. Browser belleğinden cookie silindiği için artık isteklerimizde cookie gitmiyor ve biz yetki gerektiren işlemleri yapamıyoruz. Fakat sunucu tarafından oturumumuzun sonlandığına nasıl emin olacağız? Az önce browser belleğinden silinen cookie değeri ile siteye tekrar istek gönderiyoruz. (Burada Fiddler’ı kullanabiliriz.)

GET http://localhost:60850/Manage HTTP/1.1

Host: localhost:60850

Cookie: ASP.NET_SessionId=eOmKoD1gqF1kiREWxG

Normal şartlarda 302 durum kodu ile /Login.aspx sayfasına yönlendirme yapılmalı fakat sunucu tarafında oturum silinmediyse tekrar login olduğumuzda gelen sayfayı görebiliriz. Tabii sunucu tarafında session silinmese bile aynı session id ile farklı ip adreslerinden istek gelmesini engellemiş olabilir. Biz burada bu durumların olmadığını varsayıyoruz. Böyle bir durumda cookie geçerliliğini devam ediyor olacak ve eğer çalınırsa sunucu tarafında oturum sonlanana kadar kötüye kullanabiliyor olacağız.

Bu durumu Visual Studio 2015 ile örnek bir asp.net mvc projesi oluşturarak repro edebildim. Hatta deneyenler bilir proje oluştururken hazır bir template ve üyelik sistemi ile oluşturabiliyorsunuz. Size gelen hazır üyelik sistem içerisinde de bu durum devam ediyor. Hatta buradaki class adını araştırdığımda stackoverflowda tam olarak bu konuyla ilgili soru sorulduğunu da gördüm : https://stackoverflow.com/questions/29090808/mvc-authenticationmanager-signout-is-not-signing-out

MSDN platformunda şöyle bir açıklama mevcut:

“The Web server does not store valid and expired authentication tickets for later comparison. This makes your site vulnerable to a replay attack if a malicious user obtains a valid forms authentication cookie.”

Yine stackoverflow üzerinde bu konunun nasıl çözülebileceği tartışılmış: https://stackoverflow.com/questions/16062808/form-authentication-cookie-replay-attack-protection

Tabii bu konuyu sadece .NET Framework özelinde ele almamak gerekiyor. Genelde yazılımcılar oturum yönetimi gibi temel ihtiyaçlarını kütüphanelerin sağladıkları imkanlarla hızlıca hallediyorlar ve bunların doğru çalışması konusunda yine kullandıkları kütüphaneye güveniyorlar. Buradaki tasarım/mantık, artık siz ne diyorsanız, hatası da her kütüphanede olabilecek türden ve araştırdığımızda farklı dillerde/kütüphanelerde de örneklerini görebiliyoruz.

Kötüye kullanımı neden zor?

  • HTTPS kullanımını günümüzde çok yaygınlaştığı için ağ trafiğini dinleyerek oturum çalmanın zor olması
  • Cookie tanımlarken Secure belirteci ile cookie’nin sadece https isteklerinde gitmesi gerektiği browser’a söylenebilir bu da yine ağ trafiğini dinleyen birisinin http isteğinden cookie’nin çalmasını engeller. Örneğin http://example.com isteği yaptınız ve site sizi https’e yönlendirdi. Evet https’e yönlendirdikten sonra trafik şifreli şekilde ilerliyor fakat ilk isteği siz HTTP üzerinden yapmış oldunuz. Browser HTTP isteğine, eğer cookie Secure olarak işaretlenmedi ise, ilgili cookieler eklenecektir. Bu da ağda şifresiz şekilde cookie’nin gitmesi demek oluyor :) O yüzden bu belirteci kullanmak önemli ve artık günümüzde çok yaygın bir şekilde kullanılıyor.
  • Oturum bilgisi barındıran cookielerin httpOnly belirteci ile tanımlanması sonucu XSS zafiyetini kullanarak oturumun çalınamıyor olması (Eğer sunucuda HTTP Trace methodu enable ise httpOnly atlatılabilir. Bu olaya literatürde XST yani Cross-Site Tracing deniyor.)
  • Birçok kütüphane oturum anahtarlarını rassaslığı yüksek değerler set ediyor. Bu da oturum anahtarının tahminine yönelik saldırıları zorlaştırıyor.

Fark etmişsinizdir yukarıda bahsettiklerim oturum anahtarının çalınmasının zorluğu ile ilgili, oturum anahtarını ele geçiremediğiniz zaman cookie replay atağının da kötüye kullanımı mümkün olmuyor. Bu konu ile ilgili daha çok şey yazılabilir fakat yazı yeterince uzun oldu diye düşünüyorum.

Twitter adresimde paylaştığım gibi bundan sonra düzenli blog postlar yayınlama amacım var. Bunu diyeli her ne kadar 2-3 hafta geçmiş olsa bile zamanla blog yazma olayını rutine dönüştüreceğime inanıyorum. İlk blog postlarım kıyıda köşede kalmış üzerine çok fazla Türkçe içerik üretilmemiş konular olacak. Daha sonrasında özgün ve güncel içerikler üretmek için boş zamanlarımda araştırma yapıyor olacağım.

Görüşmek üzere!