SQL Injection ve JPA: ORM Çağında Güvenli Sorgu Disiplini
JPA/Hibernate kullanmak SQL injection riskini bitirmez: birleştirilmiş JPQL, native sorgular, ORDER BY ve LIKE desenleri için güvenli sorgu disiplini rehberi.
ORM kullanıyorum — SQL injection hâlâ benim sorunum mu?
Evet. JPA/Hibernate, parametrik sorgularla kullanıldığında SQL injection'a karşı güçlü koruma sağlar; ama koruma ORM'den değil, parametre bağlamadan gelir. String birleştirmeyle kurulan her JPQL veya native sorgu, ORM'in içinden geçse bile enjeksiyona açıktır. SQL injection, OWASP Top 10'da varlığını koruyan en eski web zafiyetidir ve modern projelerde tam da bu "ORM bizi korur" varsayımı yüzünden yaşamaya devam eder.
Tek kural: veri, sorgu metnine asla girmez
Güvenli ve güvensiz desen arasındaki fark tek satırda görülür. Güvensiz: "select o from Order o where o.customer = '" + input + "'". Güvenli: "select o from Order o where o.customer = :customer" ve değerin parametre olarak bağlanması. Bu kural JPQL, Criteria API, Spring Data türetilmiş metotlar ve native sorgular dahil her katmanda aynıdır: kullanıcıdan gelen değer sorgu metnine değil, sorgu parametresine gider.
Riskin geri döndüğü dört nokta
Nokta | Neden risklidir | Güvenli yaklaşım |
|---|---|---|
Native sorgular | Ham SQL'de birleştirme alışkanlığı sürer | Named parameter ile bağlama; birleştirme yasağı |
ORDER BY / sıralama | Sütun adı parametre olarak bağlanamaz | İzin listesinden eşleme (whitelist mapping) |
LIKE desenleri | % ve _ karakterleri desen anlamı taşır | Joker karakterleri kaçışlama + parametre bağlama |
Dinamik filtre kurulumu | Koşulların string ile eklenmesi | Criteria API / Specification desenleri |
ORDER BY: parametrenin çalışmadığı yer
Sıralama sütunu, SQL'de tanımlayıcıdır (identifier) — parametre olarak bağlanamaz. Frontend'den gelen sort=price değerini doğrudan sorguya eklemek klasik bir enjeksiyon kapısıdır. Doğru desen eşlemedir: gelen değer, koddaki sabit bir izin listesiyle ("price" → o.price) eşleştirilir; listede olmayan değer reddedilir. Spring Data'nın Pageable/Sort mekanizması kullanılıyorsa da izin verilen alanların doğrulanması uygulamanın sorumluluğundadır.
Derinlemesine savunma: sorgu disiplini yalnız başına yeterli değil
Enjeksiyon savunması tek katmana bırakılmaz. Uygulama katmanında girdi doğrulama (tip, uzunluk, format) saldırı yüzeyini daraltır. Veritabanı katmanında uygulamanın bağlandığı kullanıcı en az yetkiyle tanımlanır: tablo sahipliği yok, DDL yetkisi yok, yalnızca gereken tablolarda gereken işlemler. Böylece disiplin bir noktada delinse bile hasar sınırlanır. Hata mesajlarında SQL detayının kullanıcıya dönmemesi de aynı savunmanın parçasıdır: detay loga, kullanıcıya genel mesaj.
Tespit: enjeksiyonu üretime çıkmadan yakalamak
Üç pratik hat vardır: kod incelemede "sorgu + birleştirme" desenlerinin otomatik taranması (statik analiz araçları bu deseni iyi yakalar); repository katmanı için sınır değerli birim/entegrasyon testleri; ve düzenli sızma testlerinde veri erişim uçlarının özel olarak hedeflenmesi. Birleştirilmiş sorgu bulgusu, statik analizde "tartışılmaz düzeltme" sınıfına konmalıdır.
İş etkisi: en eski zafiyet, en pahalı sonuç
SQL injection doğrudan veri tabanına — yani müşteri verisinin tamamına — açılan kapıdır; tarihteki büyük kart ve kimlik verisi ihlallerinin önemli kısmı bu sınıftandır. KVKK/GDPR bildirimi, müşteri kaybı ve sözleşme cezaları zincirleme gelir. Buna karşılık önlemin maliyeti neredeyse sıfırdır: parametre bağlama, performansı da çoğu durumda iyileştiren (sorgu planı önbelleği) standart pratiktir. Maliyet/fayda tablosu bu kadar net olan başka güvenlik başlığı azdır.
Sık sorulan sorular
Criteria API kullanırsam güvende miyim?
Değerleri parametre olarak bağladığınız sürece evet; ama Criteria içinde bile ham string ifade eklemek mümkündür — kural değişmez: veri, ifade metnine girmez.
Stored procedure kullanmak çözüm mü?
Parametreli çağrıldığında güvenlidir; ancak procedure içinde dinamik SQL birleştiriliyorsa risk aynen içeri taşınır. Güvence, prosedürün kendisinde değil parametre disiplinindedir.
Girdi doğrulama enjeksiyonu tek başına engeller mi?
Hayır — doğrulama yüzeyi daraltır ama kaçışlar mümkündür. Birincil savunma her zaman parametre bağlamadır; doğrulama ikinci katmandır.
NoSQL kullanıyorum; bu konu beni ilgilendirir mi?
Evet — enjeksiyon ilkesi sorgu diline değil, "veri ile komutun karışmasına" dairdir. NoSQL sorgu nesnelerine doğrulanmamış girdi gömmek eşdeğer riskler üretir.
Veri erişim güvenliği kontrol listesi
Kod tabanında sorgu birleştirme taraması yapıldı; bulgular kapatıldı
Tüm JPQL/native sorgular parametre bağlıyor
Sıralama/sütun seçimi izin listesi eşlemesiyle yapılıyor
LIKE desenlerinde joker kaçışlama uygulanıyor
Uygulama DB kullanıcısı en az yetkiyle tanımlı
SQL hata detayları kullanıcı yanıtlarına sızmıyor
Statik analizde birleştirilmiş sorgu kuralı zorunlu
SSH Yazılım, Java/Spring projelerinde veri erişim katmanı güvenlik denetimi ve düzeltme desteği sunar. Repository katmanınızı birlikte gözden geçirelim.