Web uygulamalarının en eski ama hâlâ en sık rastlanan güvenlik açıklarından biri XSS'tir; yani "Cross-Site Scripting" veya Türkçesiyle siteler arası betik çalıştırma. İsmi kulağa teknik gelse de temel fikri basittir: saldırgan, sizin sitenizin üzerinden başka bir kullanıcının tarayıcısında kendi JavaScript kodunu çalıştırır. Kullanıcı sizin sitenize güvendiği için, o sayfada çalışan koda da güvenir. İşte tehlike tam olarak burada başlar.

Bir e-ticaret sitesi, üyelik sistemi olan bir blog ya da müşteri paneli olan bir KOBİ yazılımı düşünün. Kullanıcıdan alınan her veri, eğer dikkatsizce ekrana basılırsa, saldırganın oturum çerezlerini çalması, sahte formlar göstermesi veya kullanıcının hesabını ele geçirmesi için bir kapı olabilir. Bu yazıda XSS'in nasıl çalıştığını, hangi türlerinin bulunduğunu ve en önemlisi geliştirici olarak buna karşı nasıl sağlam bir savunma kuracağınızı somut biçimde ele alacağız.
XSS Aslında Ne Yapar?
XSS'in kökeninde bir güven ihlali vardır. Tarayıcı, bir sayfadan gelen JavaScript kodunun o sitenin sahibi tarafından yazıldığını varsayar ve ona sayfayla ilgili geniş yetkiler verir: sayfa içeriğini okuyabilir, çerezlere erişebilir, form gönderebilir, kullanıcı adına istek atabilir. Saldırgan kendi kodunu bu güvenilir bağlama sokabilirse, artık kurbanın tarayıcısında adeta sitenin sahibiymiş gibi davranabilir.
Bu kodun yapabildikleri oldukça geniştir:
- Oturum çerezlerini çalmak: Kullanıcının giriş bilgilerini ele geçirip hesabına sızmak.
- Sahte arayüz göstermek: Sayfaya sahte bir giriş formu ekleyip şifre veya kart bilgisi toplamak.
- Kullanıcı adına işlem yapmak: Sipariş vermek, ayar değiştirmek, para transferi başlatmak.
- Zararlı yönlendirme: Kullanıcıyı oltalama (phishing) sayfasına taşımak veya zararlı yazılım indirtmek.
XSS'in en sinsi yanı, kullanıcının hiçbir hata yapmamış olmasıdır. Kurban sadece güvendiği bir siteyi ziyaret eder; kötü kod zaten o sayfanın içindedir.
XSS Türleri: Üç Ana Kategori
XSS açıkları, kötü amaçlı kodun sayfaya nasıl ulaştığına göre üç ana grupta incelenir. Doğru savunma stratejisini kurmak için farkı bilmek önemlidir.
1. Depolanmış (Stored / Persistent) XSS
En tehlikeli türdür. Saldırganın gönderdiği zararlı kod, sitenin veritabanına kaydedilir ve daha sonra o içeriği gören her kullanıcıya servis edilir. Örneğin bir ürün yorumu, forum mesajı veya profil açıklaması alanına script yerleştirilir. Bu alanı görüntüleyen her ziyaretçi otomatik olarak saldırıya maruz kalır. Tek bir zararlı yorum, binlerce kullanıcıyı etkileyebilir.
2. Yansıtılmış (Reflected) XSS
Bu türde zararlı kod kalıcı olarak saklanmaz; genellikle bir URL parametresi veya form girdisi aracılığıyla anlık olarak sayfaya yansıtılır. Saldırgan, içine zararlı kod gömülmüş özel bir bağlantı hazırlar ve bunu e-posta ya da mesajla kurbana gönderir. Kurban linke tıkladığında kod onun tarayıcısında çalışır. Bu yüzden yansıtılmış XSS çoğunlukla hedefli oltalama saldırılarıyla birlikte kullanılır.
3. DOM Tabanlı XSS
Modern tek sayfa uygulamalarının (SPA) yaygınlaşmasıyla önem kazanmıştır. Burada açık sunucu tarafında değil, tamamen tarayıcıdaki JavaScript kodunun DOM'u güvensiz biçimde işlemesinden kaynaklanır. Örneğin URL'deki bir değeri doğrudan innerHTML ile sayfaya yazan bir kod, DOM tabanlı XSS'e açıktır. Sunucu logları bu saldırıyı çoğu zaman hiç görmez, bu da tespiti zorlaştırır.
Somut Bir Senaryo
Bir yerel KOBİ'nin kurumsal sitesinde iletişim formu olduğunu düşünelim. Ziyaretçiden "ad" alanı alınıp yönetici panelinde gösteriliyor. Eğer bu alan güvenli işlenmezse, saldırgan ad kısmına bir script yerleştirebilir. Yönetici paneli açtığında kod yöneticinin tarayıcısında çalışır ve yöneticinin oturumunu çalabilir. Böylece dışarıdan kimlik doğrulaması gerektiren bir panel, hiç şifre bilmeden ele geçirilir. Bu senaryo, KVKK kapsamında ciddi bir veri ihlali anlamına gelir ve hem itibar hem de yasal sorumluluk doğurur.
XSS'e Karşı Temel Savunma İlkeleri
İyi haber şu: XSS, doğru alışkanlıklarla neredeyse tamamen önlenebilir bir açıktır. Savunma birkaç katmanda kurulur ve her katman ayrı bir güvenlik ağı sağlar.
Çıktı Kodlaması (Output Encoding)
En temel ve en etkili savunmadır. Kullanıcıdan gelen hiçbir veri, ekrana basılmadan önce yorumlanabilir HTML olarak bırakılmamalıdır. Veriyi gösterdiğiniz bağlama göre kodlarsınız:
- HTML gövdesinde: <, >, & gibi karakterleri HTML varlıklarına çevirin.
- HTML özniteliği içinde: Tırnak işaretlerini ve özel karakterleri kaçış (escape) yapın.
- JavaScript bağlamında: Veriyi asla doğrudan koda gömmeyin; güvenli serileştirme kullanın.
- URL bağlamında: Parametreleri URL kodlamasından geçirin.
PHP tarafında en pratik yöntem, kullanıcı verisini ekrana basarken htmlspecialchars() fonksiyonunu doğru karakter setiyle kullanmaktır. Bu tek alışkanlık bile depolanmış ve yansıtılmış XSS'in büyük kısmını engeller.
Giriş Doğrulama (Input Validation)
Çıktı kodlaması kadar güçlü olmasa da tamamlayıcı bir katmandır. Bir alandan yalnızca belirli türde veri bekliyorsanız (örneğin telefon numarası, e-posta, sayı) bunu sunucu tarafında sıkı biçimde doğrulayın. Beyaz liste yaklaşımı — "yalnızca izin verilenleri kabul et" — kara listeden çok daha güvenlidir.
İçerik Güvenlik Politikası (CSP)
Content Security Policy, tarayıcıya hangi kaynaklardan script çalıştırabileceğini söyleyen bir HTTP başlığıdır. İyi yapılandırılmış bir CSP, saldırgan bir şekilde sayfaya kod enjekte etse bile o kodun çalışmasını engelleyebilir. Örneğin satır içi (inline) script'leri yasaklayan bir politika, birçok XSS denemesini işe yaramaz hale getirir. CSP tek başına yeterli değildir ama son derece değerli bir savunma katmanıdır.
HttpOnly ve Secure Çerezler
Oturum çerezlerini HttpOnly bayrağıyla işaretlerseniz, JavaScript bu çerezlere erişemez. Böylece bir XSS açığı olsa bile saldırgan oturum çerezini document.cookie üzerinden çalamaz. Secure bayrağı ise çerezin yalnızca HTTPS üzerinden gönderilmesini garanti eder. Bu iki ayar, XSS'in en yıkıcı sonucu olan oturum çalınmasını ciddi ölçüde zorlaştırır.

Modern Framework'ler ve Otomatik Koruma
Bugün kullanılan çoğu modern şablon motoru ve framework, çıktıyı varsayılan olarak otomatik kaçışlar. Örneğin birçok şablon dilinde bir değişkeni ekrana bastığınızda HTML kaçışı otomatik uygulanır. Ancak bu güvenliği bozan tek şey geliştiricinin "ham HTML basma" seçeneğini bilinçsizce kullanmasıdır. Bir değeri ham olarak basmadan önce her zaman kendinize şunu sorun: "Bu içerik kullanıcıdan mı geliyor, geliyorsa gerçekten güveniyor muyum?"
Güvenlik açıklarının çoğu bilgisizlikten değil, "bu sefer sorun olmaz" varsayımından doğar. XSS'te de en tehlikeli cümle "kullanıcı buraya kötü bir şey yazmaz" cümlesidir.
XSS'e Karşı Kontrol Listesi
- Ekrana basılan tüm kullanıcı verisi bağlama uygun şekilde kodlanıyor mu?
- Şablon motorunun otomatik kaçış özelliği kapalı bırakılan yerler denetlendi mi?
- Oturum çerezleri HttpOnly ve Secure bayraklarıyla korunuyor mu?
- Bir Content Security Policy başlığı tanımlandı mı ve satır içi script'ler kısıtlandı mı?
- Kullanıcı girdileri sunucu tarafında beyaz liste yaklaşımıyla doğrulanıyor mu?
- Yorum, profil ve mesaj gibi kalıcı alanlar depolanmış XSS'e karşı test edildi mi?
- Zengin metin (rich text) girişleri güvenilir bir HTML temizleme (sanitization) kütüphanesinden geçiriliyor mu?
Sık Sorulan Sorular
Sadece giriş doğrulaması yapsam yeterli olur mu? Hayır. Giriş doğrulaması yararlıdır ama tek başına yetmez. Asıl güvenlik çıktı kodlamasından gelir; çünkü aynı veri farklı bağlamlarda (HTML, JS, URL) farklı tehlikeler taşır. İkisini birlikte kullanmalısınız.
HTTPS kullanıyorum, XSS'e karşı korunuyor muyum? Hayır. HTTPS verinin yolda şifrelenmesini sağlar ama XSS uygulamanın kendi içindeki bir açıktır. Şifreli bir kanal üzerinden de XSS kodu rahatlıkla iletilebilir. İkisi tamamen farklı sorunlardır.
Zengin metin editörü kullanan bir alanda ne yapmalıyım? Kullanıcının HTML girmesine izin veren alanlarda basit kaçış yeterli olmaz; içeriği güvenilir bir sanitization kütüphanesiyle temizlemeniz gerekir. Bu kütüphaneler yalnızca izin verilen etiketleri bırakıp script gibi tehlikeli öğeleri temizler.
Sonuç
XSS, ne kadar eski olursa olsun, hâlâ web uygulamalarını tehdit eden en yaygın açıklardan biridir. Ama aynı zamanda en iyi anlaşılmış ve en kolay önlenebilir açıklardandır. Çıktı kodlaması, akıllı bir içerik güvenlik politikası, HttpOnly çerezler ve güvenilir sanitization kütüphaneleri bir araya geldiğinde, uygulamanızı bu tehdide karşı büyük ölçüde bağışık hale getirir. Önemli olan güvenliği en baştan bir alışkanlık haline getirmektir; sonradan yamalamak her zaman daha pahalıdır.
Uygulamanızın XSS ve benzeri açıklara karşı ne kadar dayanıklı olduğundan emin değilseniz, güvenlik odaklı bir kod incelemesi ve sıkılaştırma çalışması için projenizi konuşalım. Doğru önlemleri baştan kurmak, hem müşteri verinizi hem de markanızın itibarını korur.
Bir sonraki projeniz için hazır mısınız?
Okuduklarınızı işinize uygulamak veya dijital dönüşümünüzü konuşmak isterseniz, ekibimiz bir mesaj uzağınızda.

Yorum Yap