Web uygulamalarında SQL Injection, XSS ve CSRF açıklarına karşı güvenli yazılım geliştirme prensipleri ve OWASP Top 10 savunma stratejilerini inceleyin.
Hızlı Özet (TL;DR)
Yazılım güvenliği, ürün canlıya alındıktan sonra güvenlik duvarı eklemekle değil, daha ilk kod satırı yazılırken güvenli yazılım geliştirme yaşam döngüsü (SSDLC - Secure Software Development Lifecycle) ilkelerinin uygulanmasıyla başlar. OWASP (Open Worldwide Application Security Project) Top 10 listesinde yer alan kritik zafiyetlerin başında Bozuk Erişim Kontrolü (Broken Access Control), Kriptografik Başarısızlıklar, Enjeksiyon (SQLi, NoSQLi, Command Injection ve XSS) saldırıları ve Güvensiz Tasarım gelir. Güvenli kodlamanın temel kuralı; istemciden, form alanlarından, HTTP başlıklarından veya dış API’lerden gelen hiçbir girdiye güvenmemek (Zero Trust), parametreli sorgular kullanmak, nesne düzeyinde yetki denetimi yapmak ve hassas verileri güncel kriptografik algoritmalarla korumaktır.
1. En Yaygın Web Güvenlik Açıkları ve Savunma Matrisi
Kurumsal web uygulamalarında, B2B bayi portallarında ve bulut tabanlı ERP/CRM panellerinde sıklıkla karşılaşılan güvenlik açıkları ve alınması gereken kod seviyesindeki mimari önlemler aşağıda özetlenmiştir:
| Güvenlik Açığı (OWASP Kategorisi) | Tehdit Türü ve Saldırı Vektörü | Olası İş ve Veri Sonucu | Kod Seviyesinde Savunma Stratejisi |
|---|---|---|---|
| SQL Injection (A03 - Injection) | Doğrudan veritabanı sorgusuna kontrolsüz metin birleştirme (String Concatenation) | Veritabanının tamamen ele geçirilmesi, değiştirilmesi ve toplu veri sızıntısı | Parametreli sorgu (Prepared Statements), Stored Procedure ve güvenli ORM kullanımı |
| Cross-Site Scripting (A03 - XSS) | Sayfaya veya DOM ağacına zararlı JavaScript kodu gömülmesi | Kullanıcı oturum çerezlerinin çalınması ve hesap ele geçirme (Account Takeover) | Bağlama duyarlı çıktı kodlama (Output Encoding), DOMPurify ve katı CSP başlığı |
| BOLA / IDOR (A01 - Broken Access) | URL veya JSON içindeki ID parametresini değiştirerek yetkisiz veriye erişim | Başka bir müşterinin faturasını, sözleşmesini veya siparişini görüntüleme/silme | Her sorguda oturum açmış kullanıcının nesne sahipliği (Tenant/Owner) kontrolü |
| CSRF (Siteler Arası İstek Sahtekarlığı) | Kullanıcının tarayıcısına habersizce yetkili HTTP POST/PUT isteği yaptırma | Kullanıcının bilgisi dışında parola, e-posta veya banka IBAN bilgisinin değiştirilmesi | Kriptografik Anti-CSRF token, SameSite=Strict çerez bayrağı ve Origin doğrulaması |
| SSRF (A10 - Sunucu Tarafı İstek) | Sunucuya dışarıdan verilen URL’yi iç ağa (localhost / metadata) yönlendirme | Güvenlik duvarı arkasındaki iç servislerin ve bulut anahtarlarının okunması | URL beyaz listesi (Allowlist), özel IP bloklarının (127.0.0.1, 169.254.x.x) engellenmesi |
2. Güvenli Kod Örnekleri: Parametreli Sorgular ve Enjeksiyon Önleme
Enjeksiyon zafiyetleri, geliştiricinin dışarıdan gelen veriyi (Data) çalıştırılabilir komut (Code) ile aynı metin dizgesi içinde birleştirmesinden kaynaklanır. Veritabanı yorumlayıcısı, kullanıcının gönderdiği ' OR '1'='1 gibi ifadeleri veri olarak değil, SQL mantıksal operatörü olarak algılar.
Güvensiz Yaklaşım (SQL Injection’a Açık)
// TEHLİKELİ: Kullanıcı girdisi doğrudan sorgu metnine ekleniyor
const query = `SELECT * FROM kullanicilar WHERE email = '${req.body.email}'`;
await db.execute(query);
Güvenli Yaklaşım (Prepared Statement / Parametreli Sorgu)
// GÜVENLİ: Veritabanı motoru sorgu planını önceden derler; girdiyi salt veri olarak işler
const query = "SELECT id, ad, email FROM kullanicilar WHERE email = ?";
await db.execute(query, [req.body.email]);
Modern ORM kütüphaneleri (Prisma, TypeORM, Entity Framework, Hibernate) varsayılan olarak parametreli sorgu üretir; ancak bu kütüphanelerin içinde bulunan rawQuery() veya FromSqlRaw() metodları kullanılırken yine dize birleştirme yapılırsa SQL Injection zafiyeti yeniden doğar.
3. Bozuk Erişim Kontrolü (BOLA / IDOR) ve Çok Kiracılı (Multi-Tenant) Güvenlik
OWASP Top 10 listesinin birinci sırasına yerleşen Bozuk Erişim Kontrolü (A01), geleneksel güvenlik duvarlarının veya WAF (Web Application Firewall) cihazlarının yakalayamadığı bir iş mantığı (Business Logic) hatasıdır. Örneğin bir B2B müşteri portalında /api/faturalar/1045 adresine istek atan kullanıcı, parametreyi /api/faturalar/1046 yaptığında başka bir firmanın faturasını görebiliyorsa burada kritik bir IDOR (Insecure Direct Object Reference) açığı vardır.
Nesne Düzeyinde Yetkilendirme (Object-Level Authorization)
Güvenli bir arka uç (Backend) mimarisinde yalnızca kullanıcının oturum açmış olması (isAuthenticated) yetmez; istenen kaynağın o kullanıcıya veya o kullanıcının bağlı olduğu şirkete (firma_id) ait olduğu veritabanı sorgusunun WHERE koşulunda zorunlu tutulmalıdır:
// GÜVENLİ: Fatura ID'si ile birlikte oturumdaki kullanıcının firma_id değeri de sorgulanır
const fatura = await db.query(
"SELECT * FROM faturalar WHERE id = ? AND firma_id = ?",
[req.params.faturaId, req.session.aktifFirmaId]
);
if (!fatura) {
return res.status(404).json({ hata: "Kayıt bulunamadı veya erişim yetkiniz yok." });
}
Ayrıca tahmin edilebilir ardışık tam sayılar (1045, 1046) yerine kriptografik olarak rastgele üretilen UUID v4 veya ULID kimliklerinin kullanılması, otomatik tarama araçlarının (enumeration) işini önemli ölçüde zorlaştırır.
4. Kriptografik Güvenlik, Oturum Yönetimi ve Tarayıcı Savunması
Kullanıcı kimlik bilgilerinin ve oturum anahtarlarının korunması, hem KVKK teknik tedbirleri hem de Veri Sızıntısı Önleme (DLP) politikaları açısından yasal bir zorunluluktur:
- Parola Özetleme (Hashing) Algoritmaları: Kullanıcı parolaları veritabanında asla düz metin olarak veya hızlı kırılabilen
MD5/SHA-1algoritmalarıyla saklanmamalıdır. Donanım (GPU/ASIC) saldırılarına dirençli, tuzlanmış (salted) Argon2id veya yüksek maliyet faktörlü bcrypt kullanılmalıdır. - Güvenli Çerez (Cookie) Bayrakları: Oturum çerezleri tanımlanırken
HttpOnly(JavaScript iledocument.cookieüzerinden okunmasını engeller),Secure(yalnızca HTTPS üzerinden iletilmesini zorlar) veSameSite=StrictveyaLax(CSRF saldırılarını keser) bayrakları eksiksiz tanımlanmalıdır. - Bağımlılık Güvenliği (SCA - Software Composition Analysis): Projede kullanılan açık kaynaklı
npm,NuGetveyapippaketleri CI/CD hattında otomatik taranmalı; bilinen CVE zafiyeti barındıran eski kütüphanelerin canlı ortama çıkması engellenmelidir.
Content Security Policy (CSP) ile Tarayıcı Katmanında Savunma
XSS saldırılarını ve veri sızdırma girişimlerini etkisiz kılmanın en güçlü yollarından biri HTTP yanıt başlığına katı bir CSP (İçerik Güvenlik Politikası) ve HSTS başlığı eklemektir:
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'; frame-ancestors 'none';
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
X-Content-Type-Options: nosniff
Bu başlıklar sayesinde istemci tarafına üçüncü taraf zararlı betiklerin veya satır içi (inline) kodların enjekte edilmesi, sayfanın sahte bir <iframe> içine alınarak Clickjacking yapılması ve MIME türü manipülasyonu tarayıcı tarafından doğrudan engellenir.
Web projelerinizin ve API servislerinizin siber saldırılara karşı dayanıklılığını test etmek için Sızma Testi ve Pentest sayfamızı inceleyebilir, kritik tesis güvenliği için Savunma Sanayii ve İmalat Siber Güvenlik mimarilerimize göz atabilir ve güvenli kurumsal yazılım çözümlerimiz için Özel Yazılım Geliştirme ekibimizden destek alabilirsiniz.
Kaynaklar
Sıkça Sorulan Sorular
Web uygulamamızın önünde WAF (Web Uygulama Güvenlik Duvarı) varken yine de güvenli kodlama ve pentest gerekli midir?
Kesinlikle gereklidir. WAF cihazları bilinen imza desenlerini (örneğin temel SQL Injection veya XSS dizgelerini) filtrelemekte başarılıdır; ancak uygulamanın iş mantığındaki hataları (BOLA/IDOR ile başka müşterinin verisini çekme, sepette negatif fiyat gönderme, adım atlayarak onay alma veya yetki yükseltme) anlayamaz. Ayrıca saldırganlar kodlama (encoding) ve parçalama teknikleriyle WAF kurallarını aşabilir. WAF yalnızca bir kalkan katmanıdır; asıl güvenlik kaynak kodun içinde sağlanır.
JWT (JSON Web Token) tabanlı kimlik doğrulamada en sık yapılan güvenlik hataları nelerdir?
En yaygın iki hata; JWT’nin tarayıcıda localStorage içinde saklanması (herhangi bir XSS açığında tüm token’ın çalınmasına yol açar, bunun yerine HttpOnly çerez kullanılmalıdır) ve token doğrulamasında alg: none zafiyetine veya zayıf imza anahtarlarına izin verilmesidir. Ayrıca JWT’lerin geçerlilik süresi (Access Token TTL) 15-30 dakika gibi kısa tutulmalı ve oturum kapatıldığında veya yetki değiştiğinde iptal edilebilen (Revocation / Blocklist) bir Refresh Token mimarisiyle desteklenmelidir.
SAST ve DAST testleri yazılım geliştirme sürecinin hangi aşamasında çalıştırılmalıdır?
SAST (Statik Uygulama Güvenlik Testi), uygulama henüz derlenmeden kaynak kodları ve bağımlılıkları tarayarak olası güvenlik açıklarını geliştirici kod yazarken veya Git’e Push yaptığında (CI aşamasında) yakalar. DAST (Dinamik Uygulama Güvenlik Testi) ise çalışan bir test/stage uygulamasına dışarıdan gerçek bir saldırgan gibi istekler göndererek çalışma zamanı ve yapılandırma hatalarını tespit eder. Her iki yöntem birbirini tamamlar ve her büyük sürüm öncesinde uzman sızma testi (Pentest) ile taçlandırılmalıdır.