aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Web Geliştirme

CSRF Nedir ve Web Formlarında Koruma Nasıl Çalışır

Bir kullanıcı sitenize giriş yapmışken, kötü niyetli başka bir sayfa onun adına sizin sunucunuza istek gönderebilir; işte CSRF nedir sorusunun özü budur. Cross-Site Request Forgery (siteler arası istek sahteciliği), tarayıcının çerezleri her isteğe otomatik eklemesinden faydalanan bir saldırıdır. Kullanıcı oturumu açık olduğu sürece, saldırgan onun yetkisini "ödünç alarak" şifre değiştirme, para transferi veya ayar güncelleme gibi durum değiştiren işlemleri tetikleyebilir. Bu yazıda saldırının nasıl çalıştığını, token mantığını ve modern framework'lerin bu savunmayı nasıl otomatikleştirdiğini somut örneklerle anlatıyorum.

Saldırı Adım Adım Nasıl İşler

Diyelim ki bir banka uygulaması para transferini şöyle bir formla yapıyor:

<form action="https://banka.com/transfer" method="POST">
  <input name="alici" value="...">
  <input name="tutar" value="...">
</form>

Kullanıcı banka sitesinde oturum açık halde bambaşka bir sayfayı ziyaret ederse, o sayfa gizli bir form barındırabilir:

<form action="https://banka.com/transfer" method="POST" id="kotu">
  <input type="hidden" name="alici" value="saldirgan">
  <input type="hidden" name="tutar" value="10000">
</form>
<script>document.getElementById('kotu').submit();</script>

Tarayıcı isteği gönderirken banka için kayıtlı oturum çerezini otomatik ekler. Sunucu açısından istek tıpatıp meşru bir kullanıcıdan gelmiş gibi görünür. Sorunun kökü şudur: sunucu, isteğin gerçekten kendi sayfasından mı yoksa yabancı bir kaynaktan mı geldiğini ayırt edemez.

Token Mantığı: Senkronizasyon Belirteci

Klasik savunma "synchronizer token pattern" denilen yöntemdir. Sunucu, her oturum için tahmin edilemez rastgele bir değer üretir, bunu hem kullanıcının oturumunda saklar hem de sayfadaki forma gizli bir alan olarak gömer:

<form method="POST" action="/transfer">
  <input type="hidden" name="_token" value="a1b2c3...rastgele">
  ...
</form>

Form gönderildiğinde sunucu, gelen _token ile oturumda sakladığı değeri karşılaştırır. Eşleşmezse istek reddedilir. Saldırganın hazırladığı yabancı sayfa bu tokenı bilemez, çünkü başka bir kaynaktaki sayfa Same-Origin Policy nedeniyle banka sayfasının içeriğini okuyamaz. Token gizli kalır, sahte istek de geçersiz olur.

Token'ın güvenli olması için şu özellikleri taşıması gerekir:

  • Tahmin edilemez: kriptografik açıdan güçlü rastgele üreteçle oluşturulmalı.
  • Oturuma veya kullanıcıya bağlı: bir kullanıcının tokenı başkasında geçerli olmamalı.
  • Yalnızca durum değiştiren isteklerde zorunlu: GET gibi okuma isteklerinin yan etkisi olmamalı zaten.

Double Submit Cookie Yöntemi

Sunucu tarafında oturum durumu tutmak istemeyen (stateless) API'ler için alternatif bir desen vardır: double submit cookie. Burada token hem bir çereze hem de istek başlığına (veya gövdesine) yazılır. Sunucu ikisinin eşit olup olmadığını kontrol eder. Yabancı bir site, JavaScript ile başka bir kaynağın çerezini okuyup başlığa kopyalayamayacağı için saldırı başarısız olur. Tek dezavantajı, alt alan adı (subdomain) güveni gibi konularda dikkatli yapılandırma gerektirmesidir.

SameSite Çerezleri: Tarayıcı Düzeyinde Savunma

Çerezlere eklenen SameSite özelliği, çerezin siteler arası isteklerde gönderilip gönderilmeyeceğini tarayıcıya söyler. Üç değer vardır:

  • SameSite=Strict: çerez yalnızca aynı siteden gelen isteklere eklenir; dış bağlantılarda bile gönderilmez.
  • SameSite=Lax: üst düzey gezinmelerdeki GET isteklerine eklenir ama siteler arası POST'larda gönderilmez. Çoğu modern tarayıcıda varsayılan budur.
  • SameSite=None; Secure: her durumda gönderilir; gerçekten siteler arası çerez gerekiyorsa kullanılır.

Lax veya Strict, CSRF'ye karşı güçlü bir katman sağlar çünkü saldırganın tetiklediği siteler arası POST isteğine oturum çerezi hiç eklenmez. Yine de SameSite tek başına yeterli sayılmaz; eski tarayıcılar ve bazı uç durumlar için token korumasını da birlikte kullanmak en sağlam yaklaşımdır. Savunmanın katmanlı olması esastır.

Framework'ler Bunu Nasıl Otomatikleştirir

Modern framework'ler token üretimini ve doğrulamasını sizin yerinize halleder. Laravel'de örneğin Blade içinde @csrf direktifi forma gizli token alanını ekler ve VerifyCsrfToken ara katmanı her POST, PUT, PATCH, DELETE isteğinde bunu otomatik doğrular:

<form method="POST" action="/profil">
  @csrf
  <input name="isim">
  <button>Kaydet</button>
</form>

JavaScript ile istek atarken (örneğin fetch), tokenı bir <meta> etiketinden okuyup başlığa eklemeniz gerekir:

const token = document.querySelector('meta[name="csrf-token"]').content;
fetch('/profil', {
  method: 'POST',
  headers: {
    'X-CSRF-TOKEN': token,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ isim: 'Aslain' })
});

Diğer ekosistemlerde de mantık aynıdır: Django'da {% csrf_token %} ve CsrfViewMiddleware, Rails'te protect_from_forgery, Express'te csurf türevi paketler aynı işi görür. Saf token olmayan, çerez tabanlı oturum kullanmayan (örneğin her istekte Authorization: Bearer başlığı taşıyan) API'ler ise CSRF'ye doğal olarak daha dayanıklıdır, çünkü tarayıcı bu başlığı otomatik eklemez.

Pratik Kontrol Listesi

  • Durum değiştiren her endpoint'i (POST/PUT/PATCH/DELETE) CSRF doğrulamasıyla koru.
  • Oturum çerezlerine SameSite=Lax (veya uygunsa Strict) ve Secure ekle.
  • Tokenı asla URL'de veya log'da sızdırma; gizli form alanı veya istek başlığı kullan.
  • GET isteklerini yan etkisiz tut; veri değiştirme için kullanma.
  • Framework'ün hazır korumasını kapatma; gerçekten gerekiyorsa yalnızca ilgili rotayı istisna et.

Sık Sorulan Sorular

CSRF ile XSS aynı şey mi?

Hayır. XSS, saldırganın sizin sayfanıza zararlı betik enjekte etmesidir ve token korumasını bile aşabilir. CSRF ise kullanıcının mevcut oturumunu dışarıdan kötüye kullanmaktır. XSS açığı varsa CSRF savunması da çökebilir, bu yüzden ikisini birlikte ele almak gerekir.

Sadece HTTPS kullanmak CSRF'yi engeller mi?

Hayır. HTTPS veriyi şifreler ve araya girmeyi (man-in-the-middle) zorlaştırır ama isteğin nereden geldiğiyle ilgilenmez. CSRF için yine token ve/veya SameSite çerezleri gerekir.

Token her istekte değişmeli mi?

Şart değil. Oturum boyunca sabit ama oturuma bağlı bir token çoğu durumda yeterlidir. Her istekte yenilenen token ekstra güvenlik sağlar ama "geri" tuşu ve çok sekmeli kullanımda sorun çıkarabilir; bu yüzden çoğu framework oturum ömrü boyunca tek token kullanır.

Formlarınızı güvenceye almak mı, mevcut bir uygulamayı denetlemek mi istiyorsunuz? CSRF, XSS ve oturum güvenliği konularında pratik çözümler üretiyorum. Benimle iletişime geçin ve projenizi birlikte sağlamlaştıralım.

Bu kategorideki tüm yazılar →

Devamı için