Merhaba, "İleri Seviye Güvenli Kod İnceleme Metodolojisi" modülümüzün beşinci dersine hoş geldiniz. Önceki dersimizde, enjeksiyon zafiyetlerinin evrensel doğasını inceleyerek OS komut enjeksiyonu ve SQL enjeksiyonu gibi saldırıların farklı programlama dillerindeki yansımalarını karşılaştırdık. Temel çıkarımımız şuydu: Güvenilmeyen verinin bir yorumlayıcı tarafından "kod" olarak algılanması, zafiyetin özünü oluşturur ve savunma, veri ile komutu birbirinden ayırmaya dayanır.
Bu derste, yine bir enjeksiyon zafiyeti olan fakat bu kez yorumlayıcının kullanıcının tarayıcısı olduğu Siteler Arası Komut Çalıştırma (Cross-Site Scripting - XSS) konusuna odaklanacağız. Amacımız, XSS zafiyetinin modern web framework'leri olan Spring, Django, React ve ASP.NET üzerindeki bağlama özgü (context-aware) savunma mekanizmalarını karşılaştırmaktır. Bu ders, "her şeyi escape et" şeklindeki yüzeysel yaklaşımdan daha derine inerek, çıktının hangi bağlamda (HTML body, attribute, JavaScript vb.) render edildiğinin neden hayati önem taşıdığını ve her framework'ün bu soruna nasıl yaklaştığını anlamanızı sağlayacaktır.
Modern framework'lerin sunduğu gelişmiş korumalara rağmen, XSS'in hala ne kadar yaygın olduğunu görmek için aşağıdaki görsele göz atabilirsiniz.

XSS'in Temel Taşı: Bağlama Özgü Çıktı Kodlama (Context-Aware Output Encoding)
Önceki derste, enjeksiyonu önlemek için veriyi "sanitize" etmemiz veya parametreli sorgular kullanmamız gerektiğini gördük. XSS için de benzer bir mantık geçerlidir, ancak burada "sanitize" etme eylemi çok daha karmaşıktır. Çünkü verinin nereye yazılacağına bağlı olarak farklı karakterler tehlikeli hale gelir. Örneğin, < karakteri bir <div> elementi içinde tehlikeliyken, bir JavaScript string'i içinde zararsız olabilir. Tersine, tek tırnak (') karakteri bir <div> içinde zararsızken, bir JavaScript string'ini erken kapatarak kod enjeksiyonuna olanak tanıyabilir.
Bu nedenle, etkili bir XSS savunması tek bir "kaçış" (escape) fonksiyonuna dayanamaz; bağlama duyarlı olmak zorundadır. Bu temel prensibi ve farklı bağlam türlerini anlamak için OWASP'ın bu konudaki kılavuzu mükemmel bir başlangıç noktasıdır.
Cross Site Scripting Prevention - OWASP Cheat Sheet Series
OWASP tarafından hazırlanan bu kılavuz, XSS'ten korunma stratejilerinin temelini oluşturan çıktı kodlama (output encoding) prensibini detaylı bir şekilde ele almaktadır. Farklı bağlamlar için farklı kodlama yöntemlerinin gerekliliğini vurgulaması, dersimizin ana fikrini anlamak için kritiktir.
Lütfen ilk olarak "Output Encoding" başlığı altındaki bölümü okuyun. Bu kısım, tarayıcıların HTML, JavaScript, URL ve CSS'i farklı şekillerde yorumladığını ve bu nedenle doğru kodlama yöntemini kullanmanın neden önemli olduğunu açıklar. Ardından, aşağıdaki bağlamlar için özel olarak açıklanan kodlama kurallarını dikkatlice inceleyin. Her bir bağlamın nasıl farklı bir tehdit modeli sunduğuna ve hangi karakterlerin tehlikeli olduğuna odaklanın: HTML Bağlamları HTML Nitelik (Attribute) Bağlamları JavaScript Bağlamları CSS Bağlamları URL Bağlamları Son olarak, "XSS Prevention Rules Summary" bölümündeki özet tabloyu gözden geçirin. Bu tablo, farklı veri türleri ve bağlamlar için hangi savunma yönteminin uygulanması gerektiğini somut örneklerle özetlemektedir.
Artık teorik temeli anladığımıza göre, bu prensiplerin önde gelen web framework'lerinde nasıl uygulandığını karşılaştıralım.
Framework'ler Arası Karşılaştırma
Her modern framework, XSS'e karşı yerleşik koruma mekanizmaları sunar. Ancak bu korumaların varsayılan davranışları, kapsamları ve bilinçli olarak devre dışı bırakılabilecekleri "kaçış yolları" (escape hatches) farklılık gösterir.
1. Django (Python)
Django, sunucu taraflı render (SSR) yapan framework'ler arasında en sağlam XSS korumalarından birine sahiptir.
- Varsayılan Davranış: Django'nun şablon motoru, bir değişkene (
{{ degisken }}) basılan tüm verileri varsayılan olarak HTML-encode eder. Bu,<karakterini<'e,>karakterini>'e dönüştürerek en temel HTML enjeksiyonlarını engeller. - Kaçış Yolları: Django, geliştiricilere bu korumayı bilinçli olarak aşmaları için birkaç yol sunar. İşte bu noktalar, kod incelemesinde odaklanmanız gereken kritik
sink'lerdir.
Aşağıdaki Semgrep kılavuzu, Django'daki bu tehlikeli desenleri mükemmel bir şekilde özetlemektedir.
Semgrep tarafından hazırlanan bu kılavuz, Django'da XSS zafiyetlerine yol açabilecek yaygın kodlama hatalarını ve şablon kullanım desenlerini listeler. Kod incelemesi sırasında doğrudan aranabilecek anahtar kelimeler ve desenler sunması açısından oldukça pratiktir.
Lütfen belgedeki şu bölümleri inceleyin. Her birinin, Django'nun varsayılan güvenlik mekanizmasını nasıl devre dışı bıraktığına dikkat edin: "Safe" İçerik İşaretleme: Sunucu tarafı Python kodunda, mark_safe() fonksiyonunun veya SafeString sınıfının doğrudan kullanımının çıktıyı "güvenli" olarak işaretleyip otomatik kaçış işlemini nasıl engellediğini görün. Şablon Motorunu Atlamak: HttpResponse nesnesine doğrudan veri yazmanın veya autoescape=False ayarının şablon motorunun korumalarını tamamen nasıl devre dışı bıraktığını anlayın. Şablonlarda Kaçışsız Değişkenler: Şablon içinde |safe filtresinin veya {% autoescape off %} bloğunun kullanımının, belirli değişkenler veya bloklar için kaçış işlemini nasıl iptal ettiğini inceleyin. Tehlikeli Konumlardaki Değişkenler: Bir değişken tırnak içine alınmadan bir HTML niteliğine (<div class={{ classes }}>) veya bir href niteliğine yerleştirildiğinde (<a href="{{ link }}">) otomatik kaçışın neden yetersiz kaldığını ve javascript: gibi protokoller aracılığıyla nasıl XSS'e yol açabileceğini öğrenin. Ayrıca, değişkenleri doğrudan <script> bloğuna yerleştirmenin tehlikelerini ve json_script etiketinin neden daha güvenli bir alternatif olduğunu görün.

2. Spring (Java) & Thymeleaf
Spring Boot ile genellikle kullanılan Thymeleaf şablon motoru, Django'ya benzer şekilde, bağlama duyarlı otomatik kaçış özelliği sunar.
- Varsayılan Davranış: Thymeleaf, bir değişkenin kullanıldığı bağlamı anlar ve uygun kaçış yöntemini otomatik olarak uygular.
th:text="'<script>alert(1)</script>'": Bu,<script>...etiketini HTML entity'lerine dönüştürerek (<script>...) güvenli bir şekilde ekrana basar.th:attr="data-id=${degisken}": Değişkeni nitelik bağlamı için uygun şekilde kodlar.- JavaScript inlining:
let username = /*[[${kullaniciAdi}]]*/ 'default';ifadesinde Thymeleaf,kullaniciAdideğişkeninin bir JavaScript string'i içinde olduğunu anlar ve"veya'gibi karakterleri\"veya\'şeklinde doğru bir şekilde kaçırır.
- Kaçış Yolu: Otomatik kaçışı devre dışı bırakmak için
th:utext(unescaped text) kullanılır.th:utextkullanımı,mark_safegibidir ve kod incelemesinde mutlaka sorgulanması gereken bir durumdur. - Anti-Pattern: OWASP kılavuzunda da belirtildiği gibi,
Spring InterceptorveyaServlet Filtergibi mekanizmalarla tüm parametreleri global olarak encode etmeye çalışmak hatalı bir yaklaşımdır. Çünkü bu katman, verinin nihayetinde hangi bağlamda (HTML, JS, CSS) render edileceği bilgisine sahip değildir ve yanlış kodlama yaparak hem güvenliği sağlayamaz hem de uygulamayı bozabilir.
3. React (JavaScript)
React gibi istemci taraflı (client-side) framework'lerde XSS dinamiği, sunucu taraflı render'dan farklıdır. Burada sink'ler, doğrudan DOM'u manipüle eden JavaScript fonksiyonlarıdır.
- Varsayılan Davranış: React, JSX içinde
{}süslü parantezlerle render edilen tüm ifadeleri varsayılan olarak string'e çevirir ve HTML olarak yorumlamaz. Bu, en yaygın Reflected XSS saldırılarına karşı güçlü bir koruma sağlar. Örneğin,<div>{userInput}</div>yazdığınızda,userInputiçinde<script>etiketleri olsa bile bunlar metin olarak görünecektir. - Kaçış Yolu: React'in en bilinen tehlikeli "kaçış yolu"
dangerouslySetInnerHTMLprop'udur. Adından da anlaşılacağı gibi, bu prop'u kullanmak, React'in varsayılan XSS korumasını tamamen devre dışı bırakır ve sağlanan string'i doğrudan HTML olarak DOM'a enjekte eder. - Diğer Zafiyet Vektörleri:
- URL Enjeksiyonu: React, bir
<a>etiketininhrefözelliğine atananjavascript:alert(1)gibi bir URL'i engellemez. Bu, JSX'in kendisi güvenli olsa bile, nitelikler üzerinden XSS'e yol açabilir. - DOM Manipülasyonu:
innerHTML,outerHTMLgibi doğrudan DOM manipülasyonu yapan vanilla JavaScript fonksiyonlarının kullanımı da React'in korumalarını atlar.
- URL Enjeksiyonu: React, bir
Bu tehlikeli kullanımları ve çözümlerini anlamak için aşağıdaki video mükemmel bir kaynaktır.
The Last XSS Defense Talk - Jim Manico - NDC Porto 2022
Jim Manico'nun "The Last XSS Defense Talk" başlıklı bu konuşması, modern framework'lerde XSS savunmasını son derece pratik ve akılda kalıcı bir şekilde anlatıyor.
Lütfen şu bölümlere odaklanın: React ve View'da XSS Bypass: Konuşmacı, bir href niteliğine javascript: URI'si enjekte ederek React ve Vue'nun varsayılan korumalarının nasıl aşılabileceğini gösteriyor. Güvenli çözüm olarak, URL'in sadece http veya https ile başlamasını zorunlu kılan bir kontrol eklemeyi öneriyor. HTML Sanitizasyonu: Kullanıcının zengin metin (HTML) girmesine izin verilen durumlarda (WYSIWYG editörleri gibi), dangerouslySetInnerHTML gibi fonksiyonların nasıl güvenli hale getirileceğini açıklıyor. Çözüm olarak DOMPurify gibi bir HTML sanitizasyon kütüphanesi ile veriyi temizlemeyi gösteriyor. Bu yaklaşımın React, Angular ve Vue'da nasıl uygulandığını karşılaştırıyor. Güvenli ve Güvensiz JavaScript Fonksiyonları: innerHTML gibi tehlikeli (unsafe sink) ve textContent gibi güvenli (safe sink) JavaScript fonksiyonlarını listeliyor. DOMPurify kullanılarak tehlikeli fonksiyonların nasıl güvenli hale getirilebileceğini tekrar vurguluyor.
4. ASP.NET (C#)
ASP.NET Core'da kullanılan Razor şablon motoru da varsayılan olarak güçlü XSS korumaları sunar.
- Varsayılan Davranış: Razor,
@karakteri ile basılan tüm değişkenleri otomatik olarak HTML-encode eder. Bu, Django ve Thymeleaf'e benzer bir varsayılan güvenlik duruşudur. - Kaçış Yolu: Bu otomatik kodlamayı atlamak için
Html.Raw()metodu kullanılır.stringbir değeriIHtmlContenttipine dönüştürerek Razor'a "bu içeriğin güvenli olduğunu ve doğrudan render edilmesi gerektiğini" söyler.Html.Raw(kullaniciGirdisi)kullanımı, kod incelemelerinde kırmızı bayrak olmalıdır. - Bağlam Farkındalığı: Razor, HTML body ve attribute'lar için varsayılan olarak güvenli olsa da, JavaScript bağlamları için geliştiricinin daha dikkatli olması gerekir. Değişkenleri doğrudan
<script>blokları içine yazmak, JavaScript kaçış kurallarının uygulanmasını gerektirir. Bunun içinSystem.Text.Encodings.Web.JavaScriptEncodergibi sınıflar kullanılabilir.
Özet ve Katmanlı Savunma
Aşağıdaki tablo, tartıştığımız framework'lerin XSS'e karşı yaklaşımlarını özetlemektedir:
| Framework | Varsayılan Davranış | Tehlikeli "Kaçış Yolu" | Temel Savunma Stratejisi |
|---|---|---|---|
| Django | Şablonlarda otomatik HTML kaçışı | mark_safe, |safe |
Şablon motorunun varsayılanlarına güvenin. "Safe" olarak işaretlenen her şeyi denetleyin. JS'e veri aktarmak için json_script kullanın. |
| Spring (Thymeleaf) | Bağlama duyarlı otomatik kaçış | th:utext |
Thymeleaf'in bağlam analizine güvenin. th:utext kullanımını sıkı bir şekilde denetleyin. |
| React | JSX içinde string olarak render etme | dangerouslySetInnerHTML |
Ham HTML'i asla render etmeyin. Gerekliyse, DOMPurify ile sanitize edin. href gibi niteliklere gelen URL'leri doğrulayın. |
| ASP.NET (Razor) | Şablonlarda otomatik HTML kaçışı | Html.Raw() |
Razor'ın varsayılan kaçış mekanizmasına güvenin. Html.Raw() kullanımını denetleyin. JS bağlamları için manuel kodlama gerektiğini unutmayın. |
Derinlemesine Savunma: Content Security Policy (CSP)
Çıktı kodlama, XSS'e karşı birincil savunma hattıdır. Ancak bir hata yapılması durumunda devreye girecek ikinci bir savunma katmanı olarak Content Security Policy (CSP) kritik bir rol oynar. CSP, sunucudan tarayıcıya gönderilen bir HTTP yanıt başlığıdır ve tarayıcının hangi kaynaklardan (script'ler, stiller, resimler vb.) içerik yükleyebileceğini kısıtlayan bir beyaz liste (allow-list) tanımlar.
HTTP Secure Headers for Web App Security | CORS, CSP, HSTS and more
ByteMonk kanalının bu kısa videosu, CSP'nin ne olduğu ve nasıl çalıştığına dair mükemmel bir özet sunuyor.
Lütfen CSP bölümünü izleyin. Videonun, CSP'yi bir "beyaz liste" olarak nasıl tanımladığına ve XSS saldırısı durumunda, saldırganın enjekte ettiği script'in güvenilir kaynaklar listesinde olmadığı için tarayıcı tarafından nasıl engelleneceğini nasıl açıkladığına dikkat edin.
CSP, özellikle nonce (number used once) tabanlı politikalarla uygulandığında son derece etkilidir. Bu yaklaşımda, sunucu her sayfa isteği için rastgele bir nonce değeri üretir, bu değeri hem CSP başlığına hem de güvendiği <script> etiketlerine ekler. Saldırganın enjekte ettiği script bu nonce değerini bilmediği için tarayıcı tarafından çalıştırılmaz. Bu ileri düzey teknikler, bir sonraki "İstemci Taraflı Saldırılar" modülünde daha detaylı incelenecektir.
Kapanış
Bu derste, farklı web framework'lerinin XSS'e karşı nasıl farklı ancak temelde benzer prensiplere dayanan savunma mekanizmaları sunduğunu karşılaştırdık.
Ana Çıkarımlar:
- XSS Savunması Bağlam Gerektirir: Tek bir kaçış fonksiyonu yeterli değildir; savunma, verinin render edildiği bağlama (HTML, attribute, JS, CSS, URL) göre yapılmalıdır.
- Framework'ler Varsayılan Olarak Güvenlidir: Modern sunucu taraflı framework'ler (Django, ASP.NET/Razor, Spring/Thymeleaf) varsayılan olarak çıktıları kodlayarak güçlü bir başlangıç noktası sunar.
- "Kaçış Yollarına" Dikkat:
mark_safe,Html.Raw,th:utextgibi fonksiyonlar, bu güvenliği bilinçli olarak devre dışı bırakır ve kod incelemelerinde en çok odaklanılması gereken yerlerdir. - İstemci Tarafı Farklıdır: React gibi istemci tarafı kütüphaneler, DOM'a doğrudan HTML enjekte eden
dangerouslySetInnerHTMLgibi fonksiyonlar etrafında farklı bir risk modeli sunar. Çözüm, genellikle HTML sanitizasyonudur. - Katmanlı Savunma Esastır: Mükemmel çıktı kodlamaya ek olarak, CSP gibi mekanizmalar, olası bir hatanın istismar edilmesini önleyen kritik bir ikinci savunma hattı sağlar.
Bu dersle birlikte, kod inceleme metodolojimizin temel analitik yaklaşımlarını tamamlamış olduk. Bir sonraki modülde, bu derslerde edindiğimiz bilgileri kullanarak daha karmaşık enjeksiyon saldırılarını analiz etmeye başlayacağız. İlk olarak, bir saldırganın doğrudan bir yanıt alamadığı durumlarda bile veritabanından bilgi sızdırmasına olanak tanıyan Kör SQL Enjeksiyonu (Blind SQL Injection) ve bant dışı (out-of-band) veri sızdırma tekniklerini inceleyeceğiz.