1. Kullanıcı girdisini SQL metnine ekleme
Bir arama kutusundan gelen değeri tırnaklarla bir SQL metnine eklemek, veri ile sorgu yapısını birbirine karıştırır. Girilen değerin içinde tırnak veya sorgu parçası bulunması durumunda beklenmedik davranış oluşabilir. PDO prepared statement kullanmak, değişken değerleri ayrı parametreler olarak bağlamanı sağlar.
Bu koruma sorgunun tamamını otomatik olarak güvenli hale getirmez. Sorguda tablo veya sütun adını kullanıcıdan alıyorsan farklı bir sınır gerekir. Parametre belirteçleri bir değerin yerine kullanılabilir; bir SQL anahtar sözcüğü veya tablo adının yerine geçmez. Bu ayrım özellikle sıralama menülerinde önemlidir.
2. Küçük bir okuma sorgusu
Aşağıdaki örnek önceden güvenli biçimde oluşturulmuş bir PDO bağlantısını kullanır; bağlantı parolasını kaynak dosyasında göstermiyoruz. Sunucuda doğrulanmış kullanıcı kimliği ile alınan liste, yalnızca o kullanıcıya ait kayıtları getirir. Kullanıcı kimliğini formdan kabul etmek yerine oturumdan türetmek gerekir.
SQL injection koruması ile kayıt erişim yetkisi iki farklı meseledir. Kusursuz parametre bağlanan bir sorgu, WHERE koşulunda sahiplik kontrolü yoksa başkasının verisini döndürebilir. Yetkiyi arayüzde düğme saklayarak değil, sorgunun ve sunucu işleminin sınırında uygula.
$stmt = $pdo->prepare(
'SELECT id, title FROM reading_list
WHERE owner_id = :owner AND title LIKE :term
ORDER BY id DESC LIMIT 30'
);
$stmt->execute([
'owner' => $authenticatedUserId,
'term' => '%' . $searchTerm . '%',
]);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);3. Sıralama sütununu izinli listeden seç
ORDER BY için sütun adı bir parametreyle bağlanamaz. Bunun yerine kullanıcıya gösterdiğin seçenekleri sabit SQL parçalarına eşleştir. Örneğin “en yeni” seçeneğini created_at DESC, “başlık” seçeneğini title ASC ile eşleştir; izinli olmayan değerde güvenli varsayılana dön.
İzinli listeyi SQL'den gelen bir hata mesajına güvenerek kurma. Ayrıca sayfalama limitinin sayısal ve üst sınırı olan bir değer olduğunu doğrula. Parametre bağlamak, sınırsız veri çekme veya ağır sorgu oluşturma sorununu kendi başına çözmez.
$orders = [
'newest' => 'created_at DESC',
'title' => 'title ASC',
];
$order = $orders[$sort] ?? $orders['newest'];
// $order yalnızca yukarıdaki sabit parçalardan seçilir.
$stmt = $pdo->prepare(
"SELECT id, title FROM articles WHERE status = :status ORDER BY $order LIMIT 30"
);
$stmt->execute(['status' => 'published']);4. Hata ve işlem sınırlarını düşün
Veritabanı hatasını ziyaretçiye ham olarak döndürmek bağlantı veya şema bilgisi sızdırabilir. Sunucu günlüklerine güvenli teknik bağlam yaz; istemciye işlem tamamlanamadı mesajı ver. Günlüğe sorgunun bütün parametrelerini yazmadan önce kişisel veri ve sır içerip içermediğini değerlendir.
Birbiriyle ilişkili iki yazma işleminin birlikte tamamlanması gerekiyorsa transaction kullan. Örneğin stok düşümüyle sipariş kaydı arasında tutarsızlık kalmamalıdır. Transaction her iş akışını otomatik olarak yarış koşulundan korumaz; kilit, benzersiz kısıt ve eşzamanlılık kuralları da gerekebilir.
5. Kontrol listesi
Kod incelemesinde üç ayrı soruyu yanıtla: değerler parametreyle bağlanıyor mu, dinamik SQL parçaları izinli listeden mi geliyor, kullanıcı yalnızca yetkili olduğu kayıtlara mı erişiyor? Bunları ayrı test etmek, güvenliği yalnızca tek bir teknik özelliğe bağlamanı engeller.
Arama terimindeki yüzde ve alt çizgi LIKE içinde joker karakterdir. Parametre bağlanmış olsa da kullanıcı bunlarla daha geniş sonuçlar alabilir; bu SQL injection değildir. Uygulaman tam metin araması mı, desen araması mı istediğine göre bu davranışı bilerek seç ve kullanıcıya açıkla.
Kaynaklar ve kontrol notu
Bu rehber yapay zekâ desteğiyle hazırlanmış özgün bir editoryal içeriktir. Kaynak kontrolü: 30 Eylül 2026. Örnekleri kendi proje koşullarına uyarlayarak doğrula.
Bir hata fark ettiysen editörlüğe bildir; düzeltmeleri güncelleme tarihiyle işleriz.


