Merhaba, "İleri Seviye Injection Saldırıları ve Savunma" modülümüze devam ediyoruz. Önceki dersimizde LDAP enjeksiyonu gibi altyapı servislerine yönelik, kimlik doğrulama atlatmadan RCE'ye kadar uzanan saldırıları analiz etmiştik. Bu dersle birlikte soyutlama katmanının daha üst seviyelerine çıkıyoruz.
Bugünkü dersimizde, modern uygulama geliştirmenin verimlilik ve esneklik sağlamak amacıyla kullandığı iki güçlü mekanizmanın, yani ORM (Object-Relational Mapper) ve Expression Language (EL)'in, nasıl birer saldırı vektörüne dönüşebileceğini inceleyeceğiz. Dersin sonunda, hem ORM tabanlı enjeksiyonları (özellikle Hibernate Query Language üzerinden) hem de Expression Language enjeksiyonlarını (Spring Expression Language odaklı) kod ve davranış seviyesinde tespit etme yetkinliği kazanacaksınız. Bu zafiyetler, geliştiricinin hayatını kolaylaştırmak için tasarlanmış soyutlamaların, kullanıcı girdisiyle birleştiğinde ne kadar tehlikeli olabileceğinin mükemmel örnekleridir.
Bölüm 1: ORM Enjeksiyonu - Hibernate (HQL) Vakası
Object-Relational Mapper (ORM) araçları, en başta da Java dünyasının standardı haline gelmiş Hibernate, geliştiricileri ham SQL sorguları yazma zahmetinden kurtarır. Veritabanı tablolarını Java nesnelerine (Entity) eşleyerek, nesne yönelimli bir dil olan Hibernate Query Language (HQL) ile veritabanı işlemlerini yapmamızı sağlarlar. Yaygın bir kanı, HQL'in SQL'den farklı bir katmanda çalışmasının SQL enjeksiyonuna karşı doğal bir koruma sağladığı yönündedir. Bu, tehlikeli bir yanılgıdır.
HQL enjeksiyonu, SQL enjeksiyonuna benzer şekilde, kullanıcı girdisinin HQL sorgusunu oluşturmak için doğrudan birleştirilmesiyle ortaya çıkar. Temel fark, HQL'in veritabanı şeması (tablolar, kolonlar) yerine, uygulama içindeki eşlenmiş nesneler (sınıflar, alanlar) üzerinde çalışmasıdır.
Exploiting Hibernate Injections - Sonar
SonarSource tarafından hazırlanan bu makale, HQL enjeksiyonunun temellerini ve geleneksel SQL enjeksiyonundan farklarını net bir şekilde ortaya koyuyor.
Makalenin giriş bölümünü ve "Restrictions and Bypasses" başlığı altındaki ilk paragrafı okuyun. HQL'in yalnızca Java sınıflarına eşlenmiş (mapped) verilere erişebilmesi gibi kısıtlamalarına dikkat edin.
HQL Enjeksiyonunun Tespiti ve İstismarı
Kod incelemesi sırasında HQL enjeksiyonu ararken, createQuery gibi metodlara parametre olarak geçirilen ve string birleştirme ile oluşturulan sorgulara odaklanmalısınız.
Aşağıdaki gerçek dünya örneği, yetersiz bir temizleme (sanitization) işleminin nasıl atlatılabileceğini gösteriyor.
Exploiting Hibernate Injections - Sonar
Makalenin "LogicalDoc PreAuth HQLi 8.3.2" başlıklı bölümü, kod seviyesinde harika bir HQL enjeksiyonu örneği sunmaktadır. Sizin gibi SAST ve güvenli kod inceleme tecrübesi olan bir uzman için bu analizin oldukça aydınlatıcı olacağını düşünüyorum.
Lütfen bu bölümü dikkatle inceleyin. Odaklanmanız gereken noktalar: Zafiyetli Kod: findByWhere metoduna _entity.name = '...' şeklinde bir HQL sorgusu gönderiliyor. Yetersiz Savunma: Geliştirici, tek tırnağı (') çift tek tırnakla ('') değiştiren SqlUtil.doubleQuotes metodunu kullanarak bir önlem almaya çalışmış. Bu, birçok SQL lehçesinde string'den çıkışı engellemek için standart bir yöntemdir. Atlatma Tekniği: Ancak, altta yatan veritabanı MySQL olduğunda, \ karakteri bir kaçış karakteri (escape character) olarak davranır. Bu nedenle, abc\' or 1=sleep(2) -- x gibi bir payload gönderildiğinde replaceAll("'", "''") fonksiyonu etkisiz kalır. \' ifadesi HQL parser'ı tarafından yorumlanmaz, doğrudan alttaki SQL sorgusuna geçer ve MySQL bu ifadeyi "kaçış karakteriyle belirtilmiş tek tırnak" olarak yorumlar, böylece saldırgan string'in dışına çıkmış olur.
HQL Kapsamından Kaçış: Native SQL Enjeksiyonu
HQL'in en tehlikeli yönü, belirli durumlarda ve altta yatan veritabanının özelliklerinden faydalanarak HQL sözdiziminin dışına çıkıp doğrudan native SQL komutları enjekte etme imkanı tanımasıdır. Bu, saldırının etkisini HQL'in kısıtlı dünyasından, veritabanının tüm gücüne taşır.
Saldırgan, HQL parser'ının geçerli bir ifade olarak kabul edeceği, ancak HQL'den SQL'e çevrildiğinde alttaki veritabanı motoru tarafından tamamen farklı yorumlanacak bir payload oluşturur.
Exploiting Hibernate Injections - Sonar
Aynı makalenin devamında yer alan OpenBravo ERP zafiyeti ve "HQL Injection Cheat Sheet" bölümü, bu "kaçış" tekniğini mükemmel bir şekilde göstermektedir.
OpenBravo ERP örneğini inceleyin. Burada, PostgreSQL'in $$ ile belirtilen string literallerine olan önceliğinden faydalanılarak HQL parser'ının nasıl kandırıldığı ve pg_sleep() gibi native bir fonksiyonun nasıl çalıştırıldığı gösterilmektedir. Sonrasında HQL Injection Cheat Sheet tablosunu mutlaka gözden geçirin. Bu tablo, farklı veritabanları için HQL'den kaçış ve native SQL enjeksiyonu için kullanılabilecek pratik payload'ları özetlemektedir. Bu, sızma testi ve Red Team çalışmalarınızdan aşina olduğunuz "duruma özel exploit" mantığının ORM katmanındaki bir yansımasıdır.
Bölüm 2: Expression Language (EL) Enjeksiyonu - SpEL Vakası
Expression Language (EL), çalışma zamanında (runtime) nesne grafikleri üzerinde sorgulama ve manipülasyon yapmayı sağlayan güçlü bir dildir. Özellikle Spring Framework'ün bir parçası olan Spring Expression Language (SpEL), metod çağırma ve temel string şablonlama gibi ek özellikleriyle öne çıkar. Bu esneklik, kullanıcıdan gelen verinin bir SpEL ifadesi olarak değerlendirildiği durumlarda kritik bir güvenlik zafiyetine, yani Server-Side Template Injection (SSTI)'a yol açar. Sonucu genellikle Uzaktan Kod Çalıştırma'dır (RCE).
SpEL Enjeksiyonunun Tespiti
SpEL enjeksiyonu, temelde iki şekilde ortaya çıkar:
- Doğrudan Değerlendirme: Geliştiricinin, kullanıcı girdisini doğrudan bir SpEL parser'ına vermesi.
- Dolaylı Değerlendirme: Kullanıcı girdisinin, SpEL ifadeleri içerebilen bir şablonun (template) parçası haline gelmesi.

Dinamik test sırasında, böyle bir zafiyeti ararken uygulamanın hata mesajları en büyük ipucunuz olabilir.

Gizli Tehlike: Şablon Enjeksiyonu
Enjeksiyon her zaman parseExpression gibi bariz bir fonksiyonda olmaz. Bazen, Netflix'te de bulunan bir zafiyette olduğu gibi, özel hata mesajları oluşturmak için kullanılan mekanizmalar aracılığıyla daha gizli bir şekilde ortaya çıkar.
Leveraging the Spring Expression Language (SpEL) injection ...
Bu blog yazısı, SpEL enjeksiyonunun daha az bilinen bir vektör üzerinden nasıl RCE'ye dönüştürülebileceğini adım adım gösteriyor.
Yazının başından "Can you spot the issue..." bölümünün sonuna kadar okuyun. Özellikle şu noktalara odaklanın: Zafiyetin Kaynağı: AuthorValidator sınıfı içinde, özel bir hata mesajı String.format ile oluşturuluyor ve bu mesaj context.buildConstraintViolationWithTemplate(message) metoduna veriliyor. Kritik Hata: Hibernate Validator, buildConstraintViolationWithTemplate metoduna verilen string'i bir SpEL şablonu olarak yorumlar. Kullanıcı girdisi (value) bu şablonun bir parçası haline geldiği için, saldırgan SpEL ifadeleri enjekte edebilir.
İstismar Adımları: Tespitten RCE'ye
Bir SpEL enjeksiyonu tespit edildiğinde, RCE'ye giden yol genellikle standart bir prosedür izler. Bu adımlar, sizin OSCP ve saldırı otomasyonu tecrübenizle oldukça örtüşmektedir.
- Doğrulama:
#{7*7}gibi basit bir matematiksel ifade gönderip yanıtta49değerini aramak, ifadenin çalıştığını doğrular. - Kod Çalıştırma Yeteneğini Keşfetme: SpEL, Java sınıflarına erişim ve metod çağırma yeteneğine sahiptir. Saldırgan, Java Reflection kullanarak
java.lang.Runtimesınıfına erişipexec()metodunu çağırarak komut çalıştırabilir. - Payload Oluşturma: Genellikle
java.lang.Runtime.getRuntime().exec('command')yapısını hedefleyen karmaşık bir SpEL ifadesi oluşturulur. - Kısıtlamaları Aşma: Komut içindeki özel karakterler (
|,>,&vb.) sorun yaratabileceğinden, saldırganlar genellikle payload'larını Base64 ile kodlayıp hedef sistemdepython -c exec('...'.decode('base64'))veya benzeri bir yöntemle çalıştırırlar.
Leveraging the Spring Expression Language (SpEL) injection ...
Aynı blog yazısının devamı, bu istismar sürecini pratik olarak göstermektedir.
Yazının son bölümünü inceleyerek, bir ters kabuk (reverse shell) elde etmek için payload'un nasıl adım adım oluşturulduğunu ve Base64 kodlamasının bu süreçte nasıl kullanıldığını gözlemleyin. #{''.getClass().forName('java.lang.Runtime')...} ile başlayan payload, SpEL'in ne kadar güçlü (ve tehlikeli) olabileceğinin kanıtıdır.
Özet ve Sonraki Adımlar
Bu derste, modern uygulama geliştirmenin temel taşlarından olan iki soyutlama katmanının nasıl istismar edilebileceğini gördük.
Ana Çıkarımlar:
- ORM Enjeksiyonu (HQLi): ORM'ler SQLi'ye karşı sihirli bir çözüm değildir. HQL sorguları string birleştirme ile oluşturulduğunda enjeksiyona açık hale gelir. En tehlikeli senaryo, HQL sözdiziminden "kaçarak" alttaki veritabanına özgü native SQL komutları çalıştırmaktır.
- Expression Language Enjeksiyonu (SpELi): Kullanıcı girdisinin bir EL motoru tarafından değerlendirilmesi, genellikle RCE ile sonuçlanan kritik bir SSTI zafiyetidir. Zafiyet, sadece bariz
parseExpressionçağrılarında değil, aynı zamanda hata mesajı şablonları gibi daha gizli noktalarda da bulunabilir. - Tespit Stratejisi: Her iki zafiyet türü için de temel tespit stratejisi, kullanıcı girdisinin veri olarak işlenmek yerine, sorgu veya ifade olarak yorumlandığı "kaynak-hedef" (source-to-sink) yollarını bulmaktır.
Bu dersle birlikte modülümüzdeki temel enjeksiyon türlerinin saldırı vektörlerini tamamladık. Bir sonraki dersimizde, bu saldırılara karşı en etkili savunma hattını nasıl kuracağımıza odaklanacağız. "Farklı ORM ve veritabanı teknolojilerinde ileri düzey parameterized query stratejileri tasarlama ve dinamik sorgu oluşturma risklerini yönetme" konusunu ele alarak, güvenli ve esnek veri erişim katmanları nasıl tasarlanır sorusuna cevap arayacağız.