Uygulama Güvenliği
Cross-site Request Forgery (CSRF) ve SameSite Cookie
Bu yazımda, Cross-site Request Forgery (CSRF) saldırısının ne olduğundan, nasıl oluştuğundan, giderilmesi için neler yapılması gerektiğinden ve SameSite cookie’den bahsedeceğim.
CSRF saldırısına geçmeden önce konunun daha iyi anlaşılabilmesi için olayın en başından başlayalım. HTTP (Hypertext Transfer Protocol), stateless bir protokoldür. Stateless olması, durum bilgisini tutmadığı anlamına gelmektedir. Yani bir istek ve cevap döngüsü yaşandıktan sonra ikinci bir istekte, bir önceki döngüde ne olup bittiğine dair herhangi bir bilgi tutulmuyor.
HTTP protokolü ilk başlarda sadece statik sayfalar sunmak için tasarlanmıştı. Web teknolojilerinin gelişmesiyle birlikte uygulamalar dinamik ve daha karmaşık yapılar haline geldi. Bu gelişmeyle birlikte web uygulamaları üzerinde işlem yapan kullanıcıları tanıma ve onlara uygun içerikler sunma ihtiyacı ortaya çıktı.
Cookie’ler işte tam bu noktada hayatımıza girdi. Yapılan her istekte kullanıcı adı ve parola bilgisi gönderilmeden cookie’ler üzerinden işlem yapan kullanıcı bilgisi, sunucu tarafında takip edilebilir duruma geldi.
Web uygulamasına kullanıcı bilgilerimiz ile giriş yapıyoruz. Ardından sunucu tarafında bizim için bir session (oturum) oluşturuluyor ve bu oturuma referans eden kimlik bilgisi de cookie üzerinden bize iletiliyor.
Resmi inceleyelim. Resimdeki istemciyi kullanıcının tarayıcısı olarak düşünebiliriz.
- İlk adımda, kullanıcı example.com adresine kullanıcı bilgileri ile giriş yapar.
- İkinci adımda, sunucu tarafında kullanıcı bilgileri kontrol edilir ve doğru ise kullanıcı için bir oturum oluşturularak bu oturuma referans eden kimlik bilgisi “Set-Cookie” başlık bilgisi üzerinden tarayıcıya kaydedilir. Tarayıcı bu bilgiyi kendi veri tabanında saklar.
- Oturumu açık olan kullanıcı, örnek olarak profil sayfasını görüntülemek istediğinde tarayıcı tarafından cookie bilgisi de HTTP isteğine otomatik olarak eklenir ve bu isteği karşılayan web uygulaması, cookie üzerinden kullanıcının kim olduğunu bildiği için isteği onun oturumunda işletir.
Buraya kadar her şey normal akışta olduğu gibi ilerliyor. Tarayıcı kendi üzerine kaydettiği cookie bilgisini bundan sonra kaydettirilen domaine yapılan isteklere otomatik olarak dahil edecek. Tarayıcının bu cookie ekleme davranışı da kötüye kullanılarak CSRF (Cross-site Request Forgery) adı verilen güvenlik açığının oluşmasına zemin hazırlamaktadır.
CSRF (Cross-site Request Forgery)
Siteler arası istek sahteciliği anlamına gelen CSRF zafiyeti, tarayıcının cookie’yi ekleme davranışını kötüye kullanan bir güvenlik açığıdır.
https://medium.com/tresorit-engineering/modern-csrf-mitigation-in-single-page-applications-695bcb538eec adresinden alınmıştır.
Örnek olarak resimde yer alan kullanıcı, hesap bilgileri ile bankacılık uygulamasına giriş yapmış ve bankacılık uygulaması, kullanıcının tarayıcısına cookie bilgisini kaydetmiştir (1-2).
Ardından, kullanıcının oturumu aktif iken yan sekmede saldırgan tarafından hazırlanan -masum görünen- bir sayfayı ziyaret ettiğini düşünelim (3).
Saldırgan tarafından hazırlanan bu sayfa da evil.com olsun. Saldırgan, evil.com’un kaynak koduna bankacılık uygulamasında para transferini tetikleyecek olan formu hazırlayıp, ekledi. Oturumu açık olan kullanıcı her şeyden habersiz bir şekilde evil.com’u ziyaret ederek saldırgan tarafından hazırlanan bu formu farkında olmadan tetikleyecektir. İstek, kullanıcının tarayıcısından çıkacağı ve tarayıcı da bankacılık uygulamasına yapılacak isteklere otomatik olarak cookie bilgisini dahil edeceği için günün sonunda yapılan istek, kullanıcının oturumunda işletilmiş olacaktır (4-5-6). Saldırgan bu durumu sömürerek kurban kullanıcı üzerinden kendi hesabına para gönderebilecektir.
CSRF zafiyeti ile kullanıcının oturumunun aktif olduğu uygulama üzerinde bilgisi dahilinde olmayan işlemler tetiklenebilir. Bu zafiyet, görüldüğü yere göre kritik etkilere sebep olabilir. Örneğin, admin yetkilerinde kullanıcı oluşturabilme veya kullanıcı bilgilerinin değiştirilebilmesi gibi...
Bir diğer örnek olarak, kurban kullanıcı vulnerable.com’a giriş yapmış ve mail adresini ‘test@test.com’ olarak değiştirme işlemi yapıyor.
Yapılan HTTP isteği aşağıdaki gibidir:
POST /email-change HTTP/1.1
Host: vulnerable.com
Cookie: session=BxM87QxxMnKkQkVm4IwbMPaejwrxT6y1
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 21
Connection: close
email=test%40test.com
Saldırgan, kendi kontrolünde olan bir sayfaya vulnerable.com üzerinde mail adresi değiştirme işlemini tetikleyecek formu hazırlayıp ekliyor.
Saldırganın kontrolünde olan sayfanın kaynak kodu:
<html>
<body>
<form action="https://vulnerable.com/email-change" method="POST">
<input type="hidden" name="email" value="hacker@hacker.com" />
</form>
<script>
document.forms[0].submit();
</script>
</body>
</html>
Formun hedefi olarak, vulnerable.com adresi email-change yolu ve input değeri olarak ‘hacker@hacker.com’ mail adresi yazılmış. Saldırgan bir şekilde hedeflediği kullanıcının oturumu aktif iken kendi hazırladığı sayfayı ziyaret etmesini sağlayabilirse, kullanıcının tarayıcısı bu isteği vulnerable.com’a yaparken cookie bilgisini de dahil edeceği için bu istek kullanıcının oturumunda işleme alınacak. Böylelikle saldırgan hedeflediği kişinin mail adresini kendi belirlediği bir mail adresi ile değiştirebilmiş olacaktır. Ardından parolamı unuttum akışı üzerinden -parola sıfırlama bağlantısı saldırgan kontrolünde olan mail adresine geleceği için- hesabı ele geçirebilir.
Şimdi de CSRF zafiyetinin nasıl çözülmesi gerektiğinden bahsedelim. Bu zafiyetin, tarayıcıların cookie bilgisini ekleme davranışından dolayı ortaya çıktığını söylemiştik. Tarayıcılar, başka bir kaynaktan tetiklenen isteklere cookie bilgisini dahil ediyor ve isteği alan uygulama sunucusu bu isteğin kendisi üzerinden mi yoksa başka bir kaynaktan mı yapıldığını kontrol etmeden işleme aldığı için zafiyet oluşuyor.
Burada, tarayıcılar neden böyle bir davranış sergiliyor, neden başka bir kaynaktan tetiklenen isteklere cookie’leri otomatik olarak ekliyor, diye sorabilirsiniz. Zafiyetin giderilmesi için tarayıcı tarafında aksiyon alınması gerekiyor, diyebilirsiniz. Bu konu için ortaya çıkan SameSite cookie’lere giriş yapmadan uygulama tarafında alınması gereken aksiyonları inceleyelim.
- İlk olarak, GET metodu üzerinden durum değişikliğine sebep olacak bir işlem yapılmaması gerekiyor.
- Sunucu tarafında, gelen isteklerin kendi üzerinden mi yoksa başka bir kaynaktan mı yapıldığını kontrol etmek için de CSRF Token kullanılması gerekiyor. Kullanıcının oturumu ile ilişkili bir CSRF token üretilerek cevapta hidden alan olarak dönülür. Ardından kullanıcının yapacağı isteklerde CSRF token bilgisi de gönderileceği için sunucu tarafında, CSRF token’ın kontrolü sağlanarak çözüm sağlanabilir. Örnek senaryomuzda saldırgan formu hazırlayıp, kullanıcının oturumu açık iken bir şekilde tetiklenmesini sağlasa da cookie bilgisi tarayıcı tarafından yine eklenecek fakat CSRF token saldırgan tarafından bilinmediği için isteği karşılayan uygulama sunucusu isteği reddedecektir.
<input type="hidden" name="csrf-token" value="CIwNZNlR4Xbis6s3Hy9aZr51JF39I8yWnWX9wX4WFoz" />
Son olarak, SameSite cookie’den bahsedelim. Tarayıcıların cookie ekleme davranışı güvenlik problemlerine yol açtığı için cookie’ler tarafında SameSite özniteliği geliştirildi. SameSite özniteliğini kullanarak tarayıcıların cookie ekleme davranışını kontrol edebiliyoruz. Bu tanımlama ile farklı bir kaynaktan tetiklenen isteklere cookie’nin hangi durumlarda eklenebileceği talimatını verebiliyoruz.
SameSite özniteliğinin 3 farklı tanımlaması bulunuyor:
- Strict
- Lax
- None
Strict olarak tanımlanması durumunda, başka bir kaynaktan yapılan hiçbir isteğe cookie bilgisi eklenmez. Strict, en katı SameSite tanımlamasıdır.
Set-Cookie: SessionId=xxxxx; SameSite=Strict
Lax olarak tanımlanması durumunda, başka bir kaynaktan yapılan bazı isteklerde cookie bilgisi isteğe eklenir. Strict’e göre daha esnek bir tanımlamadır. Başka bir kaynaktan yapılan GET + Top-Level Navigation işlemlerde, yani tarayıcı adres çubuğunda URL’in değiştiği durumlarda cookie bilgisi isteklere eklenir.
Set-Cookie: SessionId=xxxxx; SameSite=Lax
Örnek olarak, link tanımlamalarında Top-Level değişikliğe sebep olacağı için Lax tanımlaması yapıldığında cookie eklenirken,
<a href="…">
kullanılır.
Bir resim kaynağını yüklerken GET talebi yapılmasına karşın Top-Level değişikliğe sebep olmadığı için Lax tanımlaması yapıldığında cookie eklenmez.
<img src="…">
Chrome 80 versiyonu ile eğer SameSite tanımlaması yapılmaz ise cookie’ler varsayılan olarak Lax olarak değerlendirilir.
None olarak tanımlanması durumunda, SameSite özniteliğinin kullanılmak istenilmediği belirtilir. Bu durum, tarayıcıların başka bir kaynaktan yapılan isteklere cookie bilgisini ekleyeceği anlamına gelir.
Set-Cookie: SessionId=xxxxx; SameSite=None; Secure
Eğer, None olarak kullanılmak isteniyorsa tarayıcılar, Secure özniteliği ile kullanılmasını şart koşuyor.
Hangi tarayıcı sürümlerinde SameSite cookie'nin desteklendiğini incelemek için:
https://caniuse.com/?search=SameSite
Kaynaklar:
Bilgilendirici makalen için teşekkür ederim.
SameSite=Lax öz niteliğinin daha kapsamlı bir yazılımı var mı?
Yoksa sadece Set-Cookie: SessionId=xxxxx; SameSite=Lax bunu sitemize yerleştirmemiz yeterli mi?