Web Uygulama Güvenliği

XSS Güvenliği

Cross-Site Scripting açıklarını güvenli laboratuvar örnekleriyle anlayın; çıktı kodlama, güvenli DOM kullanımı ve Content Security Policy ile uygulamanızı koruyun.

17 Temmuz 202620 dk okumaBaşlangıç–Orta Seviye

1. XSS Nedir?

Cross-Site Scripting (XSS), kullanıcı tarafından sağlanan verinin güvenli biçimde işlenmeden HTML veya JavaScript bağlamına yerleştirilmesi sonucu oluşan web uygulaması güvenlik açığıdır.

XSS açığı, tarayıcının güvenilmeyen içeriği sayfanın bir parçası olarak çalıştırmasına neden olabilir.

Güvenli kullanım

Testleri yalnızca size ait uygulamalarda veya açıkça izin verilmiş laboratuvarlarda gerçekleştirin.

2. XSS Açığının Olası Etkileri

  • Sayfa içeriğinin değiştirilmesi
  • Kullanıcıya sahte mesaj gösterilmesi
  • Yetkisiz tarayıcı işlemleri
  • Hassas verilerin DOM üzerinden okunması
  • Oturum güvenliğinin zayıflaması
  • Kullanıcının başka sayfalara yönlendirilmesi
  • Uygulamanın itibar kaybetmesi

Gerçek etki, uygulamanın yapısına ve tarayıcı güvenlik kontrollerine göre değişir.

3. XSS Türleri

Tür Açıklama
Reflected XSS Girdi, isteğin cevabında doğrudan sayfaya yansıtılır.
Stored XSS Zararlı içerik veritabanı veya başka bir kalıcı alanda saklanır.
DOM-Based XSS Açık, tarayıcı tarafındaki JavaScript kodunun DOM’u güvensiz değiştirmesinden kaynaklanır.

4. Reflected XSS

Reflected XSS, URL parametresi veya form girdisinin doğrulanmadan ve kodlanmadan HTTP cevabına eklenmesiyle oluşur.

Güvensiz örnek:

php
<?php
echo "Arama sonucu: " . $_GET["q"];
?>

Bu yapı, kullanıcı girdisini doğrudan HTML içine yerleştirir.

5. Stored XSS

Stored XSS, kullanıcı girdisinin yorum, profil, mesaj veya destek kaydı gibi alanlarda saklanıp daha sonra diğer kullanıcılara gösterilmesiyle oluşabilir.

Saklanan veri güvenli olsa bile ekrana basılırken bulunduğu bağlama göre kodlanmalıdır.

Önemli ilke

Girdi doğrulama tek başına yeterli değildir; çıktı her zaman bağlama uygun biçimde kodlanmalıdır.

6. DOM-Based XSS

DOM-Based XSS, istemci tarafındaki JavaScript kodunun URL, hash veya kullanıcı girdisini güvensiz bir DOM hedefinde kullanmasıyla oluşur.

Güvensiz örnek:

javascript
const value = location.hash.substring(1);
document.getElementById("output").innerHTML = value;

innerHTML yerine metin gösterimi için textContent tercih edilmelidir.

7. Zararsız Laboratuvar Testi

Yalnızca kendi laboratuvar sayfanızda, kodun çalışıp çalışmadığını görmek için zararsız bir görsel mesaj kullanılabilir.

zararsız test girdisi
<strong>XSS_TEST</strong>

Bu örnek JavaScript çalıştırmaz; uygulamanın HTML etiketlerini metin olarak mı yoksa HTML olarak mı işlediğini anlamaya yardımcı olur.

Kapsam dışı testler

Çerez okuma, oturum ele geçirme, yönlendirme veya gerçek kullanıcıları hedefleyen payload’lar kullanılmamalıdır.

8. Güvensiz HTML Kullanımı

Aşağıdaki DOM özellikleri ve fonksiyonları güvenilmeyen veriyle kullanıldığında risk oluşturabilir:

  • innerHTML
  • outerHTML
  • insertAdjacentHTML()
  • document.write()
  • Güvensiz string tabanlı şablonlar

9. Güvenli DOM Kullanımı

Metin göstermek için güvenli yaklaşım:

javascript
const value = location.hash.substring(1);
document.getElementById("output").textContent = value;

Yeni element oluşturmak için:

javascript
const paragraph = document.createElement("p");
paragraph.textContent = userInput;
document.body.appendChild(paragraph);

10. HTML Çıktı Kodlama

HTML metin bağlamında aşağıdaki karakterler özel anlam taşır:

Karakter Kodlanmış karşılık
& &amp;
< &lt;
> &gt;
" &quot;
' &#39;

Modern frameworklerin otomatik çıktı kodlama özelliği devre dışı bırakılmamalıdır.

11. PHP ile Güvenli Çıktı

PHP’de HTML metin bağlamı için:

php
<?php
$query = $_GET["q"] ?? "";
echo htmlspecialchars(
    $query,
    ENT_QUOTES | ENT_SUBSTITUTE,
    "UTF-8"
);
?>

Çıktı kodlama işlemi verinin yerleştirildiği bağlama uygun olmalıdır.

12. Node.js ve Şablon Motorları

Şablon motorlarının varsayılan otomatik kodlama özelliği kullanılmalıdır.

Örneğin EJS içinde güvenli metin çıktısı:

ejs
<%= userInput %>

Ham HTML çıktısı veren yapılar yalnızca güvenilir ve temizlenmiş içerikle kullanılmalıdır.

13. React ve Benzeri Frameworkler

React, değerleri JSX içinde varsayılan olarak kodlar:

jsx
function Message({ userInput }) {
  return <p>{userInput}</p>;
}

dangerouslySetInnerHTML yalnızca zorunlu ve güvenli şekilde temizlenmiş içerik için kullanılmalıdır.

14. HTML Sanitization

Uygulama kullanıcıların sınırlı HTML girmesine izin veriyorsa yalnızca çıktı kodlama yeterli olmayabilir. İzin verilen etiket ve özellik listesine dayalı bir sanitization kütüphanesi kullanılmalıdır.

  • Güvenilir ve güncel kütüphane kullanın.
  • İzin verilen etiketleri en aza indirin.
  • Olay işleyici özelliklerini engelleyin.
  • Tehlikeli URL şemalarını reddedin.
  • Sanitize edilmiş içeriği sonradan yeniden birleştirmeyin.

15. Content Security Policy

Content Security Policy (CSP), tarayıcının hangi kaynaklardan betik ve içerik yükleyebileceğini sınırlar.

Başlangıç için örnek bir politika:

http header
Content-Security-Policy:
default-src 'self';
script-src 'self';
object-src 'none';
base-uri 'self';
frame-ancestors 'none';

Politika önce raporlama modunda test edilmeli, ardından uygulamaya uygun şekilde sıkılaştırılmalıdır.

17. Girdi Doğrulama

Girdi doğrulama, beklenen veri tipini ve biçimini sınırlar.

  • Yaş alanında yalnızca sayı kabul etmek
  • Kullanıcı adında izin verilen karakterleri sınırlamak
  • Uzunluk sınırı belirlemek
  • URL alanlarında izin verilen protokolleri kontrol etmek
  • Sunucu tarafında doğrulama yapmak

Doğrulama, çıktı kodlamanın yerine geçmez; iki kontrol birlikte kullanılmalıdır.

18. Güvenli Test Yaklaşımı

  1. Test ortamının size ait olduğunu doğrulayın.
  2. Snapshot veya yedek alın.
  3. Zararsız metin ve HTML girdileriyle başlayın.
  4. Uygulamanın çıktıyı hangi bağlamda oluşturduğunu belirleyin.
  5. Tarayıcı geliştirici araçlarında DOM’u inceleyin.
  6. Düzeltmeyi uygulayın.
  7. Aynı testi tekrar çalıştırın.
  8. Sonuçları dokümante edin.

19. Geliştirici Kontrol Listesi

  • Kullanıcı girdisini doğrudan HTML içine eklemeyin.
  • Bağlama uygun çıktı kodlama uygulayın.
  • innerHTML yerine güvenli DOM API’lerini kullanın.
  • Frameworkün otomatik kodlamasını kapatmayın.
  • HTML gerekiyorsa güvenilir sanitization uygulayın.
  • CSP yapılandırın.
  • Çerezlerde HttpOnly, Secure ve SameSite kullanın.
  • Bağımlılıkları güncel tutun.
  • Güvenlik testlerini CI/CD sürecine ekleyin.

20. Yaygın Savunma Hataları

Yalnızca kara liste kullanmak

Belirli kelime veya etiketleri engellemek kolayca yetersiz kalabilir. İzin listesi ve bağlama uygun kodlama tercih edilmelidir.

Yalnızca istemci tarafında doğrulama yapmak

Tarayıcı tarafındaki kontroller değiştirilebilir. Sunucu tarafı doğrulaması zorunludur.

CSP’yi tek savunma olarak görmek

CSP ek bir güvenlik katmanıdır; temel XSS açığını ortadan kaldırmaz.

Tüm bağlamlarda aynı kodlamayı kullanmak

HTML, özellik, URL, CSS ve JavaScript bağlamları farklı kodlama kuralları gerektirir.

21. Hızlı Savunma Özeti

Risk Önerilen savunma
HTML içine kullanıcı girdisi HTML çıktı kodlama
DOM güncelleme textContent ve güvenli DOM API’leri
Kullanıcının HTML girmesi İzin listeli sanitization
Betik kaynakları Sıkı CSP
Oturum çerezleri HttpOnly, Secure, SameSite
Girdi biçimi Sunucu tarafı doğrulama

22. Sonuç

Bu dokümanda Reflected, Stored ve DOM-Based XSS türleri; güvenli DOM kullanımı, çıktı kodlama, sanitization, CSP ve çerez güvenliği ele alındı.

XSS’e karşı en etkili yaklaşım, kullanıcı girdisini güvenilmeyen veri olarak kabul etmek ve veriyi kullanıldığı bağlama uygun şekilde kodlamaktır.

© 2026 Kemal Tokmak — Gerçek Deneyimler, Gerçek Dokümantasyon