Her yıl milyonlarca web uygulaması güvenlik açıklarından etkileniyor. Bu açıkların büyük çoğunluğu önlenebilir türde. OWASP (Open Web Application Security Project) Top 10, geliştiricilerin odaklanması gereken kritik riskleri listeler.
A01: Broken Access Control
2021'den bu yana listedeki ilk sıra. Yetkilendirme hataları, kullanıcıların yetkisiz kaynaklara erişmesine izin verir.
// ❌ Güvensiz: Kullanıcı ID'si parametreden alınıyor
app.get("/api/users/:id/profile", async (req, res) => {
const profile = await db.users.findById(req.params.id);
res.json(profile);
});
// ✅ Güvenli: Oturum açmış kullanıcının kendi profilini doğrula
app.get("/api/users/:id/profile", authenticate, async (req, res) => {
if (req.user.id !== req.params.id && !req.user.isAdmin) {
return res.status(403).json({ error: "Forbidden" });
}
const profile = await db.users.findById(req.params.id);
res.json(profile);
});Temel kural: Her isteği, her seferinde yetkilendirin. Session'a değil, token'a güvenin.
A02: Cryptographic Failures
Hassas verilerin şifresiz veya zayıf algoritmalarla saklanması.
# ❌ MD5 veya SHA-1 ile parola hashleme — kırılabilir
import hashlib
hashed = hashlib.md5(password.encode()).hexdigest()
# ❌ bcrypt doğru kullanılmamış — salt rounds çok düşük
import bcrypt
hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=4))
# ✅ Argon2id — OWASP'ın önerdiği modern algoritma
from argon2 import PasswordHasher
ph = PasswordHasher(time_cost=2, memory_cost=65536, parallelism=2)
hashed = ph.hash(password)Veritabanındaki tüm hassas alanlar (TC kimlik, IBAN, sağlık verileri) AES-256-GCM ile şifrelenmelidir.
A03: Injection
SQL, NoSQL, OS Command, LDAP injection. Hâlâ en yaygın saldırı vektörlerinden biri.
// ❌ SQL Injection'a açık
const query = `SELECT * FROM users WHERE email = '${email}'`;
// Saldırı: email = "' OR '1'='1'; DROP TABLE users;--"
// ✅ Parametreli sorgu (Prepared Statement)
const result = await db.query(
"SELECT * FROM users WHERE email = $1",
[email]
);
// ✅ ORM ile (Prisma/TypeORM otomatik parametre binding yapar)
const user = await prisma.user.findUnique({
where: { email }, // otomatik olarak güvenli
});NoSQL injection'a dikkat:
// ❌ MongoDB injection
User.findOne({ email: req.body.email, password: req.body.password });
// Saldırı: { "password": { "$ne": null } }
// ✅ Validasyon + schema enforcement
const { email, password } = z.object({
email: z.string().email(),
password: z.string().min(8).max(128),
}).parse(req.body);A05: Security Misconfiguration
Varsayılan yapılandırmalar genellikle güvensizdir.
// ❌ Express'te güvensiz varsayılanlar
app.use(express.json()); // Boyut limiti yok → DoS
app.get("/debug", (req, res) => res.json(process.env)); // Env değişkenleri sızdı!
// ✅ Güvenli yapılandırma
import helmet from "helmet";
import rateLimit from "express-rate-limit";
app.use(helmet()); // Security headers
app.use(express.json({ limit: "10kb" })); // Boyut limiti
app.use(rateLimit({ // Brute-force koruması
windowMs: 15 * 60 * 1000,
max: 100,
}));
// Üretimde debug endpoint'leri kapatın
if (process.env.NODE_ENV !== "production") {
app.use("/debug", debugRouter);
}A07: Identification and Authentication Failures
Zayıf oturum yönetimi ve kimlik doğrulama açıkları.
// JWT güvenli kullanımı
import jwt from "jsonwebtoken";
// ❌ Zayıf: Kısa ömürlü token yok, algoritma belirtilmemiş
const token = jwt.sign({ userId }, secret);
// ✅ Güvenli
const accessToken = jwt.sign(
{ userId, iat: Date.now() },
process.env.JWT_SECRET!,
{
algorithm: "RS256", // Asimetrik — public key doğrulama
expiresIn: "15m", // Kısa ömür
issuer: "myapp.com",
}
);
// Refresh token → rotation + blacklist
const refreshToken = crypto.randomBytes(64).toString("hex");
await db.refreshTokens.create({
token: await hash(refreshToken),
userId,
expiresAt: addDays(new Date(), 30),
});Güvenlik Testi Araçları
# OWASP ZAP ile otomatik tarama
docker run -t owasp/zap2docker-stable zap-baseline.py \
-t https://yourtarget.com
# Nikto ile web sunucu taraması
nikto -h https://yourtarget.com
# SQLMap ile SQL injection testi (yalnızca yetkili sistemlerde!)
sqlmap -u "https://target.com/page?id=1" --dbsGüvenli Yazılım Geliştirme Kültürü
Güvenlik bir özellik değil, bir kalite göstergesidir. Bu prensipler günlük geliştirme sürecinize entegre edilmeli:
- Threat modeling: Her yeni özellik için "Bu nasıl kötüye kullanılabilir?" sorusunu sorun
- Dependency audit:
npm audit,pip-auditgibi araçları CI/CD'ye ekleyin - Secret management: Gizli bilgileri asla koda gömmeyin — Vault, AWS Secrets Manager kullanın
- SAST/DAST: Statik ve dinamik analiz araçlarını geliştirme pipeline'ınıza dahil edin
Güvenlik açıkları çoğunlukla kötü niyet değil, dikkatsizlikten kaynaklanır. Farkındalık, en güçlü savunmadır.