Merhaba, "İleri Seviye Injection Saldırıları ve Savunma" modülümüze devam ediyoruz. Önceki dersimizde, belge tabanlı veritabanlarını hedef alan ve sorgu mantığını manipüle etmeye dayanan NoSQL enjeksiyon saldırılarını ve bunlara karşı geliştirilecek savunma stratejilerini analiz etmiştik.
Bu dersimizde, kurumsal altyapıların temel taşlarından biri olan ve genellikle kimlik doğrulama, yetkilendirme ve kaynak bilgilerini depolamak için kullanılan bir başka kritik servise odaklanacağız: LDAP (Lightweight Directory Access Protocol). Bu dersin amacı, LDAP enjeksiyon saldırılarının mekanizmasını analiz etmek, hem basit filtre manipülasyonuyla kimlik doğrulama atlatma tekniklerini hem de daha ileri seviye, Java ortamlarına özgü uzaktan kod çalıştırmaya (RCE) varabilen vektörleri incelemek ve son olarak bu saldırılara karşı güvenli LDAP sorgu filtreleri oluşturma prensiplerini tasarlamaktır.
LDAP Filtrelerinin Anatomisi ve Zafiyetin Kaynağı
LDAP, bilgiyi hiyerarşik bir ağaç yapısında saklar ve bu bilgilere erişmek için özel bir sorgu dili kullanır. Bu dilin temelini LDAP arama filtreleri oluşturur. Tıpkı SQL ve NoSQL sorguları gibi, bu filtreler de kullanıcı girdilerinden dinamik olarak oluşturulduğunda enjeksiyon saldırılarına açık hale gelir.
LDAP filtreleri, Lehçe notasyonu (prefix notation) olarak da bilinen bir sentaksa sahiptir. Karmaşık koşullar, & (AND) ve | (OR) gibi mantıksal operatörler kullanılarak iç içe geçmiş parantez yapılarıyla ifade edilir.

Örneğin, bir kullanıcıyı kullanıcı adı ve parolası ile doğrulamak için arka planda oluşturulan filtre şu şekilde olabilir:
(&(username=kullanici_adi)(userPassword=parola))
Eğer kullanici_adi ve parola değerleri, kullanıcıdan gelen girdilerle doğrudan birleştirilerek bu filtre oluşturuluyorsa, zafiyetin kapısı aralanmış olur. Saldırgan, (, ), *, &, | gibi özel karakterleri enjekte ederek bu filtrenin mantığını tamamen değiştirebilir.
Klasik LDAP Enjeksiyonu: Kimlik Doğrulama Atlatma
En yaygın LDAP enjeksiyon senaryosu, kimlik doğrulama mekanizmasını atlatmaktır. Saldırgan, kullanıcı adı alanına özel olarak hazırlanmış bir girdi göndererek parola kontrolünü etkisiz hale getirebilir.

Bu saldırı türü, SQL enjeksiyonundaki ' OR '1'='1 mantığına oldukça benzer. Amaç, orijinal sorgu mantığını kırıp her zaman doğru sonuç döndürecek bir koşul eklemektir.
LDAP Injection & Blind LDAP Injection
Sektörün klasikleşmiş makalelerinden olan bu Black Hat whitepaper'ı, LDAP enjeksiyonunun temellerini ve saldırı mantığını çok net bir şekilde açıklamaktadır.
Makalenin başından itibaren "AND LDAP Injection" bölümünün sonuna kadar okumanızı rica ediyorum. Okurken şu noktalara odaklanın: Temel Konsept: Bu giriş bölümü, saldırının SQL enjeksiyonu ile benzerliğini ve filtrelenmemiş kullanıcı girdilerinin nasıl bir zafiyete yol açtığını anlatır. AND Enjeksiyonu: Bu kısım, yukarıda görselle açıkladığımız kimlik doğrulama atlatma senaryosunu (slisberger)(&))) teorik olarak detaylandırır.
Blind LDAP Enjeksiyonu ile Veri Sızdırma
OSCP ve sızma testi deneyimlerinizden bildiğiniz gibi, her zaman doğrudan sonuç veya hata mesajı alamazsınız. Blind LDAP Injection, uygulamanın verdiği ikili (binary) yanıtlara (örneğin, "Giriş başarılı" / "Giriş başarısız", "Sonuç bulundu" / "Sonuç bulunamadı") dayanarak LDAP dizininden bilgi sızdırma tekniğidir.
Saldırgan, LDAP filtresinin izin verdiği joker karakterleri (*) ve karşılaştırma operatörlerini kullanarak dizine "doğru/yanlış" soruları sorar. Örneğin, bir kullanıcının parolasını harf harf tahmin etmek için aşağıdaki gibi filtreler enjekte edilebilir:
kullanici_adi)(&(userPassword=a*))-> Parola 'a' ile mi başlıyor?kullanici_adi)(&(userPassword=b*))-> Parola 'b' ile mi başlıyor?- ...
Doğru harf tahmin edildiğinde uygulama başarılı bir yanıt verir ve saldırgan bir sonraki harfe geçer. Bu süreç, otomatize edildiğinde oldukça etkilidir.
Golang For Hackers: LDAP Injector - Episode 01
IppSec'in bu videosu, bir Hack The Box makinesi üzerinde boolean tabanlı bir Blind LDAP enjeksiyonunun nasıl yapıldığını ve Golang ile nasıl otomatize edildiğini pratik olarak göstermektedir.
Lütfen videonun ilk bölümlerini izleyerek saldırının manuel olarak nasıl gerçekleştirildiğini gözlemleyin: Manuel Saldırı: Bu bölümde, IppSec, basit bir * (wildcard) enjeksiyonu ile kimlik doğrulamasını nasıl atladığını ve ardından parolasını bulmak istediği kullanıcı için boolean tabanlı bir saldırı planladığını anlatıyor. Burp Suite Analizi: Burada, saldırı isteklerini Burp Suite'te analiz ederek başarılı (303 Redirect) ve başarısız (200 OK with error) yanıtlar arasındaki farkı nasıl tespit ettiğini gösteriyor. Bu, blind saldırıların temelini oluşturan adımdır. Videodaki otomasyon kısmı Go dilinde olsa da, testPassword ve pruneCharset gibi fonksiyonların arkasındaki mantık, Python veya Bash ile script yazma tecrübeniz sayesinde size çok tanıdık gelecektir.
Bu tekniğin teorik altyapısı, booleanization ve charset reduction gibi optimizasyonları içerir. Saldırıya başlamadan önce parolada hangi karakterlerin kullanıldığını (*a*, *b* vb. sorgularla) tespit etmek (charset reduction), deneme sayısını önemli ölçüde azaltır.
LDAP Injection & Blind LDAP Injection
Aynı Black Hat makalesi, blind saldırıların teorik altyapısını ve pratik istismar adımlarını da detaylandırmaktadır.
Lütfen "Blind LDAP Injection" ve "Exploitation example" bölümlerini inceleyin. Özellikle şu adımlara dikkat edin: Temel Mantık: Bu kısım, uygulamanın ikili yanıtlarından faydalanarak nasıl doğru/yanlış soruları sorulabileceğini açıklar. İstismar Adımları: Bu bölümler, nitelik (attribute) keşfi, booleanization (bir değeri evet/hayır sorularına dönüştürme) ve charset reduction (karakter kümesini daraltma) gibi pratik teknikleri adım adım gösterir.
İleri Vektör: Java'da LDAP Enjeksiyonundan RCE'ye
LDAP dizinleri sadece metin tabanlı veriler saklamaz. Java uygulamaları, JNDI (Java Naming and Directory Interface) aracılığıyla LDAP dizinlerinde serileştirilmiş Java nesnelerini de depolayabilir. İşte bu noktada, basit bir girdi doğrulama hatası, Uzaktan Kod Çalıştırma (RCE) gibi kritik bir zafiyete dönüşebilir. Bu saldırı vektörü, Log4Shell zafiyetinin de temelini oluşturan mekanizmalarla yakından ilişkilidir.
Saldırı zinciri şu şekilde işler:
- Java uygulaması, bir LDAP araması yaparken
SearchControls.setReturningObjFlag(true)parametresini kullanır. Bu bayrak, LDAP sunucusuna "sadece nitelikleri değil, bulduğun girişle ilişkili Java nesnesini de (varsa) döndür" talimatını verir. - Saldırgan, bir şekilde (başka bir zafiyetle, aşırı yetkilerle vb.) LDAP dizinindeki bir girdiyi manipüle eder. Bu girdiye, uzak bir sunucudaki zararlı bir sınıfı işaret eden özel JNDI referans nitelikleri (
javaClassName,javaCodebase,javaFactory) ekler. Bu işleme LDAP Entry Poisoning denir. - Zafiyetli uygulama, zehirlenmiş LDAP girdisini
setReturningObjFlag(true)ile sorguladığında, JNDI mekanizması bu referansı görür. - JNDI,
javaCodebaseile belirtilen saldırgan sunucusuna bağlanır,javaFactoryile belirtilen zararlı sınıfı indirir ve çalıştırır. Sonuç: RCE.
Bu saldırının en endişe verici yanı, Spring Security gibi popüler framework'lerin bazı eski veya varsayılan yapılandırmalarında setReturningObjFlag(true) bayrağını otomatik olarak kullanmasıdır.
[PDF] HPE Security Fortify, Software Security Research - Black Hat
Bu Black Hat makalesi, LDAP ve JNDI arasındaki tehlikeli ilişkiyi ve bunun nasıl RCE'ye yol açabileceğini derinlemesine inceleyen ileri seviye bir kaynaktır. Kod inceleme ve mimari tasarım rolleriniz için oldukça değerli bilgiler içermektedir.
Makalede şu kritik bölümlere odaklanın: Object-returning Searches: Bu bölüm, zafiyetin temelini oluşturan setReturningObjFlag(boolean) metodunu ve nesne döndürme mekanizmasını açıklar. Java Schema ve İstismar Vektörleri: Bu iki bölüm, Java nesnelerinin (Serialized Objects, JNDI References) LDAP'ta nasıl temsil edildiğini ve javaCodebase, javaFactory gibi niteliklerin RCE için nasıl istismar edilebileceğini anlatır. Gerçek Dünya Örneği: Bu kısım, Spring Security'nin LDAP kimlik doğrulama sağlayıcısının bu zafiyetten nasıl etkilendiğini kod seviyesinde gösterir. Bu, kıdemli geliştiriciler için mükemmel bir "ne yapılmamalı" örneğidir.
Savunma Stratejileri ve Güvenli Filtre Oluşturma
Bir AppSec Mimarı olarak göreviniz, bu tür saldırılara karşı katmanlı savunma hatları tasarlamaktır.
1. Filtre Enjeksiyonuna Karşı Savunma
Bu, en temel ve en önemli adımdır. Kural basittir: Kullanıcıdan gelen hiçbir girdi, LDAP filtresine doğrudan eklenmemelidir. Bunun yerine, girdinin mutlaka "kaçış" (escaping) işleminden geçirilmesi gerekir.
LDAP filtreleri için özel anlam taşıyan karakterler şunlardır: (, ), &, |, =, *, ~, >, <, \ ve NUL (\00).
Güvenli bir filtre oluşturmak için bu karakterler, \ karakteri ve ardından karakterin ASCII değerinin iki haneli onaltılık (hex) temsili ile değiştirilmelidir. Örneğin:
(karakteri\28olur.*karakteri\2aolur.\karakteri\5colur.
Neyse ki bu işlemi manuel yapmanıza gerek yoktur. Kullandığınız programlama dili veya framework'ün bu iş için sağladığı kütüphaneleri kullanmalısınız.
- Java (Spring LDAP):
LdapEncoder.filterEncode(String value) - Python:
ldap.filter.escape_filter_chars(String value) - .NET:
System.DirectoryServices.Protocolskütüphanesindeki ilgili metodlar.
Bu, SQL'deki parameterized query'lerin LDAP'taki karşılığıdır.
2. RCE Vektörüne Karşı Savunma
LDAP Entry Poisoning gibi daha karmaşık saldırılara karşı savunma, mimari düzeyde önlemler gerektirir:
setReturningObjFlag(true)Kullanımından Kaçının: Uygulamanızın LDAP'tan Java nesneleri okumasına gerek yoksa, bu bayrağı kesinlikle kullanmayın veyafalseolarak ayarlayın.- LDAP Sunucusunu Sıkılaştırın: LDAP sunucusuna yazma izinlerini (ACL'ler) en az yetki prensibine göre katı bir şekilde yapılandırın. Uygulama servis hesabının, kullanıcı niteliklerini (özellikle
java*ile başlayanları) değiştirememesini sağlayın. - Modern Java Sürümleri Kullanın: Güncel Java sürümleri, JNDI üzerinden uzaktan kod tabanı yüklemeye karşı varsayılan olarak daha sıkı korumalar içerir (
com.sun.jndi.ldap.object.trustURLCodebase=false).
LDAP Injection & Blind LDAP Injection
İlk okuduğumuz makalenin sonuç bölümü, filtre enjeksiyonuna karşı temel savunma prensiplerini özetlemektedir.
Lütfen "Securing Applications against..." başlıklı bölümü okuyun. Burada özel karakterlerin filtrelenmesinin önemi vurgulanmaktadır.
Özet ve Sonraki Adımlar
Bu dersimizde, kurumsal altyapıların vazgeçilmez bir parçası olan LDAP servislerine yönelik enjeksiyon saldırılarını kapsamlı bir şekilde ele aldık.
Ana Çıkarımlar:
- LDAP enjeksiyonu, filtrelenmemiş kullanıcı girdilerinin LDAP arama filtresinin sentaksını bozmasıyla gerçekleşir.
- Bu saldırılar, kimlik doğrulama atlatma, bilgi sızdırma (blind tekniklerle) ve hatta Java ortamlarında JNDI istismarı yoluyla uzaktan kod çalıştırmaya (RCE) kadar varabilir.
- Birincil savunma, tüm kullanıcı girdilerini LDAP filtresine eklemeden önce standartlara uygun bir şekilde escape işleminden geçirmektir.
- Mimari düzeyde ise, LDAP'tan Java nesneleri okumaktan kaçınmak ve LDAP sunucusunun erişim kontrollerini sıkılaştırmak RCE riskini büyük ölçüde azaltır.
Böylece SQL, SSTI, NoSQL ve LDAP gibi farklı sistemleri ve paradigmaları hedef alan temel enjeksiyon türlerini tamamlamış olduk. Bir sonraki dersimizde, modern uygulama geliştirmenin ayrılmaz bir parçası olan soyutlama katmanlarına odaklanacağız. ORM (Object-Relational Mapper) ve Expression Language (EL) tabanlı enjeksiyon saldırılarını nasıl tespit edeceğimizi ve bu katmanların sunduğu kolaylıkların nasıl güvenlik zafiyetlerine yol açabileceğini inceleyeceğiz.