Bölüm 9 / 11
OWASP Top 10
SQL injection, XSS, IDOR, güvenlik yanlış yapılandırması.
17 dakikalık okuma
Bu hat boyunca kimlik tarafını kurduk. Şimdi geriye kalan
her şeyin ortak listesi var: OWASP Top 10 — web uygulamalarındaki en yaygın
ve en etkili zafiyet kategorileri. Bu ders bir liste ezberi değil; her kategoriyi
mekanizma düzeyinde açıp senin daha önce yazdığın koda bağlıyor: 7. hattaki
parametreli sorgu, 12-09'daki beyaz liste, 11. hattaki
dangerouslySetInnerHTML. Ağırlık iki başlıkta: bozuk erişim
kontrolü (3. dersin devamı) ve enjeksiyon — SQL ve XSS. Sonunda
13-04'te açık bıraktığımız borç kapanıyor: CSP.
01Ne öğreneceksin
- OWASP Top 10 ne değildir: neden bir uyumluluk kontrol listesi sayılmaz
- A01 Bozuk erişim kontrolü: IDOR'un kardeşleri — yol geçişi, kütle atama, zorla gezinme, CORS yanlış yapılandırması
- SQL enjeksiyonu mekanizması, parametreli sorgunun neden işe yaradığı ve ORM'in yalancı güvenliği; kör enjeksiyon; komut enjeksiyonu
- XSS üç tür (yansıyan / saklanan / DOM tabanlı), bağlama göre çıktı kodlama ve çerçevelerin kaçış kapıları
- CSP:
nonce,unsafe-inlineve raporlama modu — XSS'e karşı ikinci savunma hattı - Kalan kategoriler: kriptografik hatalar, güvensiz tasarım, yanlış yapılandırma + güvenlik başlıkları tablosu, eski bileşen, bütünlük, loglama
- SSRF ve bulut metadata servisi; dosya yükleme kontrol listesi
02Liste ne işe yarar, ne işe yaramaz
OWASP Top 10, gerçek uygulamalardan toplanan zafiyet verilerine dayanan, birkaç yılda bir güncellenen bir farkındalık belgesidir. Kategoriler yaygınlık, istismar edilebilirlik ve etkiye göre sıralanır. Değeri, "nereye bakmalıyım" sorusuna veri temelli bir cevap vermesidir.
Ne değildir: tam bir güvenlik standardı değildir (onun için ASVS gibi belgeler vardır), bir uyumluluk kontrol listesi değildir ve "bu on maddeyi geçtim, güvenliyim" anlamına gelmez. Kategoriler geniştir: "bozuk erişim kontrolü" başlığı altında birbirinden çok farklı onlarca zafiyet biçimi vardır. Doğru kullanım şudur: listeyi tehdit modelinin (1. ders) girdi listesi olarak kullan, kendi sisteminde her kategorinin karşılığını ara.
Bir de sıralamanın kendisi bilgi taşır: erişim kontrolü listenin başındadır. Yani sahadaki en yaygın ve en etkili sorun egzotik bir kriptografi açığı değil, "kontrol edilmesi gereken yerde kontrol edilmemiş olması"dır. Kıdemli bir gözün ilk baktığı yer burasıdır.
03A01 — Bozuk erişim kontrolü
3. derste IDOR'u işledik: rol kontrol edilip sahiplik unutulması. Aynı kategorinin diğer yüzleri şunlardır ve hepsi aynı kök hataya çıkar — kararın istemciye bırakılması:
| Biçim | Nasıl | Savunma |
|---|---|---|
| IDOR | /basvuru/{id} — başkasının kimliği denenir | Kimlik oturumdan; sahiplik sorgunun koşulunda (3. ders, 8. ders) |
| Zorla gezinme | Menüde görünmeyen /admin/... yolu doğrudan yazılır | Güvenli varsayılan: FallbackPolicy (8. ders) |
| Yol geçişi | ?dosya=../../etc/passwd ya da ..%2f..%2f | Kullanıcı girdisi yol birleştirmede kullanılmaz; kimliğe göre dosya eşlemesi; çözümlenmiş yolun kök dizin altında olduğu doğrulanır (12-04) |
| Kütle atama | Gövdeye "rol":"yonetici" eklenir, model bağlama yazar | Ayrı DTO; alan beyaz listesi; zod .strict() (12-09) |
| Metot atlaması | GET korunmuş, aynı işi yapan PUT unutulmuş | Kontrol uç bazında değil işlem bazında düşünülür |
| CORS yanlış yapılandırma | Gelen Origin'i aynen yansıtmak + credentials: true | Beyaz liste; joker ile kimlik bilgisi birlikte kullanılmaz |
Son satır 12-07 ile 13-04'ün birleştiği yerdir ve inceliklidir. CORS bir güvenlik
önlemi değil bir gevşetme mekanizmasıdır; ama yanlış gevşetilirse
zafiyet üretir. Klasik hata, "hangi köken gelirse ona izin verelim" diye gelen
Origin başlığını yanıta aynen kopyalamak ve üstüne
Access-Control-Allow-Credentials: true eklemektir. Sonuç: herhangi
bir site, kullanıcının çerezleriyle senin API'ni çağırıp yanıtı okuyabilir.
Bu artık CSRF değil, doğrudan veri hırsızlığıdır. Kural: izin verilen kökenler sabit
bir listeden gelir ve joker (*) ile kimlik bilgisi asla birlikte
kullanılmaz.
04Enjeksiyon — SQL ve komut
Enjeksiyonun tek cümlelik tanımı: veri olması gereken şeyin kod olarak yorumlanması. Kullanıcı girdisi bir yorumlayıcıya (SQL motoru, kabuk, LDAP, XPath, şablon motoru) gönderilirken veri ile komut aynı kanaldan gidiyorsa, girdi komutu değiştirebilir.
-- ZAFİYETLİ: dize birleştirme
var sql = "SELECT * FROM Basvurular WHERE Eposta = '" + eposta + "'";
-- Girdi: ' OR '1'='1' --
-- Sonuç: SELECT * FROM Basvurular WHERE Eposta = '' OR '1'='1' --'
-- → tüm tablo döner
-- DOĞRU: parametreli sorgu — girdi ASLA sorgu metnine girmez
var sql = "SELECT * FROM Basvurular WHERE Eposta = @eposta";
cmd.Parameters.Add("@eposta", SqlDbType.NVarChar, 320).Value = eposta;
Parametreli sorgu neden işe yarar? Çünkü sorgu metni ve veri
ayrı kanallardan gider: veritabanı önce sorgu planını kurar, sonra
parametre değerlerini yerleştirir. Değer içinde tırnak, noktalı virgül ya da
DROP olması hiçbir şeyi değiştirmez — o artık kod değil, veridir.
Bu, "kaçış karakteri ekleyerek temizlemekten" kategorik olarak daha güçlüdür;
kaçış listeleri her zaman eksiktir, kanal ayrımı ise yapısaldır.
ORM'in yalancı güvenliği. "Entity Framework kullanıyorum, enjeksiyon
olmaz" cümlesi yanlıştır. EF Core LINQ sorgularını parametreli üretir, evet — ama
üç kapı açık kalır: ham SQL çalıştırma (FromSqlRaw,
ExecuteSqlRaw), dinamik sıralama/filtreleme için dize birleştirme, ve
saklı yordamın içinde yapılan dinamik SQL. 12-09'daki kural burada da
geçerlidir: parametre olamayan şeyler — tablo adı, sütun adı, ASC/DESC —
birleştirme ile değil beyaz liste ile konur.
// Dinamik sıralama: parametre kullanılamaz → beyaz liste ZORUNLU
static readonly HashSet<string> IzinliSutunlar = new() { "olusturma", "unvan", "durum" };
var sutun = IzinliSutunlar.Contains(istek.Sirala) ? istek.Sirala : "olusturma";
var yon = istek.Yon == "desc" ? "DESC" : "ASC";
var sql = $"SELECT ... ORDER BY {sutun} {yon}"; // her iki değer de KAPALI kümeden geldi
Kör enjeksiyon. Uygulama hata mesajı ya da veri döndürmese bile saldırı
mümkündür: saldırgan doğru/yanlış koşullar sokup yanıtın farkına bakar
(boolean tabanlı) ya da WAITFOR DELAY / pg_sleep ile
süreye bakar (zaman tabanlı). Bu yüzden "hata mesajlarını gizledik, güvendeyiz"
yanlıştır; hata mesajını gizlemek bilgi ifşasını azaltır ama enjeksiyonu kapatmaz.
Komut enjeksiyonu aynı hatanın kabuk versiyonudur ve Node tarafında
12-04'ün devamıdır: exec("convert " + dosyaAdi) bir kabuk çağırır ve
;, |, $( ) karakterleri komut çalıştırır.
Doğrusu kabuğu hiç devreye sokmamaktır: execFile/spawn ile
program ve argümanları ayrı ayrı verilir. Aynı ilke: kanal ayrımı.
Aynı kategorinin diğer üyeleri: NoSQL enjeksiyonu (sorgu nesnesine
{"$ne": null} gibi operatör kaçırmak — girdi tipini doğrulamamaktan
doğar), LDAP ve XPath enjeksiyonu, ve sunucu tarafı şablon
enjeksiyonu (kullanıcı girdisini şablon kaynağı olarak kullanmak).
05XSS — üç tür ve bağlama göre kodlama
XSS, enjeksiyonun tarayıcı tarafındaki hâlidir: saldırganın verisi, sayfada
kod olarak çalışır. Betik senin kökeninde çalıştığı için oturum çerezine
(HttpOnly olsa bile isteğe otomatik eklenir), sayfadaki CSRF jetonuna
ve kullanıcının gördüğü her şeye erişir — 13-04'te "XSS varsa CSRF savunması
anlamsızdır" derken kastettiğimiz budur.
| Tür | Nasıl | Örnek |
|---|---|---|
| Yansıyan | Girdi istekle gelir, yanıtta geri yazılır | Arama sonucu sayfasında sorgu metninin kodlanmadan basılması; saldırı bağlantıyla yayılır |
| Saklanan | Girdi veritabanına yazılır, sonra herkese servis edilir | Yorum/açıklama alanı — en tehlikelisi, her ziyaretçiyi etkiler |
| DOM tabanlı | Sunucu hiç görmez; istemci betiği URL'den okuyup DOM'a yazar | element.innerHTML = location.hash |
Asıl savunma çıktı kodlamasıdır ve bağlama göre değişir. Aynı veri HTML gövdesinde, öznitelik içinde, JavaScript dizesinde ve URL'de farklı kodlanır:
HTML gövdesi : < > & " ' → < > & ...
HTML özniteliği : ayrıca tırnak içine alınmalı — tırnaksız öznitelikte boşluk yeni öznitelik açar
JavaScript içi : HTML kodlaması BURADA İŞE YARAMAZ; veri JS'e ancak JSON olarak geçirilir
URL parametresi : yüzde kodlama; ayrıca "javascript:" şeması engellenmeli
CSS içi : ayrı kurallar — kullanıcı girdisini CSS'e koymamak en iyisi
İyi haber: modern çerçeveler bunu varsayılan olarak yapar. Angular
interpolasyonu, React'in {deger} ifadesi ve Razor'ın @deger
çıktısı otomatik kodlar. Kötü haber: hepsinin bir kaçış kapısı vardır ve
XSS'lerin çoğu oradan girer:
React : <div dangerouslySetInnerHTML={{ __html: veri }} />
Angular : [innerHTML]="veri" ve DomSanitizer.bypassSecurityTrustHtml(veri)
Razor : @Html.Raw(veri)
Vanilla : element.innerHTML = veri · document.write(veri) · eval(veri)
Bu API'lerin adları bilerek rahatsız edicidir. Kullanılmaları gerekiyorsa
(zengin metin editörü çıktısı gibi) tek doğru yol sunucu tarafında olgun bir
HTML temizleyiciden geçirmektir — beyaz listeli, bakımlı bir kütüphane. Kendi
düzenli ifadenle etiket temizlemek çalışmaz; saldırı yüzeyi
(<img onerror>, <svg onload>, kodlama
varyasyonları) düzenli ifadeyle kapatılamayacak kadar geniştir.
DOM tabanlı XSS için ek kural: innerHTML yerine
textContent, setAttribute yerine güvenli
özellik atamaları; ve URL'den gelen değerlerin şemasının doğrulanması
(href'e javascript: yazılabilir).
06CSP — 13-04'ün açık borcu
İçerik güvenliği politikası (Content Security Policy), tarayıcıya "bu sayfada hangi kaynaklardan kod/stil/görsel yüklenebilir" diyen bir yanıt başlığıdır. XSS'i önlemez — asıl savunma hâlâ çıktı kodlamasıdır — ama bir XSS'in işe yaramasını engelleyebilir: enjekte edilen betik çalışamaz ya da çaldığı veriyi dışarı gönderemez. Klasik derinlemesine savunma katmanıdır.
Content-Security-Policy:
default-src 'self';
script-src 'self' 'nonce-r4nd0m123'; ← yalnız bu nonce'a sahip inline betikler çalışır
style-src 'self';
img-src 'self' data:;
connect-src 'self' https://api.ornek.gov.tr;
frame-ancestors 'none'; ← clickjacking savunması (X-Frame-Options'ın yerini aldı)
object-src 'none'; base-uri 'self'; form-action 'self'
<script nonce="r4nd0m123"> /* her yanıtta YENİ üretilen rastgele değer */ </script>
Üç pratik nokta. Birincisi: 'unsafe-inline' yazmak politikayı
büyük ölçüde anlamsızlaştırır — enjekte edilen inline betik de çalışır. Doğru yol
her yanıtta üretilen bir nonce ya da betik özeti (hash) kullanmaktır;
'unsafe-eval' de aynı şekilde kaçınılması gerekendir.
İkincisi: CSP'yi mevcut bir uygulamaya eklemek genelde bir şeyleri kırar; bu
yüzden önce Content-Security-Policy-Report-Only ile yayına alınır,
raporlar toplanır ve politika oradan sıkılaştırılır. Üçüncüsü:
frame-ancestors 'none' ile clickjacking savunması aynı başlıkta
halledilir — sayfanın başka bir sitenin iframe'ine gömülüp kullanıcıya görünmez
tıklatma yaptırılması engellenir.
07Kalan kategoriler ve güvenlik başlıkları
| Kategori | Tipik hâli | Bu yol haritasında |
|---|---|---|
| Kriptografik hatalar | Hassas veri düz metin; parolada hızlı hash; kendi şifreleme algoritmanı yazmak; sabit IV; zayıf rastgelelik | 2. ders (TLS), 3. ders (parola), 14. hat |
| Güvensiz tasarım | Kod doğru ama tasarım yanlış: iş akışında yetki adımı hiç yok, oran sınırı düşünülmemiş | 1. ders (tehdit modeli) |
| Yanlış yapılandırma | Varsayılan parola; açık Swagger; ayrıntılı hata sayfası; gereksiz açık port; eksik güvenlik başlıkları; dizin listeleme | Aşağıdaki tablo, 10. ders |
| Eski/zafiyetli bileşen | Güncellenmemiş paketler; terk edilmiş bağımlılıklar; envanter yokluğu | 12-03 (npm), 18. hat (boru hattında tarama) |
| Kimlik doğrulama hataları | Zayıf parola politikası; oran sınırı yok; oturum yönetimi hataları | 3-5. dersler |
| Yazılım/veri bütünlüğü | İmzasız güncelleme; güvensiz seri hâlden çıkarma; CI/CD boru hattının ele geçirilmesi | 18. hat |
| Loglama ve izleme eksikliği | Saldırı fark edilmiyor; log yok ya da PII dolu; alarm yok | 12-11 (yapılandırılmış log, redaksiyon), 14. hat (SIEM) |
| SSRF | Sunucuya, saldırganın belirlediği adrese istek attırmak | 8. bölüm |
Güvenlik başlıkları, yanlış yapılandırma kategorisinin en ucuz kazancıdır; birkaç satır ara yazılımla eklenir:
| Başlık | Ne yapar |
|---|---|
Content-Security-Policy | Kaynak beyaz listesi; XSS'in etkisini sınırlar (6. bölüm) |
Strict-Transport-Security | HTTPS zorunluluğu (2. ders) |
X-Content-Type-Options: nosniff | Tarayıcının içerik türünü tahmin etmesini kapatır — yüklenen dosyanın betik olarak yorumlanmasını önler |
Referrer-Policy | Dış sitelere giden Referer bilgisini kısar (URL'deki jeton/kimlik sızıntısı) |
Permissions-Policy | Kamera, mikrofon, konum gibi tarayıcı yeteneklerini kapatır |
Cache-Control: no-store | Kimlikli yanıtların vekil/tarayıcı önbelleğinde kalmasını engeller |
Aynı başlıkta bir de çıkarma işi vardır: Server,
X-Powered-By, X-AspNet-Version gibi sürüm sızdıran
başlıklar kaldırılır. Bu tek başına bir savunma değildir (belirsizlik yoluyla
güvenlik — 1. ders), ama otomatik tarayıcıların işini zorlaştırır ve maliyeti
sıfırdır.
08SSRF ve dosya yükleme
SSRF (sunucu tarafı istek sahteciliği), uygulamanın kullanıcı tarafından verilen bir adrese istek atmasıdır: "şu URL'deki görseli içe aktar", "webhook adresini test et", "PDF'i şu adresten çek". Saldırgan adresi değiştirir ve sunucuyu kendi eli gibi kullanır — sunucu, saldırganın erişemediği iç ağa erişebilir.
Saldırganın denediği adresler:
http://169.254.169.254/latest/meta-data/ ← bulut metadata servisi: geçici kimlik bilgileri!
http://localhost:5432/ · http://10.0.0.7/admin ← iç servisler, yönetim panelleri
file:///etc/passwd · gopher://... ← şema değiştirme
İlk satır SSRF'i "ilginç" olmaktan çıkarıp kritik yapan şeydir: bulut
ortamlarında metadata servisi, makinenin rolüne ait geçici kimlik bilgilerini
döndürür; SSRF ile onu okuyan saldırgan bulut hesabında yetki kazanır. Savunma
katmanları: beyaz liste (izin verilen alan adları/şemalar — kara liste
yetersizdir), yalnız http/https şemalarına izin,
yönlendirmelerin takip edilmemesi ya da her adımda yeniden doğrulanması
(DNS rebinding ve yönlendirmeyle beyaz liste atlatılır), çıkış trafiğinin
ağ düzeyinde kısıtlanması ve metadata servisine erişimin kapatılması. Ayrıca yanıtın
gövdesi kullanıcıya aynen geri verilmez — verilirse kör SSRF, okunabilir
SSRF'e döner.
Dosya yükleme kendi başına bir kontrol listesidir ve birden çok kategoriye dokunur:
- Dosya adına asla güvenilmez. Sunucuda üretilen yeni bir ad kullanılır; kullanıcının adı yalnızca gösterim için saklanır (yol geçişi ve üzerine yazma riski — 12-04).
- Tür doğrulaması uzantıyla yapılmaz. İçerik türü başlığı da istemciden gelir. İçeriğin kendisi (imza baytları) kontrol edilir ve beyaz liste uygulanır.
- Yüklenen dosyalar çalıştırılabilir olmamalıdır. Web kök dizininin dışında saklanır; mümkünse ayrı bir alan adından servis edilir ki bir HTML dosyası yüklense bile senin kökeninde çalışmasın (XSS'e dönüşmesin).
Content-Disposition: attachment+nosniffile tarayıcıda çalıştırılması yerine indirilmesi sağlanır.- Boyut ve kaynak sınırları: istek boyutu sınırı, disk kotası ve arşiv açılıyorsa açılmış boyut sınırı (zip bomb). 12-05'teki stream disiplini burada bellek koruması sağlar.
- Erişim kontrolü indirmede de vardır: yüklenen belgeyi kimin indirebileceği A01 sorusudur; tahmin edilemez dosya adı tek başına yetmez.
09Mini alıştırma — kendi uygulamanı kendin kır
Yaklaşık 20 dakika · kendi API'n + tarayıcı; hepsi kendi makinende
- SQL enjeksiyonunu üret ve kapat. Bir uçta bilerek dize birleştirmeli
sorgu yaz,
' OR '1'='1' --ile tüm kayıtları döndür. Parametreli sorguya çevir ve aynı girdinin artık yalnızca arandığını gör. Sonra dinamik sıralama ekle: parametre kullanamadığını fark et ve beyaz listeyle çöz. - Kör enjeksiyonu gözle. Hata mesajlarını kapat ve
' AND 1=1 --ile' AND 1=2 --girdilerinde yanıtın farklılaştığını göster. "Hata mesajını gizledim, güvendeyim" cümlesinin neden yanlış olduğunu bir cümleyle yaz. - Üç XSS türünü de dene. (a) Arama sonucunda sorguyu kodlamadan bas —
yansıyan; (b) yorum alanına
<img src=x onerror=alert(1)>yaz ve başka bir tarayıcıda aç — saklanan; (c)element.innerHTML = location.hash.slice(1)yazan bir sayfa kur — DOM tabanlı. Üçünü de kapat: sunucuda çıktı kodlaması,textContent, ve zengin metin için temizleyici. - CSP'yi devreye al. Önce
Content-Security-Policy-Report-Onlyiledefault-src 'self'yayınla ve konsoldaki ihlalleri oku — kaç inline betiğin olduğunu gör. Sonranonceyaklaşımına geçip politikayı zorunlu hâle getir; (b) şıkkındaki saklanan XSS'in artık çalışmadığını doğrula. CSP'nin XSS'i "önlemediği" ama ne yaptığını yaz. - CORS'u yanlış yapılandır. Gelen
Origin'i yansıtan +credentials: trueveren bir yapılandırma kur, ikinci bir porttaki sayfadanfetch(..., {credentials:"include"})ile kimlikli veri çek ve yanıtı okuyabildiğini gör. Beyaz listeye çevirip düzelt. Bunun CSRF'den farkını bir cümlede yaz. - SSRF ve yükleme. "URL'den görsel içe aktar" ucu yaz ve
http://127.0.0.1:<kendi portun>/adminvererek sunucunun kendi iç ucunu çağırdığını gör; beyaz liste + şema kontrolü + yönlendirme takip etmeme ile kapat. Ardından yükleme ucuna.htmluzantılı bir dosya yükle ve servis edildiğinde tarayıcıda çalıştığını gör; yeni ad üretme,nosniff,Content-Disposition: attachmentve web kökü dışında saklama ile kapat.
10Kendini sına
OWASP Top 10 ne işe yarar, ne değildir? A01'in IDOR dışındaki biçimlerini say; CORS'un yanlış yapılandırılması neden CSRF'den farklı bir zafiyettir?
Gerçek zafiyet verisine dayanan, birkaç yılda bir güncellenen bir
farkındalık belgesidir; "nereye bakmalıyım" sorusuna veri temelli cevap verir.
Tam bir standart (ASVS gibi) ya da uyumluluk kontrol listesi değildir ve "bu
onu geçtim, güvenliyim" anlamına gelmez; kategoriler geniştir. Doğru kullanım, listeyi
tehdit modelinin girdi listesi yapmaktır. Sıralamanın kendisi de bilgidir:
erişim kontrolü listenin başındadır — en yaygın sorun egzotik bir kripto açığı
değil, kontrolün yapılmamış olmasıdır. A01'in biçimleri: IDOR; zorla
gezinme (menüde olmayan /admin yolunun doğrudan yazılması);
yol geçişi (../../etc/passwd); kütle atama
("rol":"yonetici"); metot atlaması (GET korunmuş, aynı işi yapan
PUT unutulmuş); CORS yanlış yapılandırması. Sonuncusu CSRF'den farklıdır:
CSRF'de saldırgan yanıtı okuyamaz, yalnız yan etki üretir. Gelen
Origin'i aynen yansıtıp Allow-Credentials: true vermek ise
herhangi bir sitenin kullanıcının çerezleriyle API'yi çağırıp yanıtı
okumasına izin verir — bu doğrudan veri hırsızlığıdır. Kural: sabit beyaz liste;
joker ile kimlik bilgisi asla birlikte kullanılmaz.
Enjeksiyonun kök sebebi nedir; parametreli sorgu neden kaçış karakterinden daha güçlüdür? "ORM kullanıyorum, SQL enjeksiyonu olmaz" cümlesinin nesi yanlıştır?
Kök sebep: veri olması gereken şeyin kod olarak
yorumlanması — girdi ile komut aynı kanaldan gidiyorsa girdi komutu değiştirir.
Parametreli sorgu yapısal olarak üstündür çünkü sorgu metni ve veri
ayrı kanallardan gider: motor önce planı kurar, sonra değerleri yerleştirir;
değerdeki tırnak veya DROP artık koddur değil veridir. Kaçış listeleri
ise her zaman eksiktir (kodlama varyasyonları, çok baytlı karakterler). ORM
cümlesi yanlıştır çünkü üç kapı açıktır: ham SQL API'leri
(FromSqlRaw/ExecuteSqlRaw), dinamik sıralama/filtreleme
için dize birleştirme ve saklı yordamın içindeki dinamik SQL. Parametre
olamayan şeyler — tablo adı, sütun adı, ASC/DESC — birleştirmeyle değil
beyaz listeyle konur (12-09'un kuralı). Ayrıca kör enjeksiyon vardır:
uygulama hata ya da veri döndürmese bile saldırgan doğru/yanlış koşullarla yanıt
farkına (boolean) ya da WAITFOR/pg_sleep ile süreye
(zaman) bakarak veriyi çıkarabilir — "hata mesajını gizledim" enjeksiyonu kapatmaz.
Aynı hatanın kabuk sürümü komut enjeksiyonudur; çözüm kabuğu hiç devreye
sokmamaktır (execFile/spawn ile ayrı argümanlar).
XSS'in üç türünü ayır. Çıktı kodlaması neden "bağlama göre"dir ve çerçevelerin kaçış kapıları nelerdir?
Yansıyan: girdi istekle gelir, yanıtta kodlanmadan geri
yazılır; saldırı bir bağlantıyla yayılır. Saklanan: girdi veritabanına yazılıp
sonra herkese servis edilir — en tehlikelisi, her ziyaretçiyi etkiler.
DOM tabanlı: sunucu hiç görmez; istemci betiği URL'den okuyup DOM'a yazar
(innerHTML = location.hash). Betik senin kökeninde çalıştığı için
HttpOnly çerez de isteğe otomatik eklenir ve CSRF jetonu sayfadan
okunur — "XSS varsa CSRF savunması anlamsızdır" cümlesinin sebebi budur.
Kodlama bağlama göredir çünkü aynı veri HTML gövdesinde, HTML özniteliğinde,
JavaScript dizesinde, URL'de ve CSS'te farklı kaçış kurallarına tabidir; özellikle
HTML kodlaması JavaScript bağlamında işe yaramaz — veri JS'e ancak JSON olarak
geçirilir, URL'de javascript: şeması engellenir. Çerçeveler varsayılan
olarak kodlar; XSS'ler kaçış kapılarından girer:
dangerouslySetInnerHTML, [innerHTML] /
bypassSecurityTrustHtml, @Html.Raw, düz
innerHTML/document.write/eval. Zorunluysa
olgun bir HTML temizleyici kullanılır; kendi düzenli ifadenle etiket temizlemek
çalışmaz.
CSP ne yapar, ne yapmaz; unsafe-inline ve nonce farkı nedir? SSRF neden kritiktir ve dosya yüklemede hangi kontroller gerekir?
CSP tarayıcıya hangi kaynaklardan kod/stil/görsel
yükleneceğini söyleyen bir başlıktır. XSS'i önlemez — asıl savunma çıktı
kodlamasıdır — ama bir XSS'in işe yaramasını engelleyebilir: enjekte edilen
betik çalışamaz ya da çaldığını dışarı gönderemez; klasik derinlemesine savunma
katmanıdır. 'unsafe-inline' yazmak politikayı büyük ölçüde
anlamsızlaştırır, çünkü enjekte edilen inline betik de çalışır; doğrusu her yanıtta
üretilen bir nonce (ya da betik hash'i) kullanmaktır.
'unsafe-eval' de kaçınılır. Mevcut uygulamada önce
Report-Only ile yayına alınıp raporlara göre sıkılaştırılır; ayrıca
frame-ancestors 'none' clickjacking savunmasını aynı başlıkta
halleder. SSRF kritiktir çünkü sunucu, saldırganın erişemediği iç ağa
erişebilir; en çarpıcı hedef bulut metadata servisidir
(169.254.169.254) — makinenin rolüne ait geçici kimlik bilgilerini
döndürür ve saldırgan bulut hesabında yetki kazanır. Savunma: alan adı/şema
beyaz listesi (kara liste yetersiz), yalnız http/https, yönlendirmeleri
takip etmemek ya da her adımda yeniden doğrulamak (DNS rebinding), çıkış
trafiğini ağ düzeyinde kısmak, metadata erişimini kapatmak ve yanıt gövdesini
kullanıcıya aynen geri vermemek. Dosya yükleme: dosya adına güvenilmez
(sunucuda yeni ad); tür uzantıyla değil içerik imzasıyla ve beyaz listeyle
doğrulanır; dosyalar web kökü dışında, tercihen ayrı bir alan adından servis
edilir ki yüklenen HTML senin kökeninde çalışmasın;
Content-Disposition: attachment + nosniff; boyut/kota ve
arşiv açılım sınırı (zip bomb); ve indirme de bir erişim kontrolü sorusudur —
tahmin edilemez ad tek başına yetmez.
11Sınav köşesi
Yazılıda nasıl sorulur
(1) OWASP Top 10 nedir? (2) Broken access control kategorisine hangi zafiyetler
girer? (3) IDOR nedir? (4) SQL injection nasıl çalışır, nasıl önlenir?
(5) Parametreli sorgu neden güvenlidir? (6) Blind SQL injection nedir?
(7) Command injection nedir? (8) XSS türlerini açıklayın. (9) Output encoding
neden bağlama göre yapılır? (10) CSP nedir, hangi direktifleri vardır?
(11) unsafe-inline neden sakıncalıdır? (12) Clickjacking nedir, nasıl
önlenir? (13) Güvenlik başlıklarını sayın ve görevlerini yazın. (14) SSRF nedir,
bulut ortamında neden kritiktir? (15) Güvenli dosya yükleme için hangi kontroller
yapılır? (16) Security misconfiguration örnekleri nelerdir?
Sözlüde nasıl anlatılır — 2 dakikalık taslak
Düzen: (1) Çerçeve — "Top 10 bir standart değil, veri temelli bir farkındalık
listesidir; ben onu tehdit modelimin girdi listesi olarak kullanırım. Sıralamanın
kendisi bilgi taşır: en başta erişim kontrolü var — sahadaki asıl sorun
egzotik açıklar değil, kontrolün hiç yapılmamış olması." (2) A01 — "IDOR'un
kardeşlerini sayarım: zorla gezinme, yol geçişi, kütle atama, metot atlaması ve
CORS'un yanlış gevşetilmesi. Sonuncusunda Origin'i yansıtıp credentials açmak,
herhangi bir sitenin kimlikli yanıtı okumasına izin verir — bu CSRF'den
farklı, doğrudan hırsızlıktır." (3) Enjeksiyon — "Kök sebep veri ile komutun aynı
kanaldan gitmesidir; parametreli sorgu kanalları ayırır, o yüzden kaçış
karakterinden kategorik olarak güçlüdür. ORM her şeyi çözmez: ham SQL, dinamik
sıralama ve saklı yordam içi dinamik SQL açık kapılardır — parametre olamayan
şeyleri beyaz listeyle koyarım." (4) XSS ve CSP — "Üç türü ayırırım; asıl savunma
bağlama göre çıktı kodlamasıdır ve çerçeveler bunu varsayılan yapar — açıklar
dangerouslySetInnerHTML gibi kaçış kapılarından girer. CSP ikinci
hattır: XSS'i önlemez, işe yaramasını engeller; unsafe-inline yerine
nonce kullanır, mevcut sisteme Report-Only ile sokarım."
(5) Kıdem vuruşu — "İki başlığı ayrıca vurgularım: SSRF, bulutta metadata
servisinden geçici kimlik bilgisi okunmasına yol açtığı için kritiktir; beyaz
liste yetmez, yönlendirmeleri de yeniden doğrularım. Ve dosya yükleme: adı
sunucu üretir, türü içerik imzasıyla doğrularım, dosyaları ayrı bir alan adından
servis ederim ki yüklenen bir HTML benim kökenimde çalışıp XSS'e dönüşmesin —
indirmenin kendisi de bir yetkilendirme sorusudur."
