Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 13

ORM ve EL Injection Saldırı Tespiti

Recommended resources

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:

  1. Doğrudan Değerlendirme: Geliştiricinin, kullanıcı girdisini doğrudan bir SpEL parser'ına vermesi.
  2. Dolaylı Değerlendirme: Kullanıcı girdisinin, SpEL ifadeleri içerebilen bir şablonun (template) parçası haline gelmesi.
Bu Java kodu, bir `@RestController` içerisinde SpEL enjeksiyonuna yol açan klasik bir zafiyet desenini göstermektedir. `spelInjection` metodu, HTTP isteğinden gelen `input` parametresini hiçbir doğrulama veya temizleme yapmadan doğrudan `parser.parseExpression(input)` metoduna vermektedir. Bu, saldırganın yolladığı herhangi bir string'in sunucu tarafında bir SpEL ifadesi olarak çalıştırılmasına neden olur.

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

Bu görsel, bir HTTP isteğine verilen 500 Internal Server Error yanıtını göstermektedir. Yanıtın JSON gövdesindeki `exception` alanı, `org.springframework.expression.spel.SpelEvaluationException` olarak belirtilmiştir. Bu hata, sunucunun bir SpEL ifadesini değerlendirmeye çalışırken sorun yaşadığını açıkça gösterir. Bu, bir EL enjeksiyon zafiyeti için çok güçlü bir kanıttır.

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.

  1. Doğrulama: #{7*7} gibi basit bir matematiksel ifade gönderip yanıtta 49 değerini aramak, ifadenin çalıştığını doğrular.
  2. 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.Runtime sınıfına erişip exec() metodunu çağırarak komut çalıştırabilir.
  3. Payload Oluşturma: Genellikle java.lang.Runtime.getRuntime().exec('command') yapısını hedefleyen karmaşık bir SpEL ifadesi oluşturulur.
  4. 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 sistemde python -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.