XSS (Siteler Arası Betik Çalıştırma) Nedir?
Kısa tanım
XSS (Cross-Site Scripting), bir web uygulamasının güvenilmeyen veriyi uygun kodlama yapmadan sayfaya yerleştirmesi sonucunda, saldırganın kontrol ettiği betiğin başka kullanıcıların tarayıcısında o sitenin yetkileriyle çalışabilmesidir. Kalıcı (stored), yansıtılan (reflected) ve DOM tabanlı olmak üzere üç ana türü vardır. Temel önlem bağlama uygun çıktı kodlamasıdır; CSP ve HttpOnly çerezler etkisini sınırlar.
Diğer adları: Cross-Site Scripting, siteler arası betik çalıştırma, stored XSS, reflected XSS, DOM XSS

Betik, sitenin kimliğiyle çalışır
XSS'i tehlikeli yapan, enjekte edilen betiğin saldırganın sitesinde değil, hedef sitenin kendi kökeninde çalışmasıdır. Tarayıcı açısından bu betik sitenin kendi koduyla aynı haklara sahiptir: sayfadaki her bilgiyi okuyabilir, kullanıcının oturumuyla istek gönderebilir, sayfaya sahte bir giriş formu yerleştirebilir, localStorage'daki token'lara ve HttpOnly olmayan çerezlere erişebilir. Sitede XSS varsa CSRF token'ları da koruma sağlamaz, çünkü betik token'ı sayfadan okuyabilir.
Üç tür, tek kök neden
| Tür | Veri nereden gelir? | Tipik yer |
|---|---|---|
| Kalıcı (stored) | Veritabanına kaydedilip sonraki ziyaretçilere gösterilen içerik | Yorumlar, profil adları, destek talepleri, ürün yorumları |
| Yansıtılan (reflected) | İstekteki bir parametrenin aynı yanıtta sayfaya geri yazılması | Arama sonuç sayfası, hata mesajları; kurbanın hazırlanmış bir bağlantıyı açması gerekir |
| DOM tabanlı | İstemci tarafı JavaScript'in URL, postMessage gibi bir kaynaktan aldığı veriyi tehlikeli bir API'ye yazması | Tek sayfa uygulamaları; sunucu hiç dahil olmayabilir |
Üçünde de ortak hata aynıdır: veri, HTML ya da JavaScript olarak yorumlanabileceği bir yere metin olarak değil kod olarak yerleştirilir. DOM tabanlı türü anlamak için tarayıcının sayfayı nasıl bir DOM ağacı olarak tuttuğunu bilmek yardımcı olur.
Güvensiz ve güvenli kalıp
// Güvensiz: kullanıcıdan gelen değer HTML olarak yorumlanır
sonucBasligi.innerHTML = "Aranan: " + aramaTerimi;
// Güvenli: değer yalnızca metin olarak eklenir
sonucBasligi.textContent = "Aranan: " + aramaTerimi;İkinci satırda arama terimi ne içerirse içersin ekranda harfi harfine görünür. Sunucu tarafında da aynı ilke geçerlidir: otomatik kaçışlama (auto-escaping) yapan bir şablon motoru kullanın ve bunu devre dışı bırakan kaçış yollarını (React'te dangerouslySetInnerHTML, Vue'da v-html gibi) yalnızca zorunlu durumlarda kullanın. Kullanıcının gerçekten HTML girmesi gereken yerlerde (zengin metin editörü gibi) çıktıyı, izin verilen etiketleri sınırlayan ve bakımı süren bir temizleme kütüphanesinden geçirin.
Kodlama bağlama göre değişir. HTML gövdesine, bir öznitelik değerine, bir JavaScript dizesine ya da bir URL'ye yazılan veri farklı kurallarla kodlanır. Bağlantılarda kullanıcıdan gelen adreslerin https: gibi beklenen bir şemayla başladığı da ayrıca doğrulanmalıdır.
Savunma katmanları
- Bağlama uygun çıktı kodlaması: Asıl çözüm budur; diğerleri etkiyi azaltır.
- Girdi doğrulama: Beklenen biçimi zorlamak yardımcı olur ama tek başına yeterli değildir.
- İçerik Güvenlik Politikası: Nonce tabanlı katı bir politika, kaçan bir açığın betik çalıştırmasını büyük ölçüde engeller.
- HttpOnly çerezler: Oturum çerezinin betikle okunmasını engeller; betiğin kullanıcı adına istek göndermesini engellemez.
OWASP'ın XSS önleme rehberi, tek bir tekniğin XSS'i çözmediğini vurgular.
Açıkları bulmak
Kod incelemesinde "sink" denen tehlikeli noktalara bakılır: innerHTML, outerHTML, document.write, eval, çerçevelerin ham HTML basan bileşenleri ve kullanıcı verisi alan olay öznitelikleri. Statik analiz araçları bu kalıpları otomatik işaretler. Rapor modunda çalışan bir CSP, üretimde beklenmedik satır içi betikleri görünür kılar. Kritik uygulamalarda düzenli sızma testleri, otomatik araçların kaçırdığı bağlamları yakalar.

