Web Güvenliği: Katman Katman En İyi Uygulamalar Rehberi (2026)

Advertisement
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.
Katmanlar hâlinde düşünmenin nedeni, saldırganların da böyle düşünmesidir. Verizon'un 2026 Veri İhlali Araştırmaları Raporu (DBIR), ihlallerin %31'inin artık istismar edilen bir yazılım açığıyla başladığını ortaya koydu; bu yöntem ilk kez çalınan kimlik bilgilerini geride bırakarak en yaygın giriş yolu oldu. Aynı rapora göre tüm ihlallerin %48'inde fidye yazılımı (ransomware) var. Tek bir eksik yama, sızdırılmış bir API anahtarı ya da hız sınırlaması olmayan bir yönetim sayfası yeterlidir. Bu rehberdeki kontrollerin hiçbiri egzotik değildir; ihlal edilen siteler genellikle bir katmanı cilalarken diğerinde temel adımları atlayanlardır.
Bu rehber dışarıdan içeriye doğru düzenlenmiştir. Her uygulama için neden önemli olduğunu, tam olarak neyi yapılandırmanız gerektiğini ve bunu nasıl doğrulayacağınızı bir komut ya da ücretsiz bir araçla anlatıyoruz; çünkü HTTP başlık kontrollerinde ve SSL kontrollerinde en sık gördüğümüz hata kötü bir karar değil, birinin açık olduğuna inandığı ama hiç doğrulamadığı bir ayardır.
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 Sorgulama, 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+, preload ile HSTS, 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, OWASP 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ü, Alan Adı Sağlık Kontrolü |
Advertisement
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 önceye bir takvim hatırlatıcısı ekleyin. Süresi dolan alan adları, drop-catch servisleri tarafından saatler içinde kapılır; alıcı da 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 (zone) imzalar; böylece bir çözümleyici (resolver) sahte yanıtları tespit edebilir. DNSSEC olmadan, bir çözümleyicinin önbelleğini zehirleyebilen (cache poisoning) bir saldırgan, tarayıcıda hâlâ sizin alan adınız görünürken ziyaretçilerinizi sahte bir sunucuya gönderebilir. Yönetilen DNS sağlayıcılarının çoğu (Cloudflare, Route 53, Google Cloud DNS ve birçok registrar) DNSSEC'i tek bir tıklamayla açar; tek manuel adım, DS kaydını registrar'ınızda yayımlamaktır. Sonucu dig ile ya da Alan Adı Sağlık Kontrolü içindeki DNSSEC kontrolüyle 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 20261015000000 20260924000000 34505 yourdomain.com. Kx3f...==
dig +short yourdomain.com DS
# A DS record at the parent zone proves the chain of trust is complete
# 34505 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
Subdomain takeover (alt alan adının ele geçirilmesi), bir DNS kaydı hâlâ kullanmayı bıraktığınız bir hizmeti gösterdiğinde gerçekleşir: silinmiş bir GitHub Pages sitesine, bir Azure uygulamasına, bir S3 bucket'ına ya da bir SaaS sağlayıcısının host adına işaret eden bir CNAME gibi. Terk edilmiş hedefi herkes kaydedebilir ve ardından old-app.yourdomain.com üzerinde, geçerli bir sertifikayla birlikte sizin adınıza içerik sunabilir. Kimse kaydın varlığını hatırlamadığı için bu, bug bounty programlarında en sık rastlanan bulgulardan biridir.
Alan adınızı, sertifika şeffaflığı (Certificate Transparency) loglarını okuyan Alt Alan Adı Bulucu ile tarayın; böylece bugüne kadar sertifika verilmiş her host adını görürsünüz. Ardından her birini bir DNS sorgulaması ile çözümleyin ve hedefi NXDOMAIN ya da bir sağlayıcının "no such app" sayfasını döndüren tüm kayıtları silin. Bunu üç ayda bir tekrarlayın ve DNS kaydını silmeyi, herhangi bir hizmeti devreden çıkarma sürecinin standart bir adımı hâline getirin.
2. Katman: HTTPS ve TLS'i Doğru Yapılandırın
HTTPS artık bir en iyi uygulama değil, temel gerekliliktir; tarayıcılar düz HTTP sayfalarını "Güvenli değil" olarak işaretler. Güvenli bir siteyi yalnızca şifrelenmiş bir siteden hâlâ ayıran uygulamalar şunlardır: kabul ettiğiniz TLS sürümleri, size ulaşmak için HTTP'nin herhangi bir şekilde kullanılıp kullanılamayacağı ve yenilemenin, Mart 2026'da başlayan sertifika ömrü kısaltmalarını atlatacak kadar iyi otomatikleştirilip otomatikleştirilmediği.
Advertisement
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ığını gösteren Verify return code: 0. Eksik bir ara sertifika, "Chrome'da çalışıyor, curl'de ve Android'de hata veriyor" şikâyetlerinin en yaygın nedenidir; SSL sertifika zinciri rehberimiz bunun nasıl düzeltileceğini gösterir, SSL Sertifika Kontrolü de eksik zinciri doğrudan işaretler. İşte dnsrobot.net üzerinde çalıştırılan kontrol:
echo | openssl s_client -connect dnsrobot.net:443 -servername dnsrobot.net 2>/dev/null \
| grep -E 'Protocol|Cipher|Verify return'
# Protocol : TLSv1.3
# Cipher : TLS_AES_256_GCM_SHA384
# Verify return code: 0 (ok)
# Confirm the old versions are refused:
openssl s_client -connect dnsrobot.net:443 -tls1_1 2>&1 | grep -iE 'alert|no protocols'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.
En az bir yıllık (31536000 saniye) bir max-age kullanın, tüm alt alan adlarınız HTTPS sunduğunda includeSubDomains ekleyin ve ardından alan adınızı hstspreload.org adresine göndererek Chrome, Firefox, Safari ve Edge'e sabit kodlanmış olarak dahil edilmesini sağlayın. Preload, ilk ziyaret açığını tamamen kapatır. Başlığı, HSTS'yi A'dan F'ye güvenlik puanının bir parçası olarak notlandıran HTTP Başlık Kontrolü ile doğrulayın.
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload47 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 neleri yapıp neleri yapamayacağını bildirdiği talimatlardır: hangi script'lerin çalışabileceği, sayfanın bir çerçeve (frame) içine alınıp alınamayacağı, tarayıcının içerik türlerini tahmin edip edemeyeceği ve bir ziyaretçinin nereden geldiği konusunda diğer sitelere ne söylemesi gerektiği. Hiçbir maliyeti yoktur, tüm sayfalara aynı anda uygulanır ve bütün saldırı sınıflarını engeller. Aynı zamanda çoğu sitenin kısmen yanlış yaptığı katmandır; HTTP Başlık Kontrolü aracının bunları notlandırmasının nedeni de budur. İşte dnsrobot.net'in gönderdiği başlıklar, yalnızca güvenlik başlıklarına indirgenmiş hâliyle:
curl -sI https://dnsrobot.net/ | grep -iE 'strict-transport|content-security|x-frame|x-content-type|referrer-policy|permissions-policy'
strict-transport-security: max-age=31536000; includeSubDomains; preload
content-security-policy: default-src 'self'; script-src 'self' ... https://*.googletagmanager.com; frame-ancestors 'none'; base-uri 'self'; form-action 'self'
x-frame-options: DENY
x-content-type-options: nosniff
referrer-policy: strict-origin-when-cross-origin
permissions-policy: camera=(self), microphone=(), geolocation=(), payment=(), usb=()Her Sitenin Göndermesi Gereken Yedi Başlık
Tipik bir site için hedeflemeniz gereken değerler bunlardır. İlk beşi notunuzu belirleyen başlıklardır; son ikisi ise diğerleri yerine oturduktan sonra ekleyebileceğiniz zahmetsiz eklemelerdir.
| Başlık | Önerilen değer | Neyi önler |
|---|---|---|
Strict-Transport-Security | max-age=31536000; includeSubDomains; preload | 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>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ılması gereken başlıklar da önemlidir: Server ve X-Powered-By, güvenlik açığı tarama araçlarına tam yazılım sürümlerinizi ilan eder; X-XSS-Protection ise kullanımdan kaldırılmıştır ve eski tarayıcılarda hatalara yol açabilir, bu yüzden 0 olarak ayarlayın ya da tamamen kaldırın. CMS Algılayıcı, bir tarama aracının yalnızca başlıklara bakarak altyapınız hakkında neler öğrendiğini gösterir.
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.
Advertisement
Ş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);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 şifre yöneticilerine izin verin, boşlukları ve Unicode karakterleri kabul edin ve kurallara değil entropiye dayalı bir şifre gücü göstergesi sunun.
Şifre Güç Testi aracımız bu ölçütlerin eski kurallardan nasıl ayrıldığını gösterir: kırılma süresini entropi ve örüntü tespitiyle tahmin eder ve şifreyi 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 per minute per client IP
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;
}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=28800CSRF: 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.
Advertisement
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 belki %5'ini siz yazarsınız, %95'ini ise indirirsiniz. Software Supply Chain Failures (yazılım tedarik zinciri hataları) kategorisinin 2025 OWASP Top 10'a doğrudan A03 olarak girmesinin ve 2026 DBIR'da güvenlik açığı istismarının çalınan kimlik bilgilerini geride bırakmasının nedeni budur. Eylül 2025'te oltalamaya kurban giden tek bir paket geliştiricisi, chalk, debug ve 16 npm paketine daha (toplamda haftada iki milyardan fazla indiriliyorlar) kripto para çalan kötü amaçlı yazılım yerleştirdi; bu zaman aralığında sabitlenmemiş bir sürüm yükleyen her proje, zararlı kodu otomatik olarak projesine çekti.
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>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
# SSH: keys only, no root password login
sudo sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
sudo systemctl reload sshYamaları 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 (origin) önüne bir CDN veya WAF (Cloudflare, Fastly, WAF ile AWS CloudFront ya da hosting firmanızın muadili) koyun. Bu katman hacimsel DDoS saldırılarını emer, yaygın enjeksiyon yüklerine ve kötü botlara karşı yönetilen kurallar uygular, kaynak IP'nizi gizler ve uygulamaya dokunmadan hız sınırları ile coğrafi kurallar uygulayabileceğiniz bir yer sağlar. Ardından kaynak sunucunun güvenlik duvarını, 443 numaralı porta doğrudan yalnızca CDN'in IP aralıkları ulaşabilecek şekilde kısıtlayın; aksi takdirde saldırganlar CDN'i basitçe atlar. Hosting Kontrol Aracı, bir sitenin gerçek kaynak sunucusunun CDN'in arkasında açıkta olup olmadığını gösterir.
E-posta Kimlik Doğrulama: SPF, DKIM ve DMARC
Web güvenliği; şifre sıfırlama bağlantıları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 adresinden e-posta gönderebilir; Google ve Yahoo da Şubat 2024'ten beri toplu göndericilerden (bulk sender) bu üçünü zorunlu olarak istiyor. Tam set üç DNS TXT kaydından oluşur:
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"Raporları toplamak için DMARC'a p=none ile başlayın; her meşru gönderici (pazarlama platformu, yardım masası, CRM) hizalama (alignment) kontrolünden geçtiğinde önce p=quarantine, ardından p=reject düzeyine geçin. Posta sunucularınıza şifreli teslimatı zorunlu kılmak için MTA-STS ve TLS-RPT kayıtlarını ekleyin ve hiç e-posta göndermeyen alan adlarında, hiçbir şekilde taklit edilemesinler diye bir null MX (MX 0 .) yayımlayın. Her kaydı SPF Kayıt Kontrolü, DKIM Kontrolü ve DMARC Kontrolü ile doğrulayın; e-posta teslim edilebilirliği düşerse gönderici IP'lerinizi IP Kara Liste Kontrolü ile kara listelere 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. Alan Adı Sağlık Kontrolü, DNS, SSL, e-posta kimlik doğrulama ve başlık kontrollerini her dağıtımdan sonra yeniden çalıştırabileceğiniz tek bir puanda toplar.
Olay Müdahale Planını İhtiyaç Duymadan Önce Yazın
Kimin nöbetçi olduğunu, her kimlik bilgisinin nasıl değiştirileceğini, sitenin nasıl salt okunur moda alınacağını, temiz yedeklerin nerede olduğunu ve hangi düzenleyici kuruma ya da müşterilere kaç saat içinde bildirim yapılması gerektiğini (GDPR kapsamında 72 saat) önceden belirleyin. Yılda bir kez masa başı tatbikatı (tabletop exercise) yapın. Prova edilmiş bir planı olan ekipler günler içinde toparlanır; planı olmayanlar ise haftalarca doğaçlama yapar.
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ü, nmap | Her güvenlik duvarı veya bulut değişikliğinden sonra |
| DNS, DNSSEC, e-posta kimlik doğrulama | Alan Adı 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) | OWASP 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, includeSubDomains ve preload ile HSTS | hstspreload.org'da listeleniyor |
| 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 |
| 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ı | Bir dakika içindeki altıncı deneme 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ü, 22, 3306 ve 6379 numaralı portların internetten kapalı olduğunu gösteriyor |
| 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 |
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'yi çeker ve güvenlik başlıklarını A'dan F'ye notlandırır: HSTS, Content-Security-Policy, X-Frame-Options, X-Content-Type-Options, Referrer-Policy ve Permissions-Policy için bulduğu tam değeri ve eksik olanları gösterir. Kayıt gerekmez.
Dene HTTP Başlık KontrolüAdvertisement
Web Güvenliği Hakkında Sıkça Sorulan Sorular
HTTPS'i modern TLS ve HSTS ile zorunlu kılın, sıkı güvenlik başlıkları gönderin (özellikle bir Content Security Policy), şifreleri MFA ve hız sınırlamasının arkasında Argon2id ile hashleyin, parametreli sorgular ve çıktı kodlama kullanın, erişim kontrolünü her nesne için sunucuda uygulayın, bağımlılıkları yamalı ve sabitlenmiş tutun, kullanılmayan portları kapatın ve güvenlik olaylarını merkezi olarak loglayın. İşe alan adını ve DNS'i kilitleyerek başlayın; çünkü diğer her şey, alan adınızın kontrolünün hâlâ sizde olmasına bağlıdır.