Web Güvenliği: Katman Katman En İyi Uygulamalar Rehberi (2026)
Önemli bilgi
Web güvenliği katman katman sağlanır: alan adını ve DNS'i kilitleyin (registrar lock, DNSSEC, CAA), HSTS ile modern TLS'i zorunlu kılın, sıkı bir HTTP güvenlik başlıkları seti gönderin, şifreleri MFA ve hız sınırlamasının arkasında Argon2id ile hashleyin, girdiyi doğrulayıp erişim kontrolünü sunucu tarafında uygulayın, bağımlılıkları sabitleyip denetleyin, hizmet vermediğiniz her portu kapatın ve bir ihlali fark etmenize yetecek kadar log tutun. Aşağıdaki her uygulama, tam yapılandırmasıyla ve gerçekten devrede olduğunu doğrulamanın ücretsiz bir yoluyla birlikte gelir; çünkü test etmediğiniz bir güvenlik kontrolü, aslında sahip olmadığınız bir kontroldür.
Şimdi kontrol edin

Okumaya başlayın
- Web Güvenliği En İyi Uygulamaları Gerçekte Ne Anlama Gelir?
- Web Güvenliği Yığını: Korunması Gereken Altı Katman
- 1. Katman: Alan Adını ve DNS'i Kilitleyin
- 2. Katman: HTTPS ve TLS'i Doğru Yapılandırın
- 3. Katman: HTTP Güvenlik Başlıkları
- 4. Katman: Credential Stuffing'e Dayanıklı Kimlik Doğrulama
- Oturumlar, Çerezler ve CSRF
- Enjeksiyon ve XSS: Girdiyi Doğrulayın, Çıktıyı Kodlayın
- Broken Access Control: Bir Numaralı Risk
- 5. Katman: Bağımlılıklar ve Yazılım Tedarik Zinciri
- 6. Katman: Sunucu Sıkılaştırma (Portlar, Yamalar, Gizli Anahtarlar, Yedekler)
- E-posta Kimlik Doğrulama: SPF, DKIM ve DMARC
- Loglayın, İzleyin ve İhlale Karşı Plan Yapın
- Test Edin: Tarama Araçları, Sızma Testleri ve Sürekli Kontroller
- Web Güvenliği Kontrol Listesi
- Bu Rehber OWASP Top 10:2025 ile Nasıl Eşleşiyor?
- Web Güvenliği Hakkında Sıkça Sorulan Sorular
Web Güvenliği En İyi Uygulamaları Gerçekte Ne Anlama Gelir?
Web güvenliği en iyi uygulamaları, bir web sitesinin ya da web uygulamasının ele geçirilmesini, tahrif edilmesini, kendi ziyaretçilerine saldırmak için kullanılmasını veya verilerinin sessizce sızdırılmasını önleyen kontrollerin bütünüdür. Tek bir ürün ya da tek bir ayar değildir. Alan adı kayıt firmasında (registrar) başlayıp DNS, TLS, sunucunuzun gönderdiği HTTP başlıkları, oturum açma ve kullanıcı girdisini işleyen kod, üzerine inşa ettiğiniz üçüncü taraf paketler ve sunucunun kendisinden geçen, son olarak da bir şeylerin ters gittiğini size haber veren loglarla biten bir kararlar yığınıdır.
Katmanlı düşünmenin nedeni, saldırganların da öyle düşünmesidir. Verizon'un Kasım 2024 ile Ekim 2025 arasındaki 22.000'den fazla ihlali kapsayan 2026 Data Breach Investigations Report raporuna göre ihlallerin %31'i istismar edilen bir yazılım açığıyla başladı; bu oran bir yıl önce %20'ydi ve ilk kez çalınan kimlik bilgilerinin (%13) önüne geçti, kimlik avı ise %16'da sabit kaldı. Fidye yazılımı ihlallerin %48'inde görüldü (önceki yıl %44). Tek bir eksik yama, sızmış bir API anahtarı ya da hız sınırı olmayan bir yönetici sayfası yeter. Bu rehberdeki kontrollerin hiçbiri sıra dışı değildir; ihlal yaşayan siteler genellikle bir katmanı cilalarken başka bir katmanda temel önlemleri atlayanlardır.
Bu rehber dıştan içe doğru düzenlenmiştir. Her uygulama neden önemli olduğunu, tam olarak neyi yapılandıracağınızı ve nasıl doğrulayacağınızı bir komutla ya da HTTP Başlık Kontrolü veya SSL Sertifika Kontrolü gibi ücretsiz bir araçla anlatır; çünkü açık olduğuna inandığınız ama hiç doğrulamadığınız bir ayar hiçbir şeyi korumaz.
Sitenin güvenlik başlıklarını kontrol edin
Web Güvenliği Yığını: Korunması Gereken Altı Katman
Bir web sitesine yönelik her saldırı bu altı katmandan birine iner. Aşağıdaki tablo, rehberin geri kalanının haritasıdır: her katmanda ne bulunduğu, genellikle nasıl saldırıya uğradığı ve savunmanızın gerçekten yerinde olduğunu hangi ücretsiz kontrolün doğruladığı.
| Katman | Saldırganların burada yaptığı | Temel uygulamalar | Doğrulama aracı |
|---|---|---|---|
| 1. Alan adı ve DNS | Alan adını ele geçirmek, ad sunucularını değiştirmek, sahipsiz (dangling) alt alan adlarını devralmak, sahte sertifika almak | Registrar lock, MFA, DNSSEC, CAA, eski kayıtların denetimi | WHOIS Sorgulama, DNS Sağlık Kontrolü, Alt Alan Adı Bulucu |
| 2. Taşıma katmanı (TLS) | HTTP'ye düşürme (downgrade), şifrelemeyi devre dışı bırakma, eski şifre paketlerini istismar etme, süresi dolmuş sertifikalar | TLS 1.2+, HSTS (preload isteğe bağlı), otomatik yenileme | SSL Sertifika Kontrolü |
| 3. HTTP başlıkları | Script enjekte etmek (XSS), siteyi clickjacking için bir çerçeveye almak, içerik türünü tahmin ettirmek (sniffing), referrer bilgisi sızdırmak | CSP, frame-ancestors, nosniff, Referrer-Policy, Permissions-Policy | HTTP Başlık Kontrolü |
| 4. Uygulama | Credential stuffing, enjeksiyon, bozuk erişim kontrolü, CSRF, güvensiz dosya yüklemeleri | Argon2id + MFA + hız sınırlama, parametreli sorgular, sunucu tarafında yetkilendirme, SameSite çerezler | Kod incelemesi, ZAP, Şifre Güç Testi |
| 5. Bağımlılıklar | Zehirlenmiş paketler, kütüphanelerdeki bilinen CVE'ler, ele geçirilmiş CI hatları | Lockfile'lar, denetimler, sabitlenmiş sürümler, SBOM, en az yetkili token'lar | npm audit, Dependabot, Trivy |
| 6. Sunucu ve operasyon | Açık portlar, varsayılan kimlik bilgileri, eksik yamalar, yedek ve log eksikliği | Güvenlik duvarı, yalnızca anahtarla SSH, yama yönetimi, 3-2-1 yedekleme, merkezi loglama | Port Kontrolü, IP Kara Liste Kontrolü |
Yukarıdan aşağıya doğru ilerleyin. 1-3. katmanlar bir öğleden sonrada bitirebileceğiniz yapılandırmalardır ve tüm sayfaları aynı anda korur. 4-6. katmanlar ise kod inceleme ve dağıtım (deployment) sürecinizin parçası olması gereken sürekli alışkanlıklardır.
1. Katman: Alan Adını ve DNS'i Kilitleyin
Bu rehberdeki diğer her şey, alan adınızın kontrolünün hâlâ sizde olduğunu varsayar. Bir saldırgan registrar hesabınıza girebilir ya da ad sunucularınızı (nameserver) değiştirebilirse trafiğinizi istediği yere yönlendirebilir, alan adınız için geçerli bir sertifika alabilir ve size gönderilen her e-postayı okuyabilir; üstelik uygulama kodunuzun tek bir satırı bile devreye girmez. Bu yüzden alan adı ve DNS güvenliği, web güvenliğinin ilk en iyi uygulamasıdır ve neredeyse tamamen yapılandırmadan ibarettir.
Kendi alan adınızda bir WHOIS sorgulaması yaparak işe başlayın ve üç şeyi doğrulayın: durum kodları arasında clientTransferProhibited bulunmalı, bitiş tarihi bir yıldan daha uzakta olmalı ve registrar gerçekten hesabınızın bulunduğu firma olmalı. Bir şirketin alan adının eski bir yüklenicinin registrar hesabında durması şaşırtıcı derecede yaygındır. WHOIS sorgulama rehberimiz karşınıza çıkacak tüm durum kodlarını açıklar.
Registrar Lock, MFA ve Süre Bitimi Uyarıları
Alan adının, siz kilidi açıkça kaldırmadan başka bir registrar'a taşınamaması için registrar lock (transfer kilidi olarak da bilinir) özelliğini etkinleştirin ve registrar hesabının kendisinde çok faktörlü kimlik doğrulamayı (MFA) açın. Registrar hesapları, tek bir girişin alt taraftaki her şeyi kontrol etmesi nedeniyle oltalama (phishing) saldırılarının favori hedefidir. Registrar izin verdiği her yerde SMS yerine donanım anahtarı ya da kimlik doğrulayıcı uygulama kullanın.
Alan adını süresi dolmayacak bir ödeme yöntemiyle otomatik yenilemeye ayarlayın ve yine de bitiş tarihinden 60 gün önce için takvime bir hatırlatıcı ekleyin. Süresi dolan alan adı bitiş gününde kaybolmaz; ancak ek süre ve geri alma süreleri bittiğinde (.com için yaklaşık 80 güne kadar) silinir ve drop-catch hizmetleri onu serbest kaldıktan saniyeler sonra kaydeder. Alıcı, e-postanızı, trafiğinizi ve alan adınıza güvenen tüm OAuth girişlerini devralır.
- Registry lock (kayıt kuruluşu, yani registry düzeyinde manuel ve bant dışı olarak uygulanan kilit), bir işletmenin bağımlı olduğu alan adı için ek ücrete değer; ele geçirilmiş bir registrar hesabının bile ad sunucularını değiştirmesini engeller.
- Rolleri ayırın. Alan adının ücretini ödeyen kişi, alan adının sahibi olan hesap ve DNS sağlayıcısı ayrı ayrı belgelenmeli ve tek bir çalışanın e-posta kutusuna bağlı olmamalıdır.
- İletişim bilgileriniz oltalama saldırganları için bir haritaya dönüşmesin diye WHOIS gizliliğini açın ve hesapta
domains@gibi düzenli takip edilen bir rol adresi kullanın.
Bölgeyi (Zone) DNSSEC ile İmzalayın
DNSSEC, DNS bölgenizi imzalar; böylece çözümleyici (resolver) sahte yanıtları fark edebilir. Bu olmadan, bir çözümleyicinin önbelleğini zehirleyebilen saldırgan ziyaretçilerinizi sahte bir sunucuya yönlendirebilir, tarayıcıda ise alan adınız görünmeye devam eder. Yönetilen DNS sağlayıcılarının çoğu (Cloudflare, Route 53, Google Cloud DNS ve birçok kayıt kuruluşu) bunu tek bir anahtarla açar; elle yapılacak tek adım DS kaydını kayıt kuruluşunda yayımlamaktır. dig ile ya da DS kaydını ve imzaları denetleyen DNS Sağlık Kontrolü ile doğrulayın:
dig +dnssec +short yourdomain.com A
# A signed zone returns the record AND an RRSIG line:
# 203.0.113.10
# A 13 2 3600 20270115000000 20261225000000 34505 yourdomain.com. Kx3f...==
dig +short yourdomain.com DS
# A DS record at the parent zone proves the chain of trust is complete
# 2371 13 2 6A1B...C9Sertifika Verilmesini CAA ile Sınırlayın
Bir CAA kaydı (RFC 8659), sertifika otoritelerine (CA) alan adınız için hangilerinin sertifika verebileceğini söyler. Her genel CA'nın sertifika vermeden önce bu kaydı kontrol etmesi zorunludur; dolayısıyla bir CAA kaydı, başka bir CA'nın alan adı doğrulamasını kandırmayı başaran saldırgana kapıyı kapatır. Yaygın durumları üç kayıt karşılar: kimin sertifika verebileceği, kimin wildcard sertifika verebileceği ve reddedilen bir talebin nereye bildirileceği:
yourdomain.com. CAA 0 issue "letsencrypt.org"
yourdomain.com. CAA 0 issuewild ";"
yourdomain.com. CAA 0 iodef "mailto:security@yourdomain.com"Eski Kayıtları Denetleyin: Subdomain Takeover
Alt alan adı ele geçirme (subdomain takeover), bir DNS kaydı artık kullanmadığınız bir hizmeti göstermeye devam ettiğinde olur: silinmiş bir GitHub Pages sitesine, bir Azure uygulamasına, bir S3 kovasına ya da bir SaaS sağlayıcısının ana makine adına giden CNAME gibi. Terk edilen hedefi herkes kaydedip old-app.yourdomain.com adresinde sizin adınıza, üstelik geçerli bir sertifikayla içerik sunabilir. Kaydın varlığını kimse hatırlamadığı için bug bounty programlarında sık rastlanan bir bulgudur.
Alan adınızı Alt Alan Adı Bulucu ile tarayın: iki sertifika şeffaflığı günlüğü hizmetinde, Cert Spotter (güncel sertifikalar) ve crt.sh (2013'ten beri tüm sertifikalar), arama yapar, 1.000 yaygın adı dener, her adı canlı çözümler, sahipsiz kalmış CNAME'leri işaretler ve her adı hangi ana makinenin veya CDN'in çalıştırdığını gösterir. Hedefi NXDOMAIN döndüren ya da sağlayıcının “öyle bir uygulama yok” sayfasını veren her kaydı silin; tek bir adı DNS Sorgulama doğrular. Üç ayda bir tekrarlayın ve DNS kaydını silmeyi herhangi bir hizmeti kapatma sürecinin parçası yapın.
Sertifika şeffaflığı aynı zamanda erken uyarı sisteminizdir: Cert Spotter ve Cloudflare'in CT izleme özelliği, herhangi bir CA alan adınız için sertifika verdiğinde size e-posta gönderebilir. Beklenmedik bir sertifika, çoğu zaman bir DNS ya da registrar ihlalinin ilk görünür işaretidir.
2. Katman: HTTPS ve TLS'i Doğru Yapılandırın
HTTPS artık bir en iyi uygulama değil, temel koşuldur; tarayıcılar düz HTTP sayfalarını “Güvenli değil” olarak işaretler. Google ayrıca Chrome 154'ten (Ekim 2026) itibaren tarayıcının herhangi bir herkese açık siteyi düz HTTP ile açmadan önce soracağını duyurdu (Google). Güvenli bir siteyi yalnızca şifrelenmiş bir siteden hâlâ ayıran şeyler, kabul ettiğiniz TLS sürümleri, size HTTP ile hiç ulaşılıp ulaşılamayacağı ve yenilemenin, Mart 2026'da başlayan sertifika ömrü kısaltmalarından sağ çıkacak kadar iyi otomatikleştirilip otomatikleştirilmediğidir.
En Az TLS 1.2, Tercihen TLS 1.3
TLS 1.0 ve 1.1, 2021'de RFC 8996 ile resmen kullanımdan kaldırıldı ve güncel hiçbir tarayıcı bu sürümlerle bağlantı kurmuyor. Bunları sunucuda devre dışı bırakın, TLS 1.3'ü tercih edin (bilinen tüm zayıf şifre paketlerini kaldırır ve el sıkışmayı tek bir gidiş-dönüşte tamamlar) ve TLS 1.2'yi yalnızca ECDHE-ECDSA-AES128-GCM-SHA256 veya ECDHE-RSA-CHACHA20-POLY1305 gibi AEAD şifre paketleriyle kullanın.
Dışarıdan test ederken iki satır önemlidir: müzakere edilen protokol ve tam sertifika zincirinin doğrulandığı anlamına gelen Verify return code: 0. Eksik bir ara sertifika, “Chrome’da çalışıyor, curl’de ve Android’de çalışmıyor” şikâyetlerinin sık görülen bir nedenidir; SSL sertifika zinciri rehberimiz bunun nasıl düzeltileceğini gösterir, SSL Sertifika Kontrolü ise eksik zinciri doğrudan işaretler. İşte dnsrobot.net üzerinde 27 Ekim 2026 tarihinde çalıştırılan kontrol ve ardından sunucunun TLS 1.1'i reddedip reddetmediğini sınayan bir test:
echo | openssl s_client -connect dnsrobot.net:443 -servername dnsrobot.net 2>/dev/null \
| grep -E 'Protocol|Cipher|Verify return'
# New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
# Protocol: TLSv1.3
# Verify return code: 0 (ok)
# Is TLS 1.1 refused? SECLEVEL=0 lets OpenSSL 3 and later offer it at all
openssl s_client -connect example.com:443 -servername example.com -tls1_1 \
-cipher 'DEFAULT:@SECLEVEL=0' </dev/null 2>&1 | grep -E 'alert|Cipher is'
# Refused, as it should be: ...tlsv1 alert protocol version...
# New, (NONE), Cipher is (NONE)
# Still accepted (fix it): New, TLSv1.0, Cipher is ECDHE-ECDSA-AES128-SHA
# (TLSv1.0 is the cipher's version; the handshake was TLS 1.1)Şifre listeleri, kopyalanıp yapıştırılan yapılandırmaların eskidiği yerdir. Elle yazmak yerine nginx, Apache, Caddy veya HAProxy için güncel önerilen sunucu bloğunu Mozilla SSL Configuration Generator ile üretin ve çok eski istemcileri desteklemeniz gerekmedikçe “Intermediate” profilini seçin.
HSTS: Tarayıcının Bir Daha Asla HTTP Kullanmasına İzin Vermeyin
HTTP'yi HTTPS'e yönlendirmek tek başına yeterli değildir. Bir ziyaretçinin http://yourdomain.com adresine yaptığı ilk istek yine de düz metin olarak iletilir ve aynı ağdaki bir saldırgan, yönlendirmeniz gerçekleşmeden önce bu isteğe yanıt verebilir. HTTP Strict Transport Security (RFC 6797) bu sorunu çözer: tarayıcı başlığı bir kez gördükten sonra, alan adınız için gelecekteki her http:// URL'sini herhangi bir şey göndermeden önce https:// olarak yeniden yazar.
max-age değerini en az bir yıl (31536000 saniye) yapın ve tüm alt alan adları HTTPS sunduğunda includeSubDomains ekleyin. Alan adını Chrome, Firefox, Safari ve Edge'e gömen hstspreload.org üzerinden preload yaptırmak isteğe bağlıdır: listenin kendi bakımcıları artık HSTS'nin önerildiğini ama preload'un önerilmediğini söylüyor; çünkü Chrome ve Safari gezinmeleri zaten HTTPS'e yükseltiyor ve listeden çıkmak aylar sürüyor. Başlığı, HSTS'yi Mozilla HTTP Observatory testleriyle puanlayan HTTP Başlık Kontrolü ile doğrulayın.
Strict-Transport-Security: max-age=31536000; includeSubDomains47 Günlük Sertifikalar: Yenilemeyi Şimdi Otomatikleştirin
CA/Browser Forum'un SC-081 oylaması, tüm genel TLS sertifikalarının azami geçerlilik süresini aşamalı olarak kısaltıyor. İlk kısaltma 15 Mart 2026'da yürürlüğe girdi; yani bugün satın aldığınız ya da yenilediğiniz her sertifika zaten 200 günle sınırlı ve 2029'a gelindiğinde bir sertifikanın kabaca her altı haftada bir değiştirilmesi gerekecek:
| Yürürlük tarihi | Azami sertifika geçerliliği | Alan adı doğrulamasının yeniden kullanımı |
|---|---|---|
| 15 Mart 2026 öncesi | 398 gün | 398 gün |
| 15 Mart 2026 | 200 gün | 200 gün |
| 15 Mart 2027 | 100 gün | 100 gün |
| 15 Mart 2029 | 47 gün | 10 gün |
Manuel yenileme bu takvime dayanamaz. En iyi uygulama, ACME üzerinden tamamen otomatik sertifika alımıdır: certbot, acme.sh veya Caddy aracılığıyla Let's Encrypt ya da Google Trust Services veya Cloudflare, Vercel, Netlify ve çoğu hosting paneline yerleşik otomatik sertifikalar. Yenileme sürecini ihtiyaç duymadan önce test edin (certbot için certbot renew --dry-run); aramanız gereken hata, son yenilemeden bu yana eklenmiş ve artık doğrulamayı engelleyen bir CAA kaydı ya da güvenlik duvarı kuralıdır. Ne kullanırsanız kullanın, bitiş tarihini dışarıdan da izleyin: SSL Sertifika Kontrolü kalan gün sayısını gösterir; süresi dolmuş bir sertifika ise her ziyareti tam sayfa bir tarayıcı uyarısına dönüştürür.
3. Katman: HTTP Güvenlik Başlıkları
Güvenlik başlıkları, sunucunuzun tarayıcıya sayfalarınızla neler yapıp neler yapamayacağını bildirdiği talimatlardır: hangi betikler çalışabilir, sayfa bir çerçeve (frame) içine alınabilir mi, tarayıcı içerik türlerini tahmin edebilir mi ve ziyaretçinin nereden geldiği konusunda diğer sitelere ne söylemelidir. Hiçbir maliyeti yoktur, tüm sayfalara birden uygulanır ve bütün saldırı sınıflarını engeller. Ayrıca çoğu sitenin kısmen yanlış yaptığı katmandır; bu yüzden HTTP Başlık Kontrolü onları Mozilla HTTP Observatory testleriyle notlandırır. İşte github.com'un 27 Ekim 2026'da gönderdiği başlıklar, yalnızca güvenlik başlıklarına kısaltılmış hâliyle (script-src'si tek bir varlık sunucusunu ve bir betik karmasını adlandırır, 'unsafe-inline' yoktur):
curl -sI https://github.com/ | grep -iE 'strict-transport|content-security|x-frame|x-content-type|referrer-policy'
strict-transport-security: max-age=31536000; includeSubdomains; preload
x-frame-options: deny
x-content-type-options: nosniff
referrer-policy: origin-when-cross-origin, strict-origin-when-cross-origin
content-security-policy: default-src 'none'; base-uri 'self'; ... frame-ancestors 'none'; ... script-src github.githubassets.com 'sha256-6AKuI+cDd1MoUL1u4eqrA9PXmnPAkOB4h7421hPUUm0='; ...Her Sitenin Göndermesi Gereken Yedi Başlık
Bunlar, tipik bir sitede hedeflemeniz gereken değerlerdir. Bizim HTTP Başlık Kontrolü aracımızın kullandığı Mozilla HTTP Observatory puanlamasında, eksik bir CSP 25 puana, eksik bir HSTS veya çerçeveleme koruması 20'şer puana, eksik bir nosniff ise 5 puana mal olur; Referrer-Policy ve COOP, puan hâlâ 90 veya üzerindeyse bonus puan ekler. Permissions-Policy puanlanmaz (yalnızca Chromium tabanlı tarayıcılar okur), ama yine de ayarlamaya değer.
| Başlık | Önerilen değer | Neyi önler |
|---|---|---|
Strict-Transport-Security | max-age=31536000; includeSubDomains | Protokol düşürme (downgrade), HTTP üzerinden çerez hırsızlığı |
Content-Security-Policy | Nonce tabanlı script-src ve 'strict-dynamic'; object-src 'none'; base-uri 'none'; frame-ancestors 'none' | Siteler arası betik çalıştırma (XSS), veri enjeksiyonu, clickjacking |
X-Content-Type-Options | nosniff | Bir yüklemeyi çalıştırılabilir script'e dönüştüren MIME sniffing |
Referrer-Policy | strict-origin-when-cross-origin | Tam URL'lerin (token'lar, arama terimleri) üçüncü taraflara sızması |
Permissions-Policy | camera=(), microphone=(), geolocation=(), payment=() | Üçüncü taraf script'lerin güçlü tarayıcı API'lerini sessizce kullanması |
X-Frame-Options | DENY (frame-ancestors için eski tarayıcılara yönelik yedek) | CSP Level 2 desteklemeyen tarayıcılarda clickjacking |
Cross-Origin-Opener-Policy | same-origin | window.opener üzerinden pencereler arası saldırılar |
Siteyi Bozmadan Content Security Policy Uygulamak
Content Security Policy (İçerik Güvenliği Politikası), XSS'e karşı tek başına en etkili savunmadır; çünkü bir enjeksiyon hatası olsa bile enjekte edilen script'lerin çalışmasını engeller. Sorun şu ki sıkı bir politika, unuttuğunuz her satır içi (inline) script'i ya da üçüncü taraf etiketi bozar. Google'ın önerdiği ve MDN üzerinde belgelenen modern yaklaşım nonce tabanlı bir politikadır: sunucu her yanıt için rastgele bir nonce üretir, bunu bilerek oluşturduğu her script etiketine ekler ve tarayıcı geri kalan her şeyi reddeder.
Politikayı pratik kılan şey 'strict-dynamic' ifadesidir: nonce taşıyan bir script, her birinin ayrı ayrı izin listesine eklenmesi gerekmeden başka script'leri (analitik araçları, etiket yöneticileri, widget'lar) yükleyebilir; https: ve 'unsafe-inline' belirteçleri ise modern tarayıcılar tarafından yok sayılır ve yalnızca eski tarayıcılar için yedek görevi görür. Önce Content-Security-Policy-Report-Only ile devreye alın, ihlal raporlarını bir hafta izleyin, ardından zorunlu moda geçin. Next.js, Rails ve Django gibi framework'lerin yerleşik nonce desteği vardır; statik siteler bunun yerine hash tabanlı script-src kullanabilir.
Content-Security-Policy:
script-src 'nonce-r4nd0m1z3dV4lu3' 'strict-dynamic' https: 'unsafe-inline';
object-src 'none';
base-uri 'none';
frame-ancestors 'none';
form-action 'self';
report-to csp-endpoint
<!-- Only scripts carrying the nonce run; strict-dynamic lets them load their own dependencies -->
<script nonce="r4nd0m1z3dV4lu3" src="/app.js"></script>script-src 'self' https://cdn.example.com gibi bir izin listesi (allowlist) politikası hiç yoktan iyidir, ancak izin verilen bir host üzerindeki herhangi bir JSONP uç noktası ya da eski bir kütüphane bu politikayı atlatmak için kullanılabilir. Henüz nonce kullanamıyorsanız en azından object-src 'none' ve base-uri 'none' ayarlayın; bu ikisi yaygın iki atlatma yöntemini hemen kapatır.
Clickjacking: frame-ancestors ve X-Frame-Options
Clickjacking, sitenizi bir saldırganın sayfasının içinde görünmez biçimde yükler ve ziyaretçiyi göremediği bir düğmeye tıklaması için kandırır. CSP'deki frame-ancestors 'none' (kendi sayfalarınızı gömüyorsanız 'self') bunu tüm güncel tarayıcılarda önler, X-Frame-Options: DENY ise eski tarayıcıları kapsar. Bilerek gömülebilir bir widget sunuyorsanız yalnızca o yolu ve yalnızca ihtiyaç duyan kaynaklar (origin) için muaf tutun; X-Frame-Options rehberimiz, gereken sunucu kurallarını ve test sırasında karşılaşacağınız "refused to connect" hatalarını adım adım anlatır.
nosniff, Referrer-Policy, Permissions-Policy ve COOP
X-Content-Type-Options: nosniff, tarayıcının bir Content-Type değerini kendi tahminiyle değiştirmesini engeller; kullanıcının yüklediği ve HTML içeren bir "resmi" çalıştırılabilir bir sayfaya dönüştüren şey tam da budur. Referrer-Policy: strict-origin-when-cross-origin (güncel tarayıcılarda varsayılandır ama yine de açıkça ayarlayın) diğer sitelere yalnızca kaynağınızı (origin) gönderir; böylece URL'lerdeki şifre sıfırlama token'ları ve arama sorguları gizli kalır. Permissions-Policy, kullanmadığınız tarayıcı özelliklerini devre dışı bırakır; böylece ele geçirilmiş bir üçüncü taraf script kamerayı açamaz ya da konumu okuyamaz. Cross-Origin-Opener-Policy: same-origin, açtığınız sayfalara giden window.opener bağlantısını keser ve bir pencereler arası saldırı sınıfını engeller.
Kaldırılacak başlıklar da önemlidir: Server ve X-Powered-By güvenlik açığı tarayıcılarına tam yazılım sürümlerini duyurur, X-XSS-Protection ise kullanımdan kalkmıştır ve eski tarayıcılarda hatalara yol açabilir; bu yüzden onu 0 yapın ya da kaldırın. CMS Algılayıcı, herkesin yığınınız ve sürümleri hakkında sayfanın kendisinden neler öğrenebileceğini gösterir.
Başlıkları her sayfada ayrı ayrı değil, uçta (edge) bir kez ayarlayın: CDN, reverse proxy ya da framework middleware'i. Next.js'te bu, proxy veya middleware dosyasıdır; nginx'te server bağlamındaki bir add_header bloğu; Apache'de ise Header always set. Ardından her dağıtımdan sonra HTTP Başlık Kontrolü aracını yeniden çalıştırın; çünkü yeni bir framework sürümü ya da CDN ayarı başlıklardan birini sessizce düşürebilir.
4. Katman: Credential Stuffing'e Dayanıklı Kimlik Doğrulama
Saldırganlar şifreleri nadiren tek tek tahmin eder. Başka sitelerden sızdırılmış milyarlarca e-posta ve şifre çiftini sırayla dener (credential stuffing), geri kalanını da oltalama ile ele geçirirler. Bu nedenle kimlik doğrulamada en iyi uygulamanın üç parçası vardır: şifreleri, bir veritabanı sızıntısı şifre sızıntısı anlamına gelmeyecek şekilde saklamak; çalınan bir şifreyi tek başına işe yaramaz hâle getirmek ve kaba kuvvet (brute force) saldırılarını önemsiz kalacak kadar yavaşlatmak. OWASP, OWASP Top 10:2025 listesinde Authentication Failures (kimlik doğrulama hataları) kategorisini A07'ye yerleştirir.
Şifreleri Argon2id veya bcrypt ile Hashleyin
Şifreyi asla olduğu gibi saklamayın, şifrenin hızlı bir hash'ini de saklamayın. MD5, SHA-1 ve hatta SHA-256 hızlı olacak şekilde tasarlanmıştır; bu yüzden bunlardan oluşan sızdırılmış bir tablo, tek bir GPU üzerinde saniyede milyarlarca tahminle test edilebilir. Her şifre için benzersiz bir salt ile yavaş ve bellek yoğun (memory-hard) bir şifre hashleme fonksiyonu kullanın. OWASP Password Storage Cheat Sheet sırasıyla şunları önerir:
- En az 19 MiB bellek, 2 iterasyon ve 1 paralellik derecesiyle Argon2id (veya 1 iterasyonla 46 MiB).
- Argon2'nin kullanılamadığı yerlerde N = 2^17, r = 8, p = 1 ile scrypt.
- 10 veya daha yüksek bir iş faktörüyle bcrypt (72 baytlık girdi sınırına dikkat edin; daha uzun şifreleri önceden hashlemek özen gerektirir).
- Yalnızca FIPS uyumluluğunun zorunlu kıldığı yerlerde 600.000 iterasyonla PBKDF2-HMAC-SHA256.
// Node.js with the argon2 package
import argon2 from "argon2";
const hash = await argon2.hash(password, {
type: argon2.argon2id,
memoryCost: 19456, // KiB = 19 MiB
timeCost: 2,
parallelism: 1,
});
// Later, on login:
const ok = await argon2.verify(hash, submittedPassword);Maliyeti, tek bir karma işleminin giriş sunucunuzda yaklaşık 100 ila 250 ms sürmesi için ayarlayın. Gerçek bir kullanıcı bunu fark etmez, ama her CPU çekirdeğini saniyede bir avuç tahmine, üst düzey bir ekran kartını bile milyarlar yerine binlerce tahmine sınırlar. Parametreleri yükselttiğinizde başarılı girişte yeniden karmalayın; böylece eski karmalar kendiliğinden yükselir.
Gerçekten İşe Yarayan Şifre Kuralları (NIST SP 800-63B)
Çoğu sitenin hâlâ uyguladığı karmaşıklık kuralları (bir büyük harf, bir sembol, her 90 günde bir değiştirme) Summer2026! gibi tahmin edilebilir şifreler üretir ve insanları aynı şifreyi tekrar tekrar kullanmaya iter. Güncel NIST SP 800-63B yönergeleri bu kuralların yerine gerçekten önemli olanı ölçen kurallar koyar:
- MFA da zorunluysa en az 8 karakter, tek başına kullanılan bir şifre içinse en az 15 karakter; en az 64 karaktere kadar izin verin.
- Karmaşıklık kuralı yok ve zorunlu periyodik değişiklik yok; değişikliği yalnızca şifrenin ele geçirildiğine dair kanıt olduğunda isteyin.
- Her yeni şifreyi bir sızıntı listesiyle karşılaştırın (Have I Been Pwned aralık API'si bunu şifreyi göndermeden yapmanızı sağlar) ve sızdırıldığı bilinen şifreleri reddedin.
- Yapıştırmaya ve parola yöneticilerine izin verin, boşlukları ve Unicode karakterleri kabul edin ve insanların güçlü bir parola seçmesine yardımcı olan yönlendirmeler sunun; özellikle bir parolayı reddettikten hemen sonra.
Şifre Güç Testi aracımız bu ölçütlerin eski kurallardan nasıl ayrıldığını gösterir: bir parolanın adlandırılmış 8 saldırı altında ne kadar sürede kırıldığını tahmin eder, onu zayıflatan örüntüleri gösterir ve parolayı göndermeden sızıntı verilerine karşı kontrol eder; bu, kırmızı bir “sembol gerekli” uyarısından çok daha yararlı bir geri bildirimdir.
MFA ve Passkey'ler
Çok faktörlü kimlik doğrulama, çalınan bir şifreyi çıkmaz sokağa dönüştürür. MFA'yı herkese sunun; yönetici, finans ve destek rolleri için zorunlu tutun. Seçenekleri oltalamaya karşı dayanıklılıklarına göre sıralayın: passkey'ler ve FIDO2 güvenlik anahtarları oltalamayla ele geçirilemez, çünkü kimlik bilgisi gerçek kaynağınıza (origin) bağlıdır; kimlik doğrulayıcı uygulamalar (TOTP) iyidir; SMS kodları hiç yoktan iyidir ama SIM swap (SIM kartın başka bir karta taşınması) yoluyla ele geçirilebilir. Passkey'ler tüm güncel tarayıcılarda ve işletim sistemlerinde desteklenir ve şifreyi tamamen ortadan kaldırır; bu da credential stuffing'i bir kategori olarak yok eder.
Kurtarma yolunu da oturum açma kadar dikkatle koruyun: hashlenmiş olarak saklanan kurtarma kodları, 15 dakika içinde süresi dolan tek kullanımlık token'larla e-posta üzerinden sıfırlama ve güvenlik sorusu kullanmamak.
Hız Sınırlama, Hesap Kilitleme ve Bot Savunması
Oturum açma, kayıt, şifre sıfırlama ve MFA uç noktalarına IP başına ve hesap başına hız sınırlaması (rate limiting) uygulayın ve sınır aşıldığında 429 Too Many Requests yanıtını bir Retry-After başlığıyla birlikte döndürün (HTTP 429 hatası rehberimiz istemcilerin buna nasıl tepki vermesi gerektiğini anlatır). Bunu, tek bir hesapta tekrarlanan başarısız denemelerden sonra artan bir gecikme ya da geçici bir kilitle ve dağıtık saldırı alan uç noktalar için bir CAPTCHA ya da proof-of-work doğrulamasıyla birleştirin. Başarısız her girişi kaynak IP ile birlikte loglayın; böylece bir credential stuffing saldırısının örüntüsü aylar değil dakikalar içinde görünür hâle gelir.
# nginx: 5 login attempts at once, then 1 every 12 seconds, per client IP
# (limit_req sends no Retry-After header; add one on your 429 page if clients need it)
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
location = /api/login {
limit_req zone=login burst=4 nodelay;
limit_req_status 429;
proxy_pass http://app;
}"Bilinmeyen kullanıcı" ve "yanlış şifre" durumları için hata mesajlarını birebir aynı tutun ve yanıt süresini de her ikisinde eşitleyin (kullanıcı yoksa sahte bir şifreyi hashleyin). Aksi takdirde giriş formu, kayıtlı kullanıcıları tespit etmeye yarayan bir API'ye (user enumeration) dönüşür.
Oturumlar, Çerezler ve CSRF
Oturum açıldıktan sonra oturum çerezi kullanıcının ta kendisidir; bu yüzden şifreyle aynı korumayı hak eder. İşin büyük kısmını üç çerez özniteliği ve bir adlandırma öneki görür:
Secure, çerezin asla düz HTTP üzerinden gönderilmeyeceği anlamına gelir; böylece halka açık Wi-Fi ağlarında trafik dinlenerek ele geçirilemez.HttpOnly, çerezi JavaScript'e görünmez kılar; böylece bir XSS hatası onu okuyamaz.SameSite=Lax(yönetim panelleri içinStrict), çerezin siteler arası POST isteklerinde gönderilmesini önler ve CSRF saldırılarının çoğunu etkisiz hâle getirir.__Host-öneki, tarayıcının çerezi yalnızcaSecureolduğunda,Path=/içerdiğinde veDomainözniteliği taşımadığında kabul etmesini sağlar; böylece bir alt alan adı çerezin üzerine yazamaz.
Set-Cookie: __Host-session=9f1c7e2a...; Path=/; Secure; HttpOnly; SameSite=Lax; Max-Age=28800Durum değiştiren işlemlere asla GET ile erişilememelidir. /account/delete?id=42 gibi bir bağlantı, çerez bayraklarınız ne kadar iyi olursa olsun, kullanıcının ziyaret ettiği herhangi bir sayfadaki bir <img> etiketiyle tetiklenebilir.
CSRF: SameSite'ın Arkasında İkinci Savunma Hattı
Siteler arası istek sahteciliği (CSRF), oturum açmış bir tarayıcıyı başka bir sayfadan sitenize durum değiştiren bir istek göndermesi için kandırır. SameSite çerezleri yaygın senaryoyu önler, ancak GET dışındaki her istekte ikinci bir savunma bulundurun: gizli bir form alanında ya da özel bir başlıkta oturum başına bir anti-CSRF token'ı veya Origin (ya da Sec-Fetch-Site) başlığının kendi kaynağınızla eşleştiğini doğrulayan bir kontrol. Çoğu framework (Django, Rails, Laravel, Next.js server actions) bunu varsayılan olarak yapar; yapılan hata, korumayı bir API uç noktası için kapatıp ardından o uç noktayı tarayıcıdan çağırmaktır.
Oturum Kimlikleri, Rotasyon ve JWT'ler
Oturum kimliklerini en az 128 bit rastgelelikle üretin, oturum sabitleme (session fixation) saldırılarını boşa çıkarmak için kimliği oturum açıldığında ve her yetki değişikliğinde yenileyin, oturumları belirli bir hareketsizlik süresinden sonra sonlandırın ve kullanıcılara oturumları sunucu tarafında geçersiz kılan bir "tüm cihazlardan çıkış yap" düğmesi sunun. JWT'leri kısa ömürlü tutun (iptal edilebilen bir yenileme token'ı ile birkaç dakika), herhangi bir script'in okuyabileceği localStorage içinde asla saklamayın ve sızdırılmış bir imzalama anahtarını tam bir ihlal olarak ele alın; çünkü o anahtarın imzaladığı her token artık taklit edilebilir.
Enjeksiyon ve XSS: Girdiyi Doğrulayın, Çıktıyı Kodlayın
Injection (enjeksiyon, A05:2025) ve siteler arası betik çalıştırma (XSS), farklı yerlerde yapılan aynı hatadır: kullanıcıdan gelen veri, bir yorumlayıcıya (SQL, kabuk, bir LDAP sorgusu, bir HTML sayfası) sanki kodmuş gibi verilir. Çözüm de her yerde aynıdır: veriyi ve kodu birbirinden ayrı tutun ve bir komutu asla string birleştirerek oluşturmayın.
String Birleştirme Değil, Parametreli Sorgular
SQL için hazır ifadeler (prepared statements) ya da bunları üreten bir ORM kullanın; veritabanı bu durumda girdiyi, sorgunun yapısını asla değiştiremeyecek bir değer olarak ele alır. Aynı kural kabuk komutları (asla string değil, argüman dizisi geçirin), NoSQL filtreleri (kullanıcı girdisindeki {"$gt": ""} gibi operatör nesnelerini reddedin) ve dosya yolları (yolu çözümleyin ve hedeflenen dizinin altında kaldığını doğrulayın) için de geçerlidir.
// Vulnerable: the input becomes part of the query text
const rows = await db.query(`SELECT * FROM users WHERE email = '${email}'`);
// Safe: the driver sends the value separately from the query
const rows = await db.query("SELECT * FROM users WHERE email = $1", [email]);
// Python / psycopg: same idea
cur.execute("SELECT * FROM users WHERE email = %s", (email,))Çıktı Kodlama XSS'i Durdurur
Siteler arası betik çalıştırma (XSS), kullanıcının kontrol ettiği metin, yerleştiği bağlama uygun şekilde kodlanmadan bir sayfaya yazıldığında ortaya çıkar. Modern şablon motorları (React ve JSX, Vue, Jinja2, Blade, ERB) varsayılan olarak kodlama yapar; bugün XSS genellikle bu korumayı devre dışı bırakan kaçış yollarından gelir: dangerouslySetInnerHTML, v-html, |safe, innerHTML ve kullanıcı verisinden URL ya da satır içi olay işleyicileri (event handler) oluşturmak. Tam bağlama göre kodlayın ve zengin HTML'i regex yerine DOMPurify gibi bu iş için tasarlanmış bir kütüphaneyle temizleyin (sanitize).
| Verinin yerleştiği yer | Kodlama biçimi | Örnek |
|---|---|---|
| HTML gövdesi | HTML varlıkları (entities) | < karakteri <, " karakteri " olur |
| HTML özniteliği | Tırnak içindeki öznitelik için varlıklar | Özniteliği her zaman tırnak içine alın; " ve ' karakterlerini kodlayın |
| JavaScript | Script metnine enjekte etmeyin; veriyi data- öznitelikleri veya JSON içeren bir <script type="application/json"> bloğu üzerinden aktarın | Bir string içindeki </script> ifadesi \u003c/script\u003e olur |
| URL parametresi | Yüzde kodlaması (percent-encoding) | encodeURIComponent(value) |
| CSS değeri | Tamamen kaçının; sınıf adlarını bir izin listesinden seçin | Kullanıcı girdisini asla style içine yerleştirmeyin |
SSRF, Dosya Yüklemeleri ve Deserialization
Sunucu taraflı istek sahteciliği (SSRF): sunucunuz kullanıcının verdiği bir URL'yi çekiyorsa (webhook'lar, görsel proxy'leri, bağlantı önizlemeleri), bir saldırgan onu dahili hizmetlere ya da bulut metadata uç noktası 169.254.169.254 adresine yönlendirip kimlik bilgilerini okuyabilir. Önce host adını çözümleyin, özel (private) ve link-local aralıkları reddedin, yönlendirmeleri devre dışı bırakın ve bu istekleri yapan bileşenleri dahili hiçbir şeye erişemeyen bir ağ segmentine yerleştirin.
Dosya yüklemeleri: türü uzantıya ya da istemcinin gönderdiği Content-Type değerine göre değil, içeriği inceleyerek doğrulayın; bir boyut sınırı uygulayın; dosyaları web kök dizininin dışında ya da nesne depolamada, sizin ürettiğiniz rastgele bir adla saklayın ve mümkünse nosniff ve Content-Disposition: attachment ile ayrı bir kaynaktan (origin) sunun. Bir yüklemenin, web sunucusunun onu çalıştıracağı bir yere düşmesine asla izin vermeyin.
Deserialization ve toplu atama (mass assignment): güvenilmeyen veriyi, rastgele sınıflar örnekleyebilen bir formatla (Java yerel serileştirmesi, Python pickle, PHP unserialize, özel etiketli YAML) asla deserialize etmeyin; şemayla doğrulanan JSON kullanın. İstek gövdelerini açık bir alan izin listesine bağlayın; böylece bir kullanıcı, tesadüfen bu sütuna sahip bir modele POST isteğiyle "role": "admin" gönderemez.
Broken Access Control: Bir Numaralı Risk
Broken Access Control (bozuk erişim kontrolü), 2021'den beri OWASP Top 10'un zirvesinde yer alıyor ve A01:2025 olarak da bu yerini koruyor. Tek bir hata değil, bir alışkanlıktır: her istekte birinin kim olduğunu kontrol etmek (kimlik doğrulama) ama neye dokunabileceğini kontrol etmeyi (yetkilendirme) unutmak. Klasik biçimi güvensiz doğrudan nesne referansıdır (insecure direct object reference): GET /api/invoices/1042 faturanın sahibi için çalışır, ama numarayı değiştiren herkes için de çalışır.
- Varsayılan olarak reddedin. Her rota, erişim veren açık bir kural gerektirir; eksik bir kural 200 değil 403 anlamına gelir.
- Sunucuda ve nesne bazında uygulayın. Arayüzde bir düğmeyi gizlemek erişim kontrolü değildir. Toplu uç noktalar, dışa aktarmalar ve arka plan işleri dahil her okuma ve yazma işlemi, geçerli kullanıcının o kaydın sahibi olduğunu ya da kayda erişim izni bulunduğunu doğrulamalıdır.
- Yararlı olduğu yerlerde tahmin edilemez kimlikler kullanın (UUID'ler), ancak asla bunlara güvenmeyin: gizleme (obscurity) yetkilendirme değildir.
- CORS'u sıkılaştırın. Kimlik bilgileriyle birlikte
Access-Control-Allow-Origin: *kullanmak ya da isteğin gönderdiğiOrigindeğerini olduğu gibi geri yansıtmak, API'nizi kullanıcının ziyaret ettiği herhangi bir web sitesine teslim eder. - Dizin listelemeyi devre dışı bırakın,
.git,.env, yedek ve yapılandırma dosyalarını web sunucusu düzeyinde engelleyin ve yönetim panellerini herkese açık internetten uzak ya da MFA ve IP izin listelerinin arkasında tutun. - Yetkilendirme hatalarına hız sınırı uygulayın ve bunları loglayın. Tek bir oturumdan gelen ani bir 403 artışı, devam eden bir kayıt tarama (enumeration) saldırısıdır.
// Express: ownership check on every object access
app.get("/api/invoices/:id", requireAuth, async (req, res) => {
const invoice = await Invoice.findById(req.params.id);
if (!invoice || invoice.ownerId !== req.user.id) {
return res.status(404).end(); // 404, not 403: don't confirm the record exists
}
res.json(invoice);
});5. Katman: Bağımlılıklar ve Yazılım Tedarik Zinciri
Tipik bir web uygulamasındaki kodun büyük kısmı sizin yazdığınız değil, indirdiğiniz koddur. Software Supply Chain Failures'ın 2025 OWASP Top 10'da A03'te ilk kez yer almasının ve 2026 DBIR'de güvenlik açığı istismarının kimlik avını ve çalınan kimlik bilgilerini geçmesinin nedeni budur. Eylül 2025'te kimlik avına kurban giden tek bir bakımcı sayesinde chalk, debug ve haftalık toplam indirmesi iki milyarı aşan 16 npm paketine daha kripto çalan zararlı yazılım yerleştirildi; bu süre içinde sabitlenmemiş bir sürüm kuran her proje bunu otomatik olarak aldı.
- Bir lockfile commit'leyin (
package-lock.json,yarn.lock,pnpm-lock.yaml,poetry.lock,go.sum) ve CI'da kurulumunpm ciile yapın; böylece build'ler tekrarlanabilir olur ve yeni bir upstream sürüm incelenmeden içeri sızamaz. - Sürekli tarayın:
npm audit,pip-audit,bundler-audit, güncellemeler için GitHub Dependabot veya Renovate ve işletim sistemi katmanı için Trivy ya da Grype gibi bir container tarayıcısı. - Güvenlik dışı güncellemeleri birkaç gün geciktirin (Renovate'in
minimumReleaseAgeayarı); böylece zehirlenmiş bir sürüm genellikle siz benimsemeden önce kaldırılmış olur. Güvenlik yamalarını ise hemen uygulayın. - CI'daki üçüncü taraf action'ları ve script'leri bir commit SHA'sına sabitleyin ve herkese açık bir CDN'den yüklediğiniz her script'te Subresource Integrity (
integrity="sha384-...") kullanın. - CI'a en az yetkiyi verin: mümkün olan yerlerde salt okunur token'lar, uzun ömürlü gizli anahtarlar yerine kısa ömürlü OIDC kimlik bilgileri ve yalnızca bir release işiyle sınırlı yayımlama hakları.
- Build sırasında bir SBOM oluşturun (CycloneDX veya SPDX); böylece Log4Shell sınıfındaki bir sonraki CVE ortaya çıktığında "bundan etkileniyor muyuz?" sorusunu dakikalar içinde yanıtlayabilirsiniz.
# Reproducible install + audit in CI
npm ci --ignore-scripts
npm audit --audit-level=high
# Pin a GitHub Action to a commit, not a floating tag
# uses: actions/checkout@v4 <- can change underneath you
# uses: actions/checkout@<full-commit-sha> # v4.2.2
# Subresource Integrity for a CDN script (hash from: openssl dgst -sha384 -binary lib.min.js | openssl base64 -A)
<script src="https://cdn.example.com/lib.min.js"
integrity="sha384-<base64-hash>"
crossorigin="anonymous"></script>npm ci --ignore-scripts, çoğu npm kötü amaçlı yazılımının çalışmak için kullandığı kurulum zamanı script'lerini engeller; ardından script'leri yalnızca gerçekten bir build adımına ihtiyaç duyan birkaç paket için yeniden etkinleştirin.
WordPress ya da başka bir CMS kullanıyorsanız aynı kurallar, CMS ihlallerinin çoğunun başladığı yer olan eklentiler ve temalar için de geçerlidir. Çekirdeği ve her eklentiyi güncel tutun, kullanmadıklarınızı silin ve bir tarama aracının sürümleriniz hakkında neler öğrenebileceğini CMS Algılayıcı ile kontrol edin.
6. Katman: Sunucu Sıkılaştırma (Portlar, Yamalar, Gizli Anahtarlar, Yedekler)
Altındaki sunucu SSH'ta şifreyle girişe izin veriyorsa, herkese açık bir portta veritabanı çalıştırıyorsa ya da kurulduğu günden beri yama almamışsa uygulama katmanının hiçbir önemi kalmaz. Sunucu tarafındaki en iyi uygulamalar sıkıcıdır ve fidye yazılımları tam da buradan içeri girer.
Hizmet Vermediğiniz Her Portu Kapatın
Herkese açık bir web sunucusunda 80 ve 443 numaralı portların açık olması, SSH'ın ise yalnızca kendi IP aralığınızdan erişilebilir olması gerekir. Veritabanları (3306, 5432, 27017), Redis (6379), Elasticsearch (9200), yönetim panelleri ve metrik uç noktaları yalnızca localhost'a ya da özel bir ağa bağlanmalıdır. Her değişiklikten sonra dışarıdan Port Kontrolü ile kontrol edin; çünkü bir saldırganın gördüğü tablo budur ve bulut güvenlik gruplarını yanlış yorumlamak kolaydır.
# Ubuntu: default-deny firewall, allow only web + SSH from your office range
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow from 203.0.113.0/24 to any port 22 proto tcp
sudo ufw enable # check your own IP is in that range first, or you lock yourself out
# SSH: keys only, no root password login, in a drop-in that sshd reads first
printf 'PasswordAuthentication no\nPermitRootLogin prohibit-password\n' \
| sudo tee /etc/ssh/sshd_config.d/00-hardening.conf
sudo sshd -T | grep -E '^(passwordauthentication|permitrootlogin) ' # what sshd will really use
sudo systemctl reload sshUbuntu ve Debian'da sshd, /etc/ssh/sshd_config.d/ içindeki dosyaları sshd_config'in geri kalanından önce okur ve her ayar için okuduğu ilk değer geçerli olur. Bu yüzden yukarıdaki komutlar 00-hardening.conf adlı bir drop-in yazar: ana dosyanın daha aşağısındaki bir düzenleme, PasswordAuthentication yes diyen bir bulut imajının drop-in'ine yenilir. Oturumu kapatmadan önce sonucu sudo sshd -T ile doğrulayın. Port Kontrolü aracında güvenlik duvarınızın düşürdüğü port Filtreli (yanıt yok), üzerinde hiçbir şeyin dinlemediği port ise Kapalı görünür: ikisi de sorun değildir, düzeltilmesi gereken Açık olandır.
Yamaları Düzenli Uygulayın, Gizli Anahtarları Koddan Uzak Tutun
İşletim sistemi için otomatik (gözetimsiz) güvenlik güncellemelerini etkinleştirin, çalışma ortamınızın (runtime) ve framework'ünüzün güvenlik bültenlerine abone olun ve internete açık herhangi bir bileşendeki kritik bir CVE'yi aynı gün çözülmesi gereken bir iş olarak ele alın. Hizmetleri yetkisiz kullanıcılarla, container'larda ya da systemd sandboxing ile çalıştırın; böylece ele geçirilen bir süreç tüm makineyi okuyamaz.
Gizli anahtarlar (secrets: veritabanı şifreleri, API anahtarları, imzalama anahtarları) asla depoda (repository), bir Docker imaj katmanında ya da istemci tarafı JavaScript'te yer almamalıdır. Bunları dağıtım anında enjekte edilen ortam değişkenlerinden ya da bir secrets manager'dan yükleyin, erişimi olan biri ayrıldığında değiştirin (rotate) ve depo geçmişini gitleaks gibi bir araçla tarayın; çünkü bir kez commit'lenen bir anahtar, commit kaldırılsa bile sonsuza dek ele geçirilmiş sayılır.
Fidye Yazılımına Dayanıklı Yedekler ve Önde Bir CDN
3-2-1 kuralını uygulayın: üç kopya, iki farklı ortamda, biri de şirket dışında; ayrıca en az bir kopyayı değiştirilemez (immutable) ya da çevrimdışı yapın ki sunucuya ulaşan bir fidye yazılımı yedekleri de şifreleyemesin. Yedekleri şifreleyin, veritabanını ve yüklemeler dizinini dahil edin ve en önemlisi düzenli aralıklarla geri yüklemeyi test edin. Kimsenin geri yükleme yapmadığı bir yedek plan değil, bir umuttur. Bir olayın kısa bir kesinti mi yoksa şirketi bitiren bir felaket mi olacağına kurtarma süresi karar verir.
Kaynak sunucunun önüne bir CDN veya WAF (Cloudflare, Fastly, WAF'lı AWS CloudFront ya da barındırıcınızın eşdeğeri) koyun. Hacimsel DDoS'u emer, yaygın enjeksiyon yükleri ve kötü botlar için yönetilen kurallar uygular, kaynak IP'nizi gizler ve uygulamaya dokunmadan hız sınırı ile coğrafi kurallar uygulayabileceğiniz bir yer sağlar. Ardından kaynağın güvenlik duvarını, 443 numaralı porta doğrudan yalnızca CDN'in IP aralıkları ulaşabilecek şekilde kısıtlayın; aksi hâlde saldırganlar onu basitçe atlar. Hosting Kontrol Aracı, bir sitenin önünde hangi CDN'in durduğunu ve arkasındaki barındırıcı hakkında kamuya açık kanıtların ne söylediğini gösterir.
E-posta Kimlik Doğrulama: SPF, DKIM ve DMARC
Web güvenliği, parola sıfırlamalarınızı, faturalarınızı ve destek yanıtlarınızı taşıyan e-postayı da kapsar. SPF, DKIM ve DMARC olmadan herkes billing@yourdomain.com adresiyle posta gönderebilir; Google ve Yahoo, Şubat 2024'ten beri toplu göndericilerden üçünü de istiyor, Microsoft da Mayıs 2025'ten beri Outlook.com için aynısını yapıyor. Tam set üç DNS TXT kaydıdır:
yourdomain.com. TXT "v=spf1 include:_spf.google.com -all"
google._domainkey.yourdomain.com. TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkq..."
_dmarc.yourdomain.com. TXT "v=DMARC1; p=reject; rua=mailto:dmarc@yourdomain.com; adkim=s; aspf=s"DMARC p=reject aynı zamanda bir marka koruma kontrolüdür: bir oltalama kampanyasının tam alan adınızı Kimden (From) satırına koymasını engelleyen tek şey odur. Toplu raporlar (rua=) bunu kimin denediğini size gösterir.
DMARC'a rapor toplamak için p=none ile başlayın, tüm meşru göndericiler (pazarlama platformu, yardım masası, CRM) hizalamayı geçtiğinde p=quarantine, ardından p=reject değerine geçin. Posta sunucularınıza şifreli teslimi zorunlu kılmak için MTA-STS ve TLS-RPT kayıtları ekleyin. Hiç posta göndermeyen ve almayan alan adlarında null MX (MX 0 .), v=spf1 -all ve p=reject içeren bir DMARC kaydı yayımlayın: null MX yalnızca alan adının posta kabul etmediğini söyler, alıcıların sahteciliği reddetmesini sağlayan SPF ve DMARC'tır. Her kaydı SPF Kayıt Kontrolü, DKIM Kontrolü ve DMARC Kontrolü ile doğrulayın; teslim edilebilirlik düşerse gönderici IP'lerinizi IP Kara Liste Kontrolü ile engelleme listelerine karşı kontrol edin.
Loglayın, İzleyin ve İhlale Karşı Plan Yapın
OWASP 2025'in on kategorisinden ikisi bir hatadan sonra olanlarla ilgilidir: Security Logging and Alerting Failures (güvenlik loglama ve uyarı hataları, A09) ve yeni Mishandling of Exceptional Conditions (istisnai durumların hatalı ele alınması, A10). Tipik bir ihlal hâlâ aylarca fark edilmeden kalıyor; çünkü kanıtlar ya hiç kaydedilmemiştir ya da kaydedilmiş ama kimse bakmamıştır.
- Güvenlik olaylarını bağlamıyla birlikte loglayın: her başarılı ve başarısız giriş, MFA değişiklikleri, şifre sıfırlamaları, yetki değişiklikleri, erişim kontrolü retleri, girdi doğrulama hataları ve yönetici işlemleri; her biri zaman damgası, kullanıcı kimliği, kaynak IP ve user agent bilgisiyle.
- Gizli bilgileri asla loglamayın: şifreler, oturum token'ları, tam kart numaraları, API anahtarları. Bunları her çağrı noktasında ayrı ayrı değil, loglama katmanında maskeleyin.
- Logları sunucunun dışına gönderin; en az 90 günlük saklama süresine sahip merkezi bir depoya (CloudWatch, Loki, Elastic, bir SIEM) aktarın ki root yetkisi ele geçiren bir saldırgan izlerini silemesin.
- Tek tek olaylara değil, örüntülere göre uyarı üretin: bir dakikada 50 başarısız giriş, tek bir oturumdan ani bir 403 artışı, mesai saatleri dışında oluşturulan yeni bir yönetici hesabı, sizin talep etmediğiniz hâlde alan adınız için verilmiş bir sertifika.
- Hata durumunda erişimi kapatın (fail closed): bir alt sistem kontrolü (kimlik doğrulama servisi, hız sınırlayıcı, WAF) hata verdiğinde isteği reddedin. A10'un var olma nedeni, pek çok sistemin, engellemesi gereken kontrol bir istisna fırlattığında erişim izni vermesidir.
- Dışarıdan izleyin: çalışma süresi (uptime), sertifika bitiş tarihi, DNS değişiklikleri, kara liste kayıtları ve başlık gerilemeleri. Her dağıtımdan sonra SSL Sertifika Kontrolü, HTTP Başlık Kontrolü ve DNS Sağlık Kontrolü aracını (yetki devri, ad sunucuları, DNSSEC ve SPF/DMARC üzerinde 40 kontrol) yeniden çalıştırın.
Olay Müdahale Planını İhtiyaç Duymadan Önce Yazın
Kimin nöbetçi olacağına, tüm kimlik bilgilerinin nasıl değiştirileceğine, sitenin salt okunur moda nasıl alınacağına, temiz yedeklerin nerede olduğuna ve hangi düzenleyicinin veya müşterilerin kaç saat içinde bilgilendirilmesi gerektiğine (GDPR kapsamında 72 saat) önceden karar verin. Yılda bir kez masa başı tatbikat yapın. Prova edilmiş bir plan, günler süren doğaçlamayı bir kontrol listesine dönüştürür.
/.well-known/security.txt adresinde bir security.txt dosyası yayımlayın (RFC 9116); içinde zorunlu iki alan olan Contact: satırı ve Expires: tarihi bulunsun (Encryption: anahtarı isteğe bağlıdır). Sitenizde bir hata bulan araştırmacılar önce oraya bakar; bu dosya yoksa bildirecek kimseyi bulamayabilirler.
Test Edin: Tarama Araçları, Sızma Testleri ve Sürekli Kontroller
Yukarıdaki her kontrol doğrulanabilir ve bu doğrulama, zamanla aşınmaması için mümkün olan her yerde otomatikleştirilmelidir. Ücretsiz ve anlık olandan periyodik ve ücretli olana doğru makul bir basamak dizisi:
| Kontrol | Araç | Ne sıklıkla |
|---|---|---|
| TLS yapılandırması, zincir, bitiş tarihi | SSL Sertifika Kontrolü, SSL Labs, testssl.sh | Her sertifika veya sunucu değişikliğinden sonra; bitiş tarihi günlük |
| Güvenlik başlıkları ve CSP | HTTP Başlık Kontrolü, MDN HTTP Observatory | Her dağıtımdan sonra (CI'a ekleyin) |
| Açık portlar | Port Kontrolü, ağınızın dışından nmap | Her güvenlik duvarı veya bulut değişikliğinden sonra |
| DNS, DNSSEC, e-posta kimlik doğrulama | DNS Sağlık Kontrolü, DMARC Kontrolü | Aylık ve her DNS düzenlemesinden sonra |
| Eski alt alan adları | Alt Alan Adı Bulucu | Üç ayda bir ve her hizmet kapatmada |
| Bilinen açıkları olan bağımlılıklar | npm audit, Dependabot, Trivy | Her build'de |
| Kod düzeyindeki açıklar (SAST) | Semgrep, CodeQL | Her pull request'te |
| Çalışma zamanındaki web açıkları (DAST) | ZAP, Nuclei | Staging ortamına karşı haftalık |
| Yetkilendirme ve iş mantığı | Manuel sızma testi veya bug bounty programı | Yılda bir ve büyük özelliklerden sonra |
Tarama araçları enjeksiyon, başlıklar ve güncelliğini yitirmiş bileşenler konusunda iyi, yetkilendirme ve iş mantığı konusunda ise zayıftır; bu yüzden para ya da kişisel veri işleyen her sistem için yılda en az bir insan eliyle yapılan test bütçeleyin. Düzeltmeleri maruziyete göre önceliklendirin: kimliği doğrulanmamış bir kullanıcının internetten istismar edebileceği her şey önce gelir.
Web Güvenliği Kontrol Listesi
Bunu projenizin README dosyasına ya da iş takip sisteminize kopyalayın. Her satır yukarıdaki uygulamalardan biridir ve yapıldı ya da yapılmadı olarak işaretlenebilecek şekilde ifade edilmiştir; son sütun kanıttır.
| Katman | Uygulama | Tamamlanma ölçütü |
|---|---|---|
| Alan adı | Registrar hesabında registrar lock ve MFA; otomatik yenileme açık | WHOIS'te clientTransferProhibited görünüyor; bitiş tarihi 12 aydan daha uzakta |
| DNS | DNSSEC imzalı; yalnızca sizin CA'larınızı listeleyen CAA kaydı | dig +dnssec RRSIG döndürüyor; üst bölgede DS kaydı mevcut |
| DNS | Sahipsiz (dangling) CNAME veya A kaydı yok | Alt Alan Adı Bulucu'daki her host adı sizin kontrol ettiğiniz bir hedefe çözümleniyor |
| TLS | Yalnızca TLS 1.2+, TLS 1.3 tercih ediliyor, tam zincir sunuluyor | SSL Sertifika Kontrolü: zincir tam, TLS 1.0/1.1 reddediliyor |
| TLS | Bir yıllık max-age ve includeSubDomains ile HSTS (preload isteğe bağlı) | HTTP Başlık Kontrolü HSTS testini geçiyor |
| TLS | Yenileme ACME ile otomatik; bitiş tarihi izleniyor | certbot renew --dry-run başarılı; 14 gün kala uyarı ayarlı |
| Başlıklar | CSP (nonce tabanlı), frame-ancestors, nosniff, Referrer-Policy, Permissions-Policy | HTTP Başlık Kontrolü notu A veya A+ |
| Kimlik doğrulama | Argon2id veya bcrypt ile hashleme; NIST şifre kuralları; sızıntı listesi kontrolü | Tek bir hash 100 ila 250 ms sürüyor; karmaşıklık kuralı yok |
| Kimlik doğrulama | MFA herkese sunuluyor, yöneticiler için zorunlu; passkey desteği var | İkinci faktör olmadan yönetici girişi imkânsız |
| Kimlik doğrulama | Giriş, sıfırlama ve MFA uç noktalarında IP başına ve hesap başına hız sınırı | Tek bir IP'den art arda altı deneme: altıncısı 429 döndürüyor |
| Oturumlar | Secure, HttpOnly ve SameSite özellikli __Host- çerezi; kimlik girişte yenileniyor | Çerez öznitelikleri DevTools'ta görünüyor; girişten sonra eski oturum geçersiz |
| Girdi | Her yerde parametreli sorgular; çıktı bağlama göre kodlanıyor; yüklemeler içeriğe göre doğrulanıyor | Kod aramasında string birleştirmeyle oluşturulmuş sorgu yok; XSS yükleri düz metin olarak görüntüleniyor |
| Erişim kontrolü | Varsayılan olarak reddeden yönlendirme; nesne bazında sahiplik kontrolleri; sıkı CORS | Başka bir kullanıcının kimlikleriyle yeniden oynatılan istekler 404 veya 403 döndürüyor |
| Bağımlılıklar | Lockfile commit'lenmiş; npm ci; CI'da denetim; action'lar SHA'ya sabitlenmiş; CDN script'lerinde SRI | Yüksek önem dereceli bir CVE'de build başarısız oluyor |
| Sunucu | Yalnızca 80 ve 443 herkese açık; SSH yalnızca anahtarla; otomatik güvenlik güncellemeleri; gizli anahtarlar ortam değişkenlerinde veya vault'ta | Port Kontrolü 3306 ve 6379 numaralı portları kapalı ya da filtreli gösteriyor; 22 de kendi aralığınızın dışından öyle görünüyor |
| Yedekler | Biri değiştirilemez olan 3-2-1 yedekleme; geri yükleme test edilmiş | Son başarılı geri yükleme testi son 90 gün içinde |
| E-posta | SPF -all, DKIM, DMARC p=reject, MTA-STS | DMARC Kontrolü başarılı; toplu raporlar geliyor |
| İzleme | Kimlik doğrulama ve yetkilendirme olayları merkezi olarak loglanıyor; örüntülere göre uyarılar; harici çalışma süresi, sertifika ve DNS izleme | Test uyarısı tetiklendi ve ulaştı |
| Müdahale | Yazılı olay müdahale planı; security.txt yayımlanmış; masa başı tatbikatı yapılmış | Plan son 12 ay içinde gözden geçirilmiş |
Bu Rehber OWASP Top 10:2025 ile Nasıl Eşleşiyor?
OWASP Top 10, web uygulaması riskleri konusunda en çok atıf yapılan listedir; 2025 sürümü sıralamayı değiştirdi ve iki yeni kategori ekledi. Bir müşteri, denetçi ya da uyumluluk çerçevesi bu listeyi nasıl karşıladığınızı sorarsa, bu rehberdeki uygulamalarla eşleşme tablosu şudur:
| OWASP Top 10:2025 | Bu rehberdeki uygulamalar |
|---|---|
| A01 Broken Access Control | Varsayılan olarak reddetme, nesne bazında kontroller, sıkı CORS, yönetim panellerinin kilitlenmesi |
| A02 Security Misconfiguration | Güvenlik başlıkları, HSTS, kapalı portlar, kaldırılmış sürüm başlıkları, kapalı dizin listeleme |
| A03 Software Supply Chain Failures (yeni) | Lockfile'lar, denetimler, sabitlenmiş action'lar, SRI, SBOM, en az yetkili CI |
| A04 Cryptographic Failures | TLS 1.2+ ve 1.3, HSTS, Argon2id, gizli anahtar yönetimi, şifrelenmiş yedekler |
| A05 Injection | Parametreli sorgular, çıktı kodlama, CSP, yükleme doğrulama |
| A06 Insecure Design | Katman başına tehdit modeli, hata durumunda kapanan (fail-closed) varsayılanlar, tasarımdan itibaren hız sınırlama |
| A07 Authentication Failures | NIST şifre kuralları, sızıntı kontrolleri, MFA ve passkey'ler, oturum kimliği yenileme |
| A08 Software or Data Integrity Failures | SRI, imzalı ve sabitlenmiş bağımlılıklar, güvenli deserialization |
| A09 Security Logging and Alerting Failures | Merkezi loglama, örüntü tabanlı uyarılar, harici izleme |
| A10 Mishandling of Exceptional Conditions (yeni) | Hata durumunda kapanma (fail closed), tek tip hata yanıtları, kullanıcılara stack trace gösterilmemesi |
OWASP'ın ASVS'si (Application Security Verification Standard, yani Uygulama Güvenliği Doğrulama Standardı), aynı içeriği denetimler için numaralandırılmış bir kontrol listesine dönüştürür. Seviye 1, herkese açık her site için gerçekçi bir hedeftir; kişisel veya finansal veri işleyen her şey içinse Seviye 2 hedeflenmelidir.
Sitenizin güvenlik başlıklarını saniyeler içinde kontrol edin
DNS Robot'un ücretsiz HTTP Başlık Kontrolü aracı, herhangi bir URL'nin yanıt başlıklarını sunucunun gönderdiği hâliyle gösterir ve güvenlik başlıklarını Mozilla HTTP Observatory testleriyle notlandırır; eksik olan her biri için çözümü de verir. Kayıt gerekmez.
Kaynaklar
- 2026 Data Breach Investigations Report, Verizon
- OWASP Top 10:2025, OWASP
- Password Storage Cheat Sheet, OWASP
- SP 800-63B-4: Authentication and Authenticator Management, NIST
- Ballot SC-081v3: reducing certificate validity and data reuse periods, CA/Browser Forum
- HTTPS by default, Google
- RFC 9116: A File Format to Aid in Security Vulnerability Disclosure, IETF
Web Güvenliği Hakkında Sıkça Sorulan Sorular
Web güvenliği için en önemli uygulamalar nelerdir?
OWASP Top 10 nedir ve 2026'da hâlâ önemli mi?
Her web sitesi hangi HTTP güvenlik başlıklarını göndermeli?
HTTPS bir web sitesini güvenli hâle getirmek için yeterli mi?
Kullanıcı şifreleri nasıl saklanmalı?
Content Security Policy (CSP) nedir, sitemde olmalı mı?
Web sitemin güvenliğini nasıl kontrol ederim?
TLS sertifikalarının süresi neden kısalıyor?
Web sitemin bağımlılıklarını ne sıklıkla güncellemeliyim?
Küçük web siteleri gerçekten saldırıya uğrar mı?
İlgili Makaleler
İlgili Araçlar
HTTP Başlık Kontrolü
HTTP yanıt başlıklarını ve güvenlik başlıkları derecelendirmesini analiz edin
SSL Sertifika Kontrolü
SSL sertifika geçerliliğini ve güvenlik ayrıntılarını doğrulayın
Port Kontrolü
Port bağlantısını ve servis kullanılabilirliğini test edin
DNS Sağlık Kontrolü
DNS notu: yetki devri, ad sunucuları, SOA, DNSSEC ve e-posta için 40 kontrol
DMARC Sorgulama
Alan adının DMARC politikası ve hizalama ayarlarını kontrol edin
Alt Alan Adı Bulucu
Herhangi bir alan adının tüm alt alan adlarını keşfedin



