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.
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.
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
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.
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:
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.
<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.
Ç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:
innerHTMLouterHTMLinsertAdjacentHTML()document.write()- Güvensiz string tabanlı şablonlar
9. Güvenli DOM Kullanımı
Metin göstermek için güvenli yaklaşım:
const value = location.hash.substring(1);
document.getElementById("output").textContent = value;
Yeni element oluşturmak için:
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 |
|---|---|
| & | & |
| < | < |
| > | > |
| " | " |
| ' | ' |
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
$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ı:
<%= 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:
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:
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.
16. Çerez Güvenliği
XSS riskini azaltmak için çerezlerde aşağıdaki özellikler kullanılmalıdır:
| Özellik | Amacı |
|---|---|
| HttpOnly | JavaScript üzerinden çereze erişimi sınırlar. |
| Secure | Çerezin yalnızca HTTPS üzerinden gönderilmesini sağlar. |
| SameSite | Siteler arası isteklerde çerez gönderimini sınırlar. |
HttpOnly XSS açığını düzeltmez; yalnızca bazı etkileri azaltı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ı
- Test ortamının size ait olduğunu doğrulayın.
- Snapshot veya yedek alın.
- Zararsız metin ve HTML girdileriyle başlayın.
- Uygulamanın çıktıyı hangi bağlamda oluşturduğunu belirleyin.
- Tarayıcı geliştirici araçlarında DOM’u inceleyin.
- Düzeltmeyi uygulayın.
- Aynı testi tekrar çalıştırın.
- 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.
-
innerHTMLyerine 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.