Web Güvenliği / REHBER

SQL Injection Nedir? PHP ve PDO ile Korunma Rehberi

SQL Injection riskinin neden oluştuğunu, PHP PDO parametreli sorguların nasıl koruma sağladığını ve test sürecinde hangi güvenlik kontrollerinin gerekli olduğunu öğrenin.

Siber Saldırı3 dk okuma

SQL Injection (SQLi), bir uygulamanın kullanıcıdan gelen veriyi güvenli bir şekilde ayırmadan SQL komutuna eklemesi sonucu ortaya çıkan bir güvenlik açığıdır. Böyle bir uygulamada beklenmeyen girdiler sorgunun anlamını değiştirebilir. Açığın etkisi veritabanı hesabının yetkilerine ve uygulamanın mimarisine bağlıdır; bilgi ifşası, yetkisiz değişiklikler ya da hizmet kesintileriyle sonuçlanabilir.

SQL Injection neden ortaya çıkar?

Temel hata, veri ile komutun aynı metinde birleştirilmesidir. Kullanıcı adı, arama sözcüğü veya URL parametresi gibi değerler uygulamaya dışarıdan ulaşır. Bu değerlerin bir SQL sorgusunun içine dize birleştirmesiyle eklenmesi, veritabanının kullanıcı girdisini sorgu sözdizimi olarak yorumlaması riskini doğurur. Bir alan yalnızca rakam bekliyor olsa bile bunu tek başına güvenlik sınırı saymak doğru değildir.

Risk yalnızca giriş formlarında bulunmaz. Ürün filtreleri, sıralama seçenekleri, arama kutuları, raporlar, profil güncellemeleri ve API uç noktaları da veritabanı sorguları oluşturur. Bu yüzden kontrolleri tek tek sayfalara bırakmak yerine veri erişim katmanında aynı güvenli yaklaşımı uygulamak gerekir.

PHP PDO ile parametreli sorgu nasıl kullanılır?

Hazırlanmış sorgularda SQL komutunun yapısı önceden belirlenir; kullanıcı değeri sonradan parametre olarak bağlanır. Böylece veri, komutun bir parçasına dönüştürülmeden işlenir. Aşağıdaki örnek yalnızca okuma yapan bir sorguyu gösterir:

$stmt = $pdo->prepare(
    'SELECT id, username FROM users WHERE email = :email'
);
$stmt->execute(['email' => $email]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);

Uygulama PDO istisnalarını ayrıntılı biçimde son kullanıcıya dökmemelidir. Bağlantı ve sorgu hataları güvenli günlükleme kanalına yazılmalı, ziyaretçiye ise anlaşılır ve sınırlı bir hata mesajı verilmelidir. Kod örneğindeki değer bağlama biçimi, sorgunun içindeki kullanıcı verisini yapısal SQL'den ayırır.

Parametreli sorguların sınırları

Bağlanan parametreler verileri korur; tablo adı, sütun adı veya ORDER BY yönü gibi SQL tanımlayıcıları ise genel olarak parametre olarak bağlanamaz. Bu alanlarda kullanıcıdan gelen değeri SQL'e doğrudan koymak yerine önceden tanımlanmış seçeneklerden oluşan bir izin listesi kullanılmalıdır. Örneğin sıralama için yalnızca created_at ve title seçeneklerini destekleyen bir eşleme oluşturun.

Parametre kullanımı tek başına bütün güvenlik hedeflerini karşılamaz. Veritabanı hesabını yalnızca gereken tablolar ve işlemler için yetkilendirmek, gereksiz yönetici ayrıcalıklarını kaldırmak, hassas verileri sınırlandırmak ve sunucu yapılandırmasını korumak hasarın kapsamını daraltır.

Yayın öncesi SQLi kontrol listesi

  • Uygulamadaki bütün SQL çağrılarını envantere alın; elle oluşturulmuş sorguları parametreli yapıya taşıyın.
  • Dinamik sıralama, tablo ve kolon seçimi için sabit izin listeleri kullanın.
  • Hassas işlemlerde sunucu tarafı yetkilendirme kontrolü yapın; yalnızca arayüz düğmelerini gizlemek yeterli değildir.
  • Veritabanı kullanıcısının yetkilerini en az ayrıcalık ilkesine göre düzenleyin.
  • Üretim ortamında ayrıntılı SQL hata mesajlarını ve gizli bağlantı bilgilerini ziyaretçilere göstermeyin.
  • Parametreli sorgu kullanımını kod incelemesi ve otomatik testlerle doğrulayın.
  • Güvenlik olaylarında istek yolu, zaman, anonimleştirilmiş bağlam ve ilgili olay türünü kaydedin; parola ve tokenları loglamayın.

Güvenlik testi nasıl planlanmalı?

Kontrollerinizi yalnızca size ait veya açıkça yetkilendirildiğiniz uygulamalarda yürütün. Test verisi kullanın, üretim veritabanını koruyun ve geri dönüş planı hazırlayın. Birim testlerinde tek tırnak, özel karakter ve beklenmedik uzunluk gibi girdilerin uygulamayı hataya düşürmediğini gözlemleyebilirsiniz. Testin amacı bir başkasının verisine erişmek değil, sorgunun kullanıcı girdisinden bağımsız kaldığını doğrulamaktır.

İyi tasarlanmış bir uygulama, güvenli kodlama kurallarını merkezi veri erişim katmanında uygular; loglama, yetkilendirme ve güncel bağımlılık yönetimi de bu yaklaşımı tamamlar. Kurulumunuzdaki güvenlik açıklarını önceliklendirmek için ayrıca KOBİ güvenlik kontrol listesini inceleyin.

Sık sorulan sorular

WAF kullanmak SQL Injection açığını tamamen kapatır mı?

Hayır. Web uygulama güvenlik duvarı ek koruma katmanıdır; yanlış sorgu oluşturma mantığını düzeltmez. Kalıcı çözüm güvenli sorgu oluşturma ve katmanlı kontrollerdir.

PDO kullanmak tek başına yeterli mi?

Hayır. PDO ile parametreli sorgu kullanmak gerekir. PDO üzerinden kullanıcı girdisinin doğrudan sorgu metnine birleştirilmesi aynı tür riskleri sürdürebilir.

Kaynaklar ve ileri okuma

OWASP SQL Injection Prevention Cheat Sheet ve PHP PDO Prepared Statements uygulama örnekleri için başvuru kaynaklarıdır.