HG PHP GüvenliğiEl Kitabı
Bölümler 07 / 38

İçindekiler/Enjeksiyon Sınıfı Açıklar

Bölüm 07

Cross-Site Scripting (XSS)

14 dk okuma2.821 kelimePHP 8.1+
Ön koşul

Bölüm 4 (beyaz/kara liste) ve özellikle Bölüm 5 (bağlamsal çıktı kodlama). Bu bölüm, Bölüm 5'te kurulan kodlama teorisinin açık tarafını inceler.

Bu bölümün kazanımı

XSS'i tek bir açık değil, üç farklı mekanizmaya (reflected, stored, DOM) sahip bir sınıf olarak kavrayacak; "kullanıcının tarayıcısında saldırganın kodunu çalıştırmak" hedefinin neden bu kadar yıkıcı olduğunu ve katmanlı savunmanın (kodlama + CSP + sanitization) nasıl kurulduğunu göreceksiniz.

1. Giriş

Cross-Site Scripting, adının çağrıştırdığından çok daha temel bir sorundur. İsim ("siteler arası betik çalıştırma") tarihseldir ve yanıltıcıdır; günümüzdeki özü şudur: saldırgan, bir kurbanın tarayıcısında, güvenilir bir sitenin bağlamında kendi JavaScript kodunu çalıştırır. Kod kurbanın oturumunda çalıştığı için, kurbanın site üzerinde yapabildiği her şeyi saldırgan da yapabilir hâle gelir.

XSS, web'in en eski ve en inatçı açık sınıfıdır. OWASP listelerinde onlarca yıldır yer alır; bug bounty programlarında bildirilen açıkların büyük çoğunluğunu oluşturur. İnatçılığının nedeni, web'in temel mimarisinde yatar: HTML, veri ile kodu (script) aynı belgede iç içe taşır. Bu, tam olarak SQL Injection'daki (Bölüm 6) "kod ile veri karışması" probleminin tarayıcıdaki kardeşidir.

XSS'in etkisi hafife alınır. "Sadece bir alert(1) kutusu" diye küçümsenen açık, gerçekte oturum çalma, hesap ele geçirme, tuş kaydı, sahte arayüz gösterimi ve — 2005'teki Samy solucanının kanıtladığı gibi — kendini çoğaltan, bir platformu saatler içinde diz çöktüren worm'lara kadar tırmanabilir.


2. Temel Teori

XSS'in kök nedeni Bölüm 5'te açıklanan bağlam sorununun ta kendisidir: güvenilmeyen veri, bir tarayıcı ayrıştırıcısının onu kod/işaretleme olarak yorumlayacağı bir bağlama, doğru kodlanmadan yerleştirilir.

Tarayıcı bir HTML belgesini işlerken içinde <script> bloğu, event handler (onclick, onerror), javascript: şeması gibi çalıştırılabilir öğeler arar. Eğer saldırganın verisi, tarayıcının bu öğelerden biri olarak ayrıştıracağı biçimde belgeye girerse, saldırganın kodu çalışır. Kritik nokta, çalışmanın kurbanın oturumu ve kaynak (origin) bağlamında gerçekleşmesidir. Same-Origin Policy, bu kodu "sitenin kendi kodu" sayar; dolayısıyla kod, kurbanın çerezlerine, DOM'una, localStorage'ına ve site adına yapılabilecek her isteğe erişir.

XSS üç mekanizmaya ayrılır:

Reflected (Yansıyan) XSS. Saldırganın verisi bir istekle gönderilir (örn. arama parametresi) ve aynı yanıtta kodlanmadan geri yansıtılır. Kurbanın, saldırganın hazırladığı bir bağlantıya tıklaması gerekir. Kalıcı değildir; tek isteklik.

Stored (Depolanmış) XSS. Saldırganın verisi sunucuda saklanır (yorum, profil, mesaj) ve daha sonra o içeriği gören her kullanıcıya kodlanmadan sunulur. Kurbanın özel bir bağlantıya tıklaması gerekmez; sadece etkilenen sayfayı görmesi yeterlidir. En tehlikeli türdür çünkü çok sayıda kurbana ulaşır ve worm'a dönüşebilir (Samy).

DOM-based XSS. Açık, sunucuda değil, tarayıcıdaki JavaScript'te oluşur. İstemci tarafı kod, güvenilmeyen bir kaynaktan (location.hash, document.referrer) veri alıp onu tehlikeli bir sink'e (innerHTML, eval, document.write) kodlamadan yazar. Sunucu yanıtı hiç değişmese bile açık vardır; bu yüzden sunucu-tarafı kodlama tek başına DOM XSS'i çözmez.

Sink ve source kavramı (DOM XSS için): Source, güvenilmeyen verinin girdiği yer (location.search, postMessage); sink, verinin kod olarak yorumlandığı yer (element.innerHTML, eval, setTimeout(string)). DOM XSS, bir source'tan bir sink'e giden, sanitize edilmemiş bir yoldur.


3. Mimarisel Bakış

Üç türün veri akışı belirgin biçimde farklıdır:

 REFLECTED:
   Saldırgan → kurbana kötü link → Kurban tıklar
        → İstek (param) → Sunucu → aynı yanıtta kodsuz yansır
        → Kurbanın tarayıcısında çalışır   (tek isteklik)

 STORED:
   Saldırgan → içerik gönderir → Sunucu DEPOLAR (DB)
        → ... daha sonra ...
   Kurban(lar) → sayfayı görüntüler → depolanan içerik kodsuz sunulur
        → HER görüntüleyende çalışır   (kalıcı, geniş etki, worm potansiyeli)

 DOM-BASED:
   Kurban → sayfayı açar
        → istemci JS: source (location.hash) → sink (innerHTML)  kodsuz
        → sunucu yanıtı DEĞİŞMESE BİLE tarayıcıda çalışır

Güven sınırı üçünde de aynı yerdedir: veri, tarayıcı ayrıştırıcısına (HTML/JS) ulaştığı an. Fark, o veriye kimin ve ne zaman dokunduğudur — ve bu fark, savunmanın nereye konacağını belirler.


4. Güvensiz Kod

Gerçekçi bir yorum (comment) özelliği — stored XSS için klasik zemin:

<?php
// ⚠️ GÜVENSİZ — yorum kaydetme ve listeleme
declare(strict_types=1);

// Kaydetme
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $pdo->prepare('INSERT INTO comments (post_id, author, body) VALUES (?, ?, ?)')
        ->execute([(int)$_POST['post_id'], $_POST['author'], $_POST['body']]);
}

// Listeleme
$comments = $pdo->query('SELECT author, body FROM comments ORDER BY id DESC')
                ->fetchAll(PDO::FETCH_ASSOC);
?>
<h2>Yorumlar</h2>
<?php foreach ($comments as $c): ?>
  <div class="comment">
    <strong><?= $c['author'] ?></strong>
    <p><?= $c['body'] ?></p>
  </div>
<?php endforeach; ?>

<!-- Reflected zemin: arama kutusu -->
<p>Arama sonuçları: "<?= $_GET['q'] ?? '' ?>"</p>

Ve bir DOM-based zemin (istemci tarafı):

<!-- ⚠️ GÜVENSİZ — DOM XSS -->
<div id="welcome"></div>
<script>
  // location.hash → innerHTML (source → sink), kodlama yok
  document.getElementById('welcome').innerHTML =
      'Hoş geldin, ' + decodeURIComponent(location.hash.slice(1));
</script>

5. Açığın Analizi

<?= $c['body'] ?> (yorum listeleme) — Stored XSS. body, kullanıcıdan gelir, veritabanına ham yazılır (bu doğrudur; Bölüm 5, depoda değil çıktıda kodla) ama çıktıda da kodlanmaz. Bir kullanıcı body içine bir script/işaretleme koyarsa, yorumu gören her ziyaretçinin tarayıcısında çalışır. SQL tarafı parametreli (güvenli) olduğuna dikkat edin — bu, "SQLi'yi çözdüm ama XSS açığım hâlâ var" durumunun tipik örneğidir. İki açık bağımsızdır.

<?= $_GET['q'] ?> (arama) — Reflected XSS. Sorgu parametresi aynı yanıtta HTML gövde bağlamına kodsuz yansıtılıyor. Saldırgan, bu parametreyi taşıyan bir bağlantı hazırlayıp kurbana yollar.

innerHTML = ... location.hash ... (istemci) — DOM-based XSS. location.hash bir source, innerHTML bir sink. Arada kodlama yok. Sunucu bu HTML'i değiştirmese bile, tarayıcıda # sonrası yerleştirilen işaretleme çalışır. Sunucu-tarafı htmlspecialchars burada işe yaramaz çünkü açık sunucuda değil.

Kök sorun üçünde de aynı: veri, tarayıcı ayrıştırıcısının kod sanacağı bir bağlama, o bağlama uygun kodlama olmadan giriyor (Bölüm 5).


6. Hacker Bakış Açısı

Saldırgan XSS'i nasıl keşfeder?

Yansıma noktalarını arar. Girdiği bir değeri (benzersiz bir işaret, örn. xss7391) sayfada geri görüyorsa, o değerin hangi bağlamda yansıdığını inceler: HTML gövde mi, öznitelik mi, script içi mi, bir JS değişkeni mi? Bölüm 5'teki bağlam matrisi, saldırganın da zihin haritasıdır.

Bağlamdan çıkış dener. İşaretinin yanına bağlama uygun bir "kırıcı" karakter gönderir: gövdede <, öznitelikte ", script'te ' veya </script>. Uygulamanın bunları kodlayıp kodlamadığını gözlemler. Kodlanmıyorsa açık doğrulanır.

Kodlama/filtre kalitesini yoklar. Uygulama bir kara liste filtresi uyguladıysa (Bölüm 4), saldırgan onu atlatmayı dener: büyük/küçük harf karışımı, alternatif event handler'lar, kodlanmış varyantlar, nadir HTML sözdizimi. Bu, tam olarak Samy'nin MySpace filtresini aştığı yöntemdir (Bölüm 11).

DOM XSS için istemci kodunu okur. Sayfanın JavaScript'ini inceleyip source→sink yollarını arar; innerHTML, eval, document.write gibi sink'lere giden güvenilmeyen veri akışlarını izler.

Etkiyi düşünür. Bir XSS bulan saldırgan "ne yapabilirim?" diye sorar: oturum çerezini çalabilir mi (çerezde HttpOnly var mı?), site adına istek atabilir mi (CSRF token'ı okuyabilir mi?), sahte bir giriş formu gösterebilir mi? Bu, açığın CVSS etkisini belirler.

Savunmacı dersi: Saldırgan bağlam ve etki düşünür. Savunma, her çıktı bağlamını kapatmalı (kodlama) ve bir açık kaçsa bile etkisini sınırlamalıdır (HttpOnly, CSP).


7. Exploit Mantığı

Bu bölüm silahlaştırılmış worm/hırsız kodu içermez. Amaç, XSS'in neden bu kadar güçlü bir ilkel (primitive) olduğunu kavratmaktır.

Bir XSS elde eden saldırgan, kurbanın kaynağında (origin) keyfi JavaScript çalıştırma yeteneği kazanır. Bunun neden yıkıcı olduğu, JavaScript'in o bağlamda yapabildiklerinden gelir:

  • Oturum devralma: Çerez HttpOnly değilse document.cookie okunabilir; olsa bile saldırgan, kurbanın tarayıcısını proxy gibi kullanıp site adına yetkili istekler atabilir. Yani çerezi çalmasa da kurban adına işlem yapar.
  • CSRF korumasını atlatma: XSS, sayfadaki anti-CSRF token'ını okuyabildiği için, token tabanlı CSRF savunmalarını etkisiz kılar (Bölüm 17). Bu yüzden XSS "CSRF'in üstünde" bir açıktır.
  • Kalıcılık ve yayılma: Stored XSS'te kod her görüntülemede çalışır. Kod, kendini başka kayıtlara da yazacak biçimde tasarlanırsa (Samy'de olduğu gibi) kendini çoğaltan bir worm olur — kurban sayısı üstel büyür.
  • Arayüz sahteciliği: Kod, sayfaya sahte bir giriş/ödeme formu ekleyip kimlik bilgisi toplayabilir (kurban gerçek sitede olduğu için güvenir).

Araştırmacının çerçevesi üç eksenlidir: (a) hangi tür XSS (reflected/stored/DOM) ve hangi bağlam; (b) hangi savunma eksik (kodlama? filtre atlatılabiliyor mu? CSP var mı?); (c) etki nereye tırmanıyor (çerez, CSRF token, worm). Savunma da bu üç ekseni kapatarak kurulur.


8. Güvenli Kod

Üç türü de kapatan güvenli sürüm:

<?php
// ✅ GÜVENLİ — bağlamsal kodlama (Bölüm 5) + katmanlı savunma
declare(strict_types=1);

function h(string $s): string {
    return htmlspecialchars($s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}

$comments = $pdo->query('SELECT author, body FROM comments ORDER BY id DESC')
                ->fetchAll(PDO::FETCH_ASSOC);
?>
<h2>Yorumlar</h2>
<?php foreach ($comments as $c): ?>
  <div class="comment">
    <strong><?= h($c['author']) ?></strong>
    <p><?= nl2br(h($c['body'])) ?></p>   <!-- stored XSS kapatıldı -->
  </div>
<?php endforeach; ?>

<p>Arama sonuçları: "<?= h($_GET['q'] ?? '') ?>"</p>   <!-- reflected kapatıldı -->

DOM tarafı — tehlikeli sink yerine güvenli API:

<!-- ✅ GÜVENLİ — innerHTML yerine textContent -->
<div id="welcome"></div>
<script>
  // Kullanıcı verisi kod olarak DEĞİL, düz metin olarak yerleşir
  document.getElementById('welcome').textContent =
      'Hoş geldin, ' + decodeURIComponent(location.hash.slice(1));
</script>

Zengin metin (kullanıcının gerçekten HTML girmesine izin verilen durum — yorum editörleri, wiki) için elle kodlama yetmez; sağlam bir sanitizer gerekir:

// ✅ Zengin metin için: beyaz-listeli HTML sanitizer
$config = HTMLPurifier_Config::createDefault();
$config->set('HTML.Allowed', 'p,b,i,strong,em,a[href],ul,ol,li,br');
$config->set('URI.AllowedSchemes', ['http' => true, 'https' => true, 'mailto' => true]);
$clean = (new HTMLPurifier($config))->purify($_POST['body']);

Modern PHP/tarayıcı kalıpları: - HTML çıktı: htmlspecialchars(ENT_QUOTES, 'UTF-8') (Bölüm 5); auto-escaping şablonu (Twig/Blade) tercih edilir. - DOM: innerHTML/document.write/eval yerine textContent, setAttribute gibi güvenli API'ler. Framework kullanılıyorsa (React/Vue) varsayılan çıktı zaten kodlanır; kaçış kapıları (dangerouslySetInnerHTML, v-html) denetlenir. - Zengin metin: HTML Purifier gibi beyaz-listeli sanitizer. - Katman: HttpOnly+Secure çerezler ve sıkı CSP (Bölüm 9).


9. Katmanlı Savunma: Content Security Policy (CSP)

Kodlama ilk savunmadır ama insan hata yapar; tek bir kaçmış çıktı yeterlidir. CSP, bir kodlama hatası kodu içeri soksa bile onun çalışmasını engelleyen ikinci katmandır (derinlemesine savunma, Bölüm 1).

CSP, bir HTTP başlığıyla tarayıcıya "script yalnızca şu kaynaklardan çalışsın, satır içi (inline) script çalışmasın" der. Güçlü bir modern CSP, satır içi script'i yasaklayıp yalnızca nonce ya da hash ile işaretlenmiş script'lere izin verir:

// Her istekte rastgele bir nonce üret
$nonce = base64_encode(random_bytes(16));
header("Content-Security-Policy: default-src 'self'; " .
       "script-src 'self' 'nonce-$nonce'; object-src 'none'; base-uri 'none'");
<script nonce="<?= $nonce ?>"> /* meşru script */ </script>

Bu politikada saldırganın enjekte ettiği script'in geçerli nonce'u olmayacağından tarayıcı onu çalıştırmaz. Dikkat: unsafe-inline ve unsafe-eval CSP'yi büyük ölçüde etkisizleştirir; kaçınılır. CSP report-uri/report-to ile ihlalleri raporlayarak Detection'a (Bölüm 12) da katkı sağlar. CSP tek başına çözüm değildir — kötü yapılandırılmış politikalar atlatılabilir — ama doğru kurulduğunda XSS etkisini dramatik biçimde düşürür.


10. Gerçek Hayat Senaryosu

Kurgu — bir kurumsal SaaS gösterge paneli (dashboard). Ürün, kullanıcıların "widget başlığı" belirlemesine izin verir ve bu başlık, aynı organizasyondaki tüm ekip üyelerinin panelinde gösterilir. Geliştirici başlığı çıktıda kodlamaz (stored XSS). Düşük yetkili bir kullanıcı, başlığa bir yük yerleştirir. Yük, bir yönetici paneli açtığında onun oturumunda çalışır; yöneticinin CSRF token'ını okuyup arka planda yeni bir yönetici kullanıcı oluşturur. Böylece düşük yetkili bir hesap, tek bir metin alanı üzerinden tüm organizasyonu ele geçirir (privilege escalation). Bu senaryo üç dersi birleştirir: (1) stored XSS en tehlikeli türdür çünkü yüksek yetkili kurbanlara pasif ulaşır; (2) XSS, CSRF savunmasını içeriden atlatır; (3) HttpOnly çerez + sıkı CSP bu zincirin birden çok halkasını kırardı.


11. Gerçek Vaka Analizi — Samy Solucanı (MySpace, 2005)

Aşağıdaki analiz, kamuya açık ve tarihsel olarak iyi belgelenmiş bir olaya dayanır. Solucan kodu verilmez; mekanizma ve dersleri incelenir.

Özet. 4 Ekim 2005'te 19 yaşındaki Samy Kamkar, MySpace profil sistemindeki bir depolanmış XSS açığını kullanarak kendini çoğaltan bir solucan yaydı. Solucan, kurbanın profiline "but most of all, samy is my hero" metnini ekliyor ve Samy'ye otomatik arkadaşlık isteği gönderiyordu. Kritik olan şuydu: kod, kurbanın profiline kendini de kopyalıyordu; böylece o profili gören sonraki kullanıcılar da etkileniyordu. Solucan, yaklaşık 20 saatte bir milyondan fazla profile yayıldı — tarihin en hızlı yayılan solucanı — ve MySpace, yayılmayı durdurmak için siteyi tamamen kapatmak zorunda kaldı.

Teknik neden. MySpace, profillerde bir miktar HTML'e izin veriyor ama <script> gibi tehlikeli etiketleri bir kara liste filtresiyle engelliyordu (Bölüm 4, kara listenin temel kusuru). Kamkar, filtreyi çeşitli atlatma teknikleriyle aştı: tarayıcıların o dönemde javascript: ifadesini bazı bağlamlarda (ör. CSS/style) yorumlaması, kelime içine satır sonu/parçalama ekleme ve olay tetikleyicileri gibi filtrenin öngörmediği varyantlar. Ayrıca same-origin bağlamında AJAX kullanarak, kurbanın oturumuyla profil güncelleme isteği atıp yükü kopyaladı. Yani zincir: kara liste atlatma → depolanmış XSS → same-origin AJAX ile kendini yazma → üstel yayılma.

Etki. Doğrudan veri tahribatı olmadı, ancak yayılma hızı MySpace altyapısını felç etti ve site saatlerce çevrimdışı kaldı. Kamkar, ABD Gizli Servisi tarafından soruşturuldu; şartlı tahliye, toplum hizmeti ve tazminatla sonuçlanan bir cezai süreç yaşadı. Olay, XSS'in "zararsız alert kutusu" olmadığını, bir platformu diz çöktürebilecek bir sistemik risk olduğunu tüm sektöre kanıtladı ve web güvenliği pratiğini kalıcı olarak değiştirdi.

Çıkarılacak dersler: 1. Kara liste temelli HTML filtreleme kırılır. Tehlikeli HTML'i "yasaklayarak" değil, güvenli öğeleri beyaz listeleyerek (sanitizer) temizleyin. Samy, kara liste felsefesinin ders kitabı çürütmesidir. 2. Stored XSS worm'a dönüşebilir. Kullanıcı içeriğinin same-origin ayrıcalıklarıyla birleşmesi üstel bir tehdittir; kullanıcı-üretimli içerik barındıran her sistem bunu tehdit modeline (Bölüm 2) almalıdır. 3. Kullanıcıya HTML izni vermek büyük bir sorumluluktur. Zengin içerik gerekiyorsa, kendi filtrenizi yazmayın; olgunlaşmış bir sanitizer kullanın.


12. Detection

Kod incelemede: Şablonlarda kodlanmamış çıktı (<?= $... ?>, echo), auto-escaping kaçış kapıları ({!! !!}, |raw, dangerouslySetInnerHTML, v-html) ve istemci tarafı tehlikeli sink'ler aranır:

grep -rnE '<\?=\s*\$'                     templates/
grep -rn  '{!!'                           resources/views/
grep -rnE 'innerHTML|document\.write|eval\(|outerHTML' public/js/

Her bulguda: "bu bağlamda doğru kodlama var mı?" (Bölüm 5).

SAST: XSS, kaynaktan ($_GET) çıktıya uzanan taint izi olarak modellenir; olgun bir tespit alanıdır. İstemci-tarafı DOM XSS için özel JS taint araçları gerekir.

DAST: Yansıyan/depolanan girdileri bağlam-farkında işaretlerle deneyerek kodlama boşluklarını bulur; stored XSS'i tespit için "gönder ve başka sayfada ara" mantığı kullanır.

WAF: Bilinen XSS kalıplarını yakalayabilir ama kodlama varyasyonları ve DOM XSS'i (istemcide olduğu için sunucu WAF'ı hiç görmez) kaçırır. Ek katman, tek savunma değil.

Loglar/SIEM: Girişte <script, onerror=, javascript:, <img, %3Cscript gibi kalıplar; ve en değerlisi CSP ihlal raporları (report-to uç noktası). Ani bir CSP ihlal artışı, aktif bir XSS denemesinin güçlü işaretidir.


13. Prevention

  • Bağlamsal çıktı kodlama (Bölüm 5) — birincil savunma. Auto-escaping şablon motoru kullanın.
  • Beyaz-listeli sanitizer (HTML Purifier) — kullanıcı HTML'ine izin verilen her yerde. Asla kendi kara liste filtrenizi yazmayın.
  • Güvenli DOM API'leriinnerHTML yerine textContent; framework kaçış kapılarını denetleyin.
  • CSP (nonce/hash tabanlı, unsafe-inline yok) — ikinci katman.
  • HttpOnly + Secure + SameSite çerezler — XSS ile çerez çalınmasını ve zincirlemeyi sınırlar (Bölüm 16).
  • Tehdit modelleme — kullanıcı-üretimli içerik akışlarını STRIDE "Tampering/Elevation" ile inceleyin (Bölüm 2).

14. Mitigation

  • Acil: Etkilenen çıktı noktalarına bağlamsal kodlama ekleyin; kritik yüzeylerde zengin içeriği geçici olarak düz metne indirin; WAF'ta geçici imza. Sıkı bir CSP devreye alarak çalışmayı durdurun (kodlama düzeltilene kadar bile etkili).
  • Geçici: Stored XSS için veritabanındaki yükleri tarayıp temizleyin; sızmış olabilecek oturumları iptal edin.
  • Kalıcı: Auto-escaping + sanitizer + CSP + HttpOnly çerezleri kalıcılaştırın; testler ekleyin.

15. Checklist

  • [ ] Her dinamik çıktı bağlamına göre kodlanıyor mu (Bölüm 5)?
  • [ ] Auto-escaping açık; raw/{!! !!}/v-html/dangerouslySetInnerHTML denetleniyor mu?
  • [ ] Kullanıcı HTML'i sağlam bir sanitizer'dan mı geçiyor (kendi kara liste filtreniz yok)?
  • [ ] İstemci JS'inde innerHTML/eval/document.write yerine güvenli API mi?
  • [ ] location.*, postMessage, document.referrer gibi source'lardan sink'e giden yollar sanitize ediliyor mu (DOM XSS)?
  • [ ] Nonce/hash tabanlı, unsafe-inline'sız CSP tanımlı mı?
  • [ ] Oturum çerezleri HttpOnly+Secure+SameSite mı?
  • [ ] CSP ihlal raporları toplanıp izleniyor mu?

16. Laboratuvar

Lab 7.1 — Üç tür. İzole bir ortamda reflected, stored ve DOM XSS için birer zemin kurun. Her birine benign bir işaret (document.title = 'xss' gibi) yerleştirip çalıştığını doğrulayın, sonra doğru savunmayla (kodlama / textContent / sanitizer) kapatın.

Lab 7.2 — Kara listeyi kır (Samy dersi). Basit bir str_replace('<script>', '', $x) "filtresi" yazın ve onu atlatan en az üç girdi bulun (büyük/küçük harf, event handler, iç içe etiket). Sonra HTML Purifier ile beyaz-listeli çözüme geçin.

Lab 7.3 — CSP etkisi. Bir sayfaya nonce tabanlı CSP ekleyin; kodlanmamış bir yükün artık çalışmadığını (konsolda CSP ihlali) gözlemleyin. unsafe-inline eklediğinizde korumanın nasıl çöktüğünü görün.

Lab 7.4 — HttpOnly. Bir çerezi HttpOnly ile ve olmadan ayarlayıp document.cookie'nin ikisinde ne döndürdüğünü karşılaştırın.


17. Quiz

  1. XSS'in tek cümlelik kök nedeni nedir ve SQL Injection'la ortak yanı nedir?
  2. Reflected, stored ve DOM-based XSS arasındaki farkları açıklayın. Hangisi kurbanın tıklamasını gerektirmez?
  3. DOM XSS neden sunucu-tarafı htmlspecialchars ile çözülemez? Source ve sink nedir?
  4. Neden "sadece alert(1)" küçümsemesi yanlıştır? XSS hangi etkilere tırmanır?
  5. XSS, CSRF token tabanlı savunmayı neden atlatabilir?
  6. Kara liste temelli HTML filtreleme neden kırılır? Samy solucanı bunu nasıl kanıtladı?
  7. Kullanıcı HTML'ine izin vermek gerektiğinde doğru yaklaşım nedir; neden kendi filtrenizi yazmamalısınız?
  8. CSP nedir ve bir kodlama hatası olsa bile XSS'i nasıl durdurabilir? unsafe-inline neden tehlikelidir?
  9. HttpOnly çerez XSS'e karşı ne sağlar, neyi sağlamaz?
  10. Stored XSS neden en tehlikeli tür sayılır ve nasıl worm'a dönüşür?
  11. innerHTML yerine textContent kullanmak neden DOM XSS'i önler?
  12. CSP ihlal raporları Detection'a nasıl katkı sağlar?

18. Kaynakça

  • OWASP, Cross Site Scripting Prevention Cheat Sheet ve DOM based XSS Prevention Cheat Sheet.
  • OWASP, Top 10:2021 — A03 Injection (XSS bu sınıfa dahildir).
  • MITRE, CWE-79: Improper Neutralization of Input During Web Page Generation (XSS).
  • W3C, Content Security Policy Level 3 spesifikasyonu; MDN, CSP dokümantasyonu.
  • PHP Manual, htmlspecialchars referansı; HTML Purifier dokümantasyonu.
  • Samy Kamkar, Technical explanation of the MySpace worm (samy.pl); Wikipedia, Samy (computer worm) (tarihsel doğrulama).
  • MDN, Element.textContent ve innerHTML güvenlik notları.