---
title: "İçerik Güvenlik Politikası (CSP): XSS’i Son Savunma Hattında Durdurmak"
url: "https://cilginyazilim.com/blog/icerik-guvenlik-politikasi-csp-kurulumu"
description: "İçerik güvenlik politikası XSS saldırılarını nasıl engeller? Nonce kullanımı, rapor modu, sık yapılan hatalar ve CodeIgniter ile adım adım güvenli kurulum."
published: "2026-09-15T10:00:00+03:00"
modified: "2026-09-15T10:00:03+03:00"
author: "superadmin"
category: "Siber Güvenlik"
tags: ["php", "codeigniter", "raporlama", "siber güvenlik", "xss", "içerik güvenlik politikası", "csp", "web güvenliği", "http başlıkları", "nonce", "tarayıcı güvenliği", "güvenlik açığı", "savunma"]
site: "CılgınYazılım"
language: "tr"
---

# İçerik Güvenlik Politikası (CSP): XSS’i Son Savunma Hattında Durdurmak

Kaçırdığınız tek bir XSS açığını zararsız kılan bir başlık var. Ama yanlış kurulursa hiçbir şey yapmaz.

**İçerik güvenlik politikası** (CSP), tarayıcıya "bu sayfada hangi kaynaklardan kod çalıştırılabilir" listesini veren bir HTTP başlığıdır. XSS açığını kapatmaz — onu kapatmak girdi doğrulama ve çıktı kaçırmanın işidir. CSP'nin görevi farklıdır: *kaçırdığınız* bir açığın sömürülmesini engellemektir. Yani son savunma hattıdır.

![CSP kurulumunun aşamaları](https://cilginyazilim.com/uploads/blog/2026/08/icerik-guvenlik-politikasi-csp-kurulumu-ozet.png)
*unsafe-inline içeren bir CSP, XSS karşısında pratikte hiçbir koruma sağlamaz.*

## Neden gerekli?

Büyük bir uygulamada tek bir kaçış noktası bile yeter. Bir yorum alanı, bir profil biçimi, üçüncü parti bir bileşenin çıktısı — bunlardan biri kaçırılmadan basılırsa saldırgan script çalıştırabilir. CSP doğru kurulduğunda o script, alan dışı bir kaynaktan geldiği için tarayıcı tarafından reddedilir.

## Aşama 1: kırmadan gözlemleyin

CSP'yi doğrudan zorlayıcı modda açmak, sitenin yarısını çalışmaz hâle getirmenin en hızlı yoludur. Doğru başlangıç `Report-Only` modudur: tarayıcı hiçbir şeyi engellemez, yalnızca ihlalleri bildirir.

```php
// app/Filters/CspFilter.php
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
{
    $politika = implode('; ', [
        "default-src 'self'",
        "script-src 'self'",
        "style-src 'self' 'unsafe-inline'",     // stil için geçici tolerans
        "img-src 'self' data: https:",
        "font-src 'self' data:",
        "connect-src 'self'",
        "frame-ancestors 'none'",               // clickjacking koruması
        "base-uri 'self'",
        "form-action 'self'",
        'report-uri ' . base_url('guvenlik/csp-rapor'),
    ]);

    // ÖNCE Report-Only: neyin kırılacağını üretimde öğrenin
    $response->setHeader('Content-Security-Policy-Report-Only', $politika);
}
```

## Aşama 2: raporları toplayın

```php
public function cspRapor()
{
    $ham = $this->request->getBody();
    $veri = json_decode((string) $ham, true)['csp-report'] ?? null;

    if (! is_array($veri)) {
        return $this->response->setStatusCode(204);
    }

    // Gürültüyü azalt: aynı ihlali dakikada bir kez yaz
    $anahtar = 'csp:' . md5(($veri['violated-directive'] ?? '') . ($veri['blocked-uri'] ?? ''));
    if (! cache()->get($anahtar)) {
        cache()->save($anahtar, 1, 60);
        log_message('warning', 'CSP ihlali: ' . json_encode([
            'yonerge' => $veri['violated-directive'] ?? null,
            'engellenen' => $veri['blocked-uri'] ?? null,
            'sayfa' => $veri['document-uri'] ?? null,
        ], JSON_UNESCAPED_UNICODE));
    }

    return $this->response->setStatusCode(204);
}
```

> Rapor ucunu **hız sınırlaması olmadan** açık bırakmayın. Tarayıcılar ihlal başına istek gönderir; kötü bir politika saniyede binlerce rapor üretebilir ve kendi ucunuz sizi devirir.

## Aşama 3: satır içi script sorunu

Gerçek projelerde satır içi `<script>` blokları vardır. Çözüm `'unsafe-inline'` eklemek *değildir* — bu, CSP'yi tamamen etkisiz kılar, çünkü saldırganın enjekte ettiği script de satır içidir. Doğru çözüm nonce'tur: her yanıtta rastgele bir değer üretilir, hem başlığa hem de meşru script etiketlerine yazılır.

```php
// Filtrenin before() aşamasında istek başına BİR kez üretilir
$nonce = base64_encode(random_bytes(16));
service('request')->setGlobal('csp_nonce', $nonce);   // görünümler okuyacak

$politika = "script-src 'self' 'nonce-{$nonce}'";
```

```html
<!-- Görünümde: yalnızca BİZİM script'imiz nonce taşır -->
<script nonce="<?= esc($cspNonce, 'attr') ?>">
  console.log('Bu blok çalışır.');
</script>

<!-- Saldırganın enjekte ettiği blok nonce bilemez → tarayıcı çalıştırmaz -->
```

Nonce her yanıtta değişmelidir. Sabit bir nonce, saldırganın onu okuyup kendi etiketine yazmasıyla anlamsızlaşır.

## Aşama 4: zorlayıcı moda geçiş

Raporlar birkaç gün boyunca temiz geliyorsa başlık adını `Content-Security-Policy` olarak değiştirin — ama `report-uri` yönergesini kaldırmayın. Zorlayıcı modda da raporlama, yeni eklenen bir üçüncü parti bileşenin sessizce kırılmasını fark etmenizi sağlar.

Bu tür kuralları ekibe aktarırken canlı örnek üzerinden ilerlemek etkilidir; [teknik mülakatta canlı kod yazma](https://cilginyazilim.com/blog/teknik-mulakatta-canli-kod-yazma) yazımızdaki yaklaşım eğitimlerde de işe yarar.

## Sık yapılan üç hata

**Her şeye izin veren politika.** `default-src *` ile başlayan bir politika yalnızca güvenlik taramalarında "CSP var" tikini almanızı sağlar; gerçek koruma sıfırdır.

**frame-ancestors unutmak.** Bu yönerge, sayfanızın başka bir sitede çerçevelenmesini engeller ve clickjacking'e karşı en pratik korumadır. Eski `X-Frame-Options` başlığının yerini almıştır.

**CSP'yi girdi doğrulamanın yerine koymak.** CSP bir yedek plandır. Asıl savunma hâlâ çıktı kaçırma ve izin listesine dayalı HTML temizlemedir; [en sık görülen açıklar](https://cilginyazilim.com/blog/web-uygulama-guvenligi-en-sik-gorulen-aciklar) yazımızda bu katmanları sıralamıştık.

## Kod paylaşan siteler için özel not

Blog veya dokümantasyon gibi kullanıcı/editör HTML'i basan sistemlerde CSP daha da değerlidir, çünkü zengin metin editörleri geniş bir etiket kümesine izin verir. Kaydetme anında izin listesiyle temizlemek ve yayında CSP ile ikinci bir kapı kurmak birlikte çalışır. Bağımlılık üzerinden gelen riskler içinse [bağımlılık zinciri saldırıları](https://cilginyazilim.com/blog/bagimlilik-zinciri-saldirilari-paketleri-guvenle-kullanmak) yazımıza bakabilirsiniz; CSP, ele geçirilmiş bir CDN betiğinin veri sızdırmasını da `connect-src` ile sınırlar. Yönergelerin tam listesi için [MDN CSP belgeleri](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) kapsamlı bir referanstır. Oturum tarafındaki tamamlayıcı önlemler için [parola saklama ve oturum güvenliği](https://cilginyazilim.com/blog/parola-saklama-ve-oturum-guvenligi) yazımız okunabilir.

## Sonuç

CSP, doğru kurulduğunda kaçırılan bir XSS açığını sömürülemez hâle getiren tek mekanizmadır; yanlış kurulduğunda ise yalnızca bir güvenlik raporunda iyi görünen bir başlıktır. Farkı yaratan üç karardır: `unsafe-inline` yazmamak, satır içi script'leri istek başına değişen nonce ile beyaz listelemek ve zorlayıcı moda ancak rapor modunda temiz sonuç aldıktan sonra geçmek. Bugün `Report-Only` başlığını ekleyip bir hafta rapor toplayın — sitenizin hangi kaynaklardan kod çalıştırdığını görmek, tek başına bile öğretici olacaktır.

## Sıkça Sorulan Sorular

### CSP eklersem sitem yavaşlar mı?

Hayır, CSP yalnızca bir HTTP başlığıdır ve tarayıcı tarafında ihmal edilebilir bir maliyeti vardır. Yavaşlama hissi genelde politikanın bazı kaynakları engellemesi ve sayfanın eksik yüklenmesinden kaynaklanır; bu bir performans değil yapılandırma sorunudur.

### Report-Only modunda ne kadar kalmalıyım?

Trafiğin haftanın tüm günlerini ve ana kullanıcı akışlarını kapsayacak kadar. Pratikte bir hafta çoğu site için yeterlidir. Nadiren kullanılan yönetim ekranlarını unutmamak için o sayfaları elle de gezmek gerekir.

### Nonce yerine hash kullanabilir miyim?

Evet, satır içi blok sabitse SHA-256 özetini politikaya yazabilirsiniz. Ancak blok her değiştiğinde politikayı güncellemeyi unutmak kolaydır; dinamik içerik üreten sayfalarda nonce daha sürdürülebilirdir.

### Üçüncü parti analiz betikleri politikayı zayıflatır mı?

Her eklenen dış kaynak saldırı yüzeyini büyütür. En azından tam alan adını (joker karakter kullanmadan) yazın ve connect-src ile veri gönderebileceği adresleri sınırlayın. Gerçekten gerekli olmayan üçüncü parti betiği kaldırmak, en etkili güvenlik iyileştirmesidir.

---

Kaynak: [İçerik Güvenlik Politikası (CSP): XSS’i Son Savunma Hattında Durdurmak](https://cilginyazilim.com/blog/icerik-guvenlik-politikasi-csp-kurulumu)
