LDAP Injection: Dizin Servisi Enjeksiyonu, Saldırı ve Korunma
Kurumsal giriş çoğu zaman Active Directory veya LDAP dizinine sorgu atar. Kullanıcı girdisi LDAP filtresine temizlenmeden karışırsa saldırgan özel karakterlerle kimlik doğrulamayı atlayabilir veya dizinden bilgi çekebilir. LDAP injection nasıl çalışır, filtre atlatma örnekleri ve karakter kaçışı ile korunma.
Hızlı cevap: LDAP injection, bir uygulamanın kullanıcı girdisini bir LDAP (dizin servisi, örneğin Active Directory) sorgu filtresine temizlemeden eklemesi sonucu filtre mantığının değiştirilmesidir. Kurumsal uygulamaların çoğu girişte kullanıcıyı dizinde arar; filtre
(uid=girilen_ad)gibi kurulur. Saldırgan kullanıcı adına*veya*)(uid=*))(|(uid=*gibi özel karakterler koyarsa filtre her kullanıcıyla eşleşir ve kimlik doğrulama atlanabilir ya da dizinden yetkisiz bilgi çekilebilir. Özel karakterler LDAP'ta anlam taşır:(,),*,\,&,|,=, NUL. Çözüm girdiyi LDAP kaçış kurallarıyla temizlemek (her özel karakteri kaçırmak), girdiyi beklenen biçime doğrulamak ve mümkünse parametreli/çerçeve-yönetimli sorgu kullanmaktır.
LDAP injection az konuşulan ama kurumsal ortamlarda yüksek etkili bir açıktır, çünkü doğrudan merkezi kimlik altyapısına (Active Directory, kurumsal dizin) dokunur. SQL ve NoSQL injection kadar tanınmaz, bu yüzden geliştiriciler çoğu zaman özel karakterleri kaçırmayı atlar. Bu rehber LDAP filtre söz diziminin neden saldırıya açık olduğunu, en sık görülen atlatma örneklerini, nasıl tespit edildiğini ve doğru savunmayı anlatır.
LDAP filtresi nasıl çalışır ve neden açık verir
LDAP sorguları, özel bir filtre söz dizimi kullanır. Örneğin bir kullanıcıyı bulmak için (uid=ahmet), iki koşulu birleştirmek için (&(uid=ahmet)(parola=123)) yazılır. Burada & "ve", | "veya", * "herhangi bir şey" (joker), parantezler ise koşulları gruplar. Bu karakterler filtrenin kontrol karakterleridir.
Sorun, uygulama kullanıcı girdisini bu filtreye doğrudan eklediğinde ortaya çıkar. Giriş filtresi (&(uid=GIRDI)(parola=GIRDI)) biçiminde kuruluyorsa ve saldırgan kullanıcı adı alanına * yazarsa, filtre (&(uid=*)(parola=...)) olur ve uid=* tüm kullanıcılarla eşleşir. Daha güçlüsü, saldırgan kullanıcı adına admin)(&) benzeri bir yük koyarak filtrenin yapısını kırabilir ve parola koşulunu etkisiz hale getirebilir. Bu, SQL injection'daki ' OR '1'='1 kalıbının LDAP karşılığıdır: kök neden aynıdır, girdi veri yerine sorgu yapısı olarak yorumlanır.
En sık görülen saldırı biçimleri
| Teknik | Yük örneği | Etki |
|---|---|---|
| Joker ile eşleşme | kullanıcı adı * |
Herhangi bir kullanıcıyla eşleşme |
| Filtre yapısını kırma | *)(uid=*))(|(uid=* |
Parola koşulunu etkisizleştirme |
| Her zaman doğru koşul | admin)(&) benzeri |
Kimlik doğrulama atlatma |
| Kör bilgi çıkarımı | öznitelikleri tek tek deneme | Dizinden veri sızdırma |
| Yetki özniteliği sorgulama | grup/rol filtresini manipüle etme | Yetki bilgisini sızdırma |
Kör çıkarım, NoSQL'deki $regex saldırısına benzer: saldırgan bir özniteliğin değerini doğrudan göremese de, filtreyi karakter karakter deneyerek (yanıt değişiyor mu diye) değeri çıkarabilir. Dizin servisleri kullanıcı, grup, rol, e-posta, telefon gibi hassas öznitelikleri tuttuğu için başarılı bir LDAP injection ciddi bilgi sızıntısına yol açar. Active Directory'ye yönelik iç-ağ saldırı tekniklerini Active Directory iç ağ sızma testi yazımızda ayrıca ele aldık.
Nasıl tespit edilir
Tespit, LDAP özel karakterlerinin filtreyi etkileyip etkilemediğini test etmekle başlar. Pentester giriş veya arama alanına *, (, ), \, &, | gibi karakterler ve *)(uid=* gibi yükler göndererek davranışın değişip değişmediğine bakar: giriş beklenmedik biçimde başarılı oluyor, arama daha fazla sonuç dönüyor veya farklı bir hata çıkıyorsa açık işaret verir. Tek bir * ile tüm sonuçların dönmesi klasik bir kanıttır.
Bu testler meşru isteği yakalayıp girdiyi değiştirerek yapılır; Burp Suite rehberimizde anlattığımız akış burada da geçerlidir. Enjeksiyon sınıfının genel mantığı için OWASP Top 10 web uygulama güvenliği yazımıza bakılabilir; LDAP injection aynı A03 Injection maddesinin dizin-servisine uygulanmış halidir.
Doğru savunma: kaçış, doğrulama, parametreli sorgu
LDAP injection'ın çözümü, kullanıcı girdisinin filtre yapısını değil yalnızca aranan değeri belirlemesini garantilemektir:
- LDAP özel karakter kaçışı. Girdiyi filtreye koymadan önce LDAP kaçış kurallarına göre temizleyin. RFC'de tanımlı kaçış şöyledir:
*→\2a,(→\28,)→\29,\→\5c, NUL →\00. Olgun LDAP kütüphaneleri bunu yapan bir kaçış/filtre-oluşturucu fonksiyon sunar; elle birleştirme yerine onu kullanın. - Girdi doğrulama. Kullanıcı adı gibi alanlar için beklenen biçimi (örneğin yalnızca harf, rakam, sınırlı karakter) zorlayın; özel karakter içeren girdiyi daha filtreye ulaşmadan eleyin.
- Çerçeve/parametreli sorgu. Mümkünse girdiyi filtre metnine string olarak eklemek yerine, kütüphanenin güvenli filtre-oluşturma API'sini kullanın; bu, kaçışı otomatik ve tutarlı yapar.
- En az yetki ile bağlanma. Uygulamanın dizine bağlandığı servis hesabı yalnızca ihtiyaç duyduğu öznitelikleri okuyabilsin; bir enjeksiyon başarılı olsa bile sızacak bilgi sınırlı kalsın. Kimlik doğrulamayı dizinde arama-sonra-bağlanma (search then bind) biçiminde yapın, girdiyi doğrudan parolayla aynı filtreye koymayın.
- Hata mesajlarını genelleştirin. Ayrıntılı LDAP hataları saldırgana filtre yapısını ele verir; istemciye genel mesaj dönün, ayrıntıyı sunucu loguna yazın.
Kurumsal kimlik yönetimi tarafındaki genel ilkeleri IAM kimlik ve erişim yönetimi yazımızda ele aldık.
KAOS ve DSET yaklaşımı
DSET olarak kurumsal uygulamaların giriş ve dizin-arama uç noktalarını LDAP injection'a karşı özellikle test ederiz, çünkü bu açık merkezi kimlik altyapısına dokunduğu için etkisi büyüktür ve az bilindiği için sahada sık bırakılır. Testlerimizde LDAP özel karakterleri ve filtre-kırma yükleriyle giriş ve arama alanlarını zorlar, açığı yalnızca tespit etmez, atlatılan kimlik doğrulamayı veya sızdırılan dizin bilgisini kanıtlayarak doğrularız. Geliştirdiğimiz KAOS aracı, kullanıcı girdisini kaçışsız biçimde LDAP filtresine birleştiren kalıpları işaretler, ama son kararı kanıta bağlar. Active Directory veya LDAP entegrasyonlu uygulamanızı test ettirmek için Ankara Hacettepe Teknokent'teki ekibimizle DSET ile iletişime geçin.
Sık sorulan sorular
LDAP injection ile SQL injection arasındaki fark ne?
Kök neden aynıdır: kullanıcı girdisinin veri yerine sorgu yapısı olarak yorumlanması. Fark söz dizimindedir. SQL'de tırnak ve anahtar kelimeler, LDAP'ta ise filtre kontrol karakterleri (*, (, ), &, |) kullanılır. Savunma da benzerdir: girdiyi kaçırın/doğrulayın ve yapı ile değeri ayırın. LDAP injection kurumsal kimlik altyapısına dokunduğu için etkisi çoğu zaman daha kritiktir.
Sadece * girmek giriş atlatmak için yeter mi?
Uygulama filtreyi nasıl kurduğuna bağlıdır. Bazı zayıf tasarımlarda kullanıcı adına * koymak tüm kullanıcılarla eşleşmeye ve ilk hesapla girişe yol açabilir. Daha yaygın olarak, filtre yapısını kıran (*)(uid=* gibi) yükler parola koşulunu etkisizleştirir. Her iki durumda da çözüm özel karakterleri kaçırmak ve arama-sonra-bağlanma akışını kullanmaktır.
Olgun bir LDAP kütüphanesi kullanıyorum, yine de risk var mı? Kütüphanenin güvenli filtre-oluşturma API'sini kullanırsanız risk büyük ölçüde kapanır. Risk, geliştiricinin girdiyi elle string birleştirmeyle filtreye koymasıyla ortaya çıkar. Yani asıl mesele kütüphanenin varlığı değil, doğru kullanılmasıdır: kaçış fonksiyonunu veya parametreli filtre API'sini kullanın, asla ham birleştirme yapmayın.
Kaynaklar
- OWASP Web Security Testing Guide, testing for LDAP injection bölümü.
- OWASP Top 10, A03 Injection maddesi.
- CWE-90 (improper neutralization of special elements used in an LDAP query) ve RFC 4515 LDAP filtre kaçış kuralları.
- DSET blog: Active Directory iç ağ sızma testi ve IAM kimlik ve erişim yönetimi.
Kimliğinizi doğrulayın
Yetkilendirilmiş erişim alanı. Tüm giriş denemeleri kayıt altına alınır.