XSS ve CSRF Savunma Stratejileri Rehberi

# Web Güvenliği: XSS ve CSRF Savunma Stratejileri XSS ve CSRF, tarayıcı ile sunucu arasındaki güven sınırını farklı yönlerden hedefleyen iki ayrı sal...

XSS ve CSRF Savunma Stratejileri Rehberi

Web Güvenliği: XSS ve CSRF Savunma Stratejileri

XSS ve CSRF, tarayıcı ile sunucu arasındaki güven sınırını farklı yönlerden hedefleyen iki ayrı saldırı sınıfıdır. XSS, kullanıcının tarayıcısında sizin siteniz adına kod çalıştırmayı; CSRF ise kullanıcının oturumunu kullanarak sizin sitenize istek göndermeyi amaçlar. Bu rehber, iki saldırıyı ayrı ayrı ele alıp her biri için savunma katmanlarını sıralı biçimde açıklar.

Önkoşul olarak HTTP istek/yanıt döngüsü, çerez (cookie) mekanizması ve temel HTML/JavaScript bilgisi varsayılmıştır. Kod örnekleri dil ve çatıdan bağımsız ilkeleri göstermek için sade tutulmuştur; belirli bir çatı sürümüne bağlı API kullanılmamıştır.

XSS Nedir, Nerede Oluşur?

Tarayıcı, sunucudan gelen HTML'i çalıştırılabilir içerik olarak yorumlar. Kullanıcı girdisi bu HTML'in içine "veri" olarak değil "kod" olarak karışırsa, saldırganın gönderdiği script kullanıcının tarayıcısında çalışır. Üç yaygın biçim vardır:

  • Yansıtılan (reflected): Girdi, aynı isteğin yanıtında yer alır (örneğin arama sonucu sayfası).
  • Depolanan (stored): Girdi veritabanına yazılır ve başka kullanıcılara gösterilir (örneğin yorum alanı).
  • DOM tabanlı: Sunucu devrede değildir; istemci tarafındaki JavaScript, güvenilmez veriyi innerHTML gibi tehlikeli bir noktaya yazar.

XSS'in etkisi, çalınan oturum çerezinden tuş kaydına ve sayfa içeriğinin değiştirilmesine kadar uzanır. Bu yüzden savunma tek bir noktaya değil, birden çok katmana yayılmalıdır.

XSS Savunması: Bağlama Göre Çıktı Kodlama

En temel kural şudur: girdiyi değil, çıktıyı bağlamına göre kodla. Aynı veri, HTML gövdesinde, HTML özniteliğinde, JavaScript dizesinde veya URL içinde farklı kurallarla kaçışlanır. Tek bir "her yerde geçerli" kaçışlama yoktur.

  • HTML gövdesi: &, <, >, ", ' karakterleri HTML varlıklarına dönüştürülür.
  • HTML özniteliği: Değer her zaman tırnak içine alınır ve tırnak karakterleri kodlanır. Tırnaksız öznitelik yazmak risklidir.
  • JavaScript bağlamı: Veri, script bloğuna doğrudan gömülmemelidir. Zorunluysa JSON olarak serileştirilip < karakteri kaçışlanmalıdır; aksi halde </script> dizisi bloğu erken kapatabilir.
  • URL bağlamı: javascript: gibi şemalar reddedilmeli, değer URL kodlamasından geçirilmelidir.

Çatıların çoğu (örneğin modern şablon motorları) HTML gövdesi için otomatik kaçışlama sunar. Bu koruma yalnızca kendi bağlamı için geçerlidir; innerHTML, dangerouslySetInnerHTML veya şablon motorundaki "ham HTML" işaretleri bu korumayı bilinçli olarak devre dışı bırakır.

Tehlikeli DOM API'lerinden Kaçınma

İstemci tarafında güvenilmez veriyi metin olarak yerleştirmek için textContent kullanın; innerHTML kullanmayın.

// Güvenli: veri metin olarak yerleştirilir, HTML olarak yorumlanmaz
element.textContent = kullaniciGirdisi;

// Riskli: girdi HTML olarak ayrıştırılır ve script çalışabilir
element.innerHTML = kullaniciGirdisi;

textContent beklenen davranışı şudur: içerik ekranda görünür ama tarayıcı onu işaretleme olarak yorumlamaz; <script> etiketi bile düz metin olarak gösterilir. Zorunlu olarak HTML üretmeniz gerekiyorsa, çıktıyı bir HTML temizleme (sanitization) kütüphanesinden geçirin ve yalnızca izin verilen etiket/öznitelik kümesini kabul edin.

Content Security Policy ile İkinci Katman

Kodlama hataları kaçınılmaz olabilir; CSP bunların etkisini sınırlar. Content-Security-Policy başlığı, tarayıcıya hangi kaynaklardan script, stil ve diğer içeriklerin yüklenebileceğini söyler.

Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'

Beklenen davranış: bu politika ile yalnızca aynı kaynaktan gelen script'ler çalışır; satır içi (inline) script'ler ve eval engellenir. Bu, kaçışlama hatasıyla sayfaya sızan bir <script> bloğunun çalışmasını büyük ölçüde durdurur.

CSP'yi devreye alırken dikkat edilecek noktalar:

  • 'unsafe-inline' ve 'unsafe-eval' eklemek korumayı büyük ölçüde boşa çıkarır.
  • Satır içi script gerekiyorsa nonce veya hash tabanlı yaklaşım tercih edilir.
  • Politika önce raporlama modunda (Content-Security-Policy-Report-Only) denenip kırılan kaynaklar gözlemlenebilir.

CSRF Nedir?

CSRF, tarayıcının çerezleri otomatik olarak göndermesine dayanır. Kullanıcı sitenizde oturum açmışken başka bir kötü niyetli sayfayı ziyaret ederse, o sayfa sizin sitenize bir istek tetikleyebilir ve tarayıcı oturum çerezini bu isteğe ekler. Sunucu, isteğin gerçekten sizin sitenizdeki bir formdan mı yoksa dışarıdan mı geldiğini ayırt edemez.

Kritik nokta şudur: CSRF, çerezi çalmaz. Kullanıcının tarayıcısını sizin adınıza kullanır. Bu yüzden CSRF savunması, "bu isteğin gerçekten bizim uygulamamızdan geldiğini" kanıtlamaya dayanır.

CSRF Savunması: Token ve SameSite

1. SameSite Çerez Özniteliği

Çerezlere SameSite özniteliği eklemek, tarayıcının çerezi çapraz site isteklerinde gönderme davranışını kısıtlar.

Set-Cookie: oturum=...; Secure; HttpOnly; SameSite=Lax
  • Strict: Çerez yalnızca aynı site kaynaklı isteklerde gönderilir.
  • Lax: Üst düzey gezinmelerde (örneğin bir bağlantıya tıklama) gönderilir, arka plandaki çapraz site isteklerinde gönderilmez.
  • None: Çapraz site kullanımına izin verir; bu durumda Secure zorunludur.

Lax, çoğu uygulama için makul bir varsayılandır. Ancak tek başına yeterli değildir; eski tarayıcılar veya özel kurgular boşluk bırakabilir. Bu yüzden token ile birlikte kullanılmalıdır.

2. Anti-CSRF Token

Sunucu, oturuma bağlı rastgele bir token üretir ve formu bu token ile birlikte gönderir. Gelen istekte token yoksa veya oturumdaki değerle eşleşmiyorsa istek reddedilir. Saldırganın sayfası bu token'ı okuyamaz, çünkü aynı kaynak politikası (same-origin policy) buna izin vermez.

Uygulama sırasında dikkat edilecek noktalar:

  • Token, oturuma bağlı ve tahmin edilemez olmalıdır (kriptografik rastgele üretim).
  • Token yalnızca gizli alan olarak değil, gerekiyorsa özel bir başlıkta da taşınabilir.
  • Durumu değiştiren tüm istekler (POST, PUT, DELETE, PATCH) korunmalıdır. GET istekleri yan etki üretmemelidir.
  • Karşılaştırma, zamanlama saldırılarına karşı sabit zamanlı yapılmalıdır.

Aşağıdaki örnek, token doğrulama mantığının ilkesini gösterir; belirli bir çatıya ait değildir:

// Sunucu tarafı: gelen token'ı oturumdaki token ile karşılaştır
function tokenGecerliMi(istekTokeni, oturumTokeni) {
  if (!istekTokeni || !oturumTokeni) return false;
  // Sabit zamanlı karşılaştırma; uzunluk farkı da erken çıkışa yol açmamalı
  return sabitZamanliKarsilastir(istekTokeni, oturumTokeni);
}

Beklenen davranış: token eksik, yanlış veya süresi geçmişse istek işlenmeden reddedilir; durum değişikliği gerçekleşmez.

Yaygın Hatalar ve Etkileri

  • Yalnızca girdiyi filtrelemek: XSS savunması çıktı bağlamında yapılmalıdır. Girdiyi "temizlemek" bağlam bilgisi olmadan güven vermez.
  • innerHTML ile kullanıcı verisi yazmak: En sık görülen DOM tabanlı XSS kaynağıdır.
  • CSP'yi unsafe-inline ile gevşetmek: Politika kâğıt üzerinde kalır.
  • CSRF token'ı yalnızca formlara koyup JSON API'leri korumasız bırakmak: Durum değiştiren her uç nokta korunmalıdır.
  • GET ile durum değiştirmek: CSRF savunmasını anlamsızlaştırır; GET yan etkisiz olmalıdır.
  • HttpOnly eklemeyi unutmak: XSS gerçekleşirse çerez JavaScript'ten okunabilir hale gelir. HttpOnly, çerezi document.cookie üzerinden erişilemez kılar.

Savunma Katmanlarını Birlikte Kullanmak

XSS ve CSRF ayrı saldırılar olsa da savunmaları birbirini tamamlar. Çerez bayrakları (HttpOnly, Secure, SameSite) ve token doğrulaması CSRF'i zorlaştırır; bağlama göre çıktı kodlama ve CSP ise XSS'in etkisini sınırlar. HttpOnly çerezi XSS'e karşı korumaz; yalnızca XSS gerçekleştiğinde oturumun çalınmasını zorlaştırır. Bu nedenle katmanları birbirinin yerine değil, birlikte düşünmek gerekir.

Özet ilkeler:

  1. Girdiyi veri olarak ele al, çıktıyı bağlamına göre kodla.
  2. Tehlikeli DOM API'lerinden kaçın; zorunluysa temizleme uygula.
  3. CSP ile kodlama hatalarının etkisini sınırla.
  4. Çerezlere HttpOnly, Secure ve uygun SameSite değerini ekle.
  5. Durum değiştiren tüm isteklerde anti-CSRF token doğrula.
  6. GET isteklerini yan etkisiz tut.

Bu katmanlar birlikte uygulandığında, tek bir hatanın tek başına oturum ele geçirmeye yol açması zorlaşır.

İLGİLİ İÇERİKLER

Bunları da Okumak İsteyebilirsiniz