Web güvenliği dünyasında hiçbir açık, SQL Injection (SQLi) kadar eski, yaygın ve yıkıcı olmamıştır. Yıllardır OWASP Top 10 listesinin zirvelerinden inmeyen bu zafiyet, kötü amaçlı kişilerin veritabanınıza yetkisiz erişim sağlamasına, verileri çalmasına ya da tamamıyla silmesine imkân tanır.

Peki bu saldırı tam anlamıyla nedir ve CodeBlanks felsefesine uygun, güvenli kod yazarak bu problemu nasıl kökünden çözeriz?

SQL Injection (SQLi) Nedir?

SQL Injection, bir uygulamanın kullanıcıdan aldığı veriyi filtrelemeden ya da temizlemeden direkt olarak veritabanı sorgusuna (SQL) dahil etmesi sonucu oluşan bir mantık hatasıdır. Saldırgan, giriş alanlarına (örnek olarak bir arama kutusu ya da giriş formu) zararlı SQL komutları yazarak fonda çalışan orijinal sorguyu manipüle eder.

Bir Saldırı Nasıl Gerçekleşir?

Klasik ve güvensiz bir PHP giriş (login) sorgusunu düşünelim:


$kullanici_adi = $_POST['username'];
$sifre = $_POST['password'];

// ❌ KÖTÜ VE TEHLİKELİ KULLANIM
$sorgu = "SELECT * FROM users WHERE username = '$kullanici_adi' AND password = '$sifre'";

Normalde kullanıcı buraya adını ve şifresini yazar. Ancak saldırgan, kullanıcı adı alanına şu metni girerse:

' OR '1'='1' -- 

Arka planda çalışan SQL sorgusu aniden şuna dönüşür:

SELECT * FROM users WHERE username = '' OR '1'='1' -- ' AND password = ''

'1'='1' her zaman DOĞRU (TRUE) olduğu için WHERE koşulu tüm satırlarla eşleşir. -- ise sorgunun geri kalanını, yani şifre kontrolünü yorum satırına çevirir. Sorgu tablodaki ilk kullanıcıyı döndürür; bu çoğu zaman yöneticidir ve saldırgan şifre bilmeden sisteme giriş yapar!

SQL Injection'ın Yıkıcı Sonuçları

  • Veri İhlali: Kullanıcı şifreleri, kredi kartı bilgileri ya da şahsi veriler çalınabilir.
  • Veri Kaybı: Saldırgan DROP TABLE komutu ile bütün veritabanını silebilir.
  • Sunucu Ele Geçirme: İleri düzey SQLi saldırıları ile işletim sistemi düzeyinde komutlar çalıştırılabilir.

SQL Injection'dan Nasıl Korunulur?

Bu zafiyetten korunmanın tek ve net yolu, kullanıcıdan gelen veriyi katiyen sorguyla direkt olarak birleştirmemektir. Bunun için Prepared Statements (Hazırlanmış İfadeler) kullanılır.

CodeIgniter 4 gibi modern framework'ler bu güvenliği Query Builder (Sorgu Oluşturucu) ile otomatik sağlar:

// ✅ CODEIGNITER 4 İLE GÜVENLİ KULLANIM
$userModel = new \App\Models\UserModel();

$user = $userModel->where('username', $kullanici_adi)->first();

// Şifreler hash olarak saklanır (password_hash) ve SQL'de değil, PHP'de doğrulanır
if ($user === null || ! password_verify($sifre, $user->password_hash)) {
    return redirect()->back()->with('error', 'Kullanıcı adı veya şifre hatalı.');
}

Eğer saf PHP (PDO) kullanıyorsanız:


// ✅ PDO İLE GÜVENLİ KULLANIM (Prepared Statements)
$stmt = $pdo->prepare('SELECT id, username, password_hash FROM users WHERE username = :user');
$stmt->execute(['user' => $kullanici_adi]);
$user = $stmt->fetch();

Ek Savunma Katmanları

  • Girdiyi doğrulayın: veri sorguya ulaşmadan önce tür, uzunluk ve formatını kontrol edin (örneğin bir ID tam sayı olmalıdır).
  • Dinamik kısımlar için izin listesi kullanın: tablo adı, kolon adı ve ORDER BY yönü parametre olarak bağlanamaz; bu yüzden sadece sabit bir listedeki değerleri kabul edin.
  • En az yetki ilkesini uygulayın: web uygulamanızın veritabanı kullanıcısının DROP gibi yetkileri veya başka veritabanlarına erişimi olmamalıdır.
  • Veritabanı hatalarını gizleyin: ham SQL hatalarını ziyaretçilere göstermeyin; bu hatalar saldırganın veritabanı yapınızı çözmesine yardım eder.
  • Şifreleri hash'leyin: şifreleri password_hash() ile saklayın; böylece başarılı bir saldırıda bile düz metin olarak ele geçirilemezler.

Sonuç

SQL Injection, geliştiricilerin dikkatsizliğinden beslenen bir zafiyettir. Geleneksel dize birleştirme (string concatenation) tekniklerini bırakıp, modern framework'lerin sunmuş olduğu ORM ya da Query Builder yapılarını kullanarak programlarınızı kurşun geçirmez hale getirebilirsiniz. Unutmayın, güvenilir kod, kaliteli kodun temelidir.