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.

Parametrik JPA sorgusu ile güvensiz birleştirmenin karşılaştırıldığı Java editör penceresi

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

  1. Kod tabanında sorgu birleştirme taraması yapıldı; bulgular kapatıldı

  2. Tüm JPQL/native sorgular parametre bağlıyor

  3. Sıralama/sütun seçimi izin listesi eşlemesiyle yapılıyor

  4. LIKE desenlerinde joker kaçışlama uygulanıyor

  5. Uygulama DB kullanıcısı en az yetkiyle tanımlı

  6. SQL hata detayları kullanıcı yanıtlarına sızmıyor

  7. 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.