Live data from Hacker News

Spring Core on JDK9 is vulnerable to remote code execution

praetorian.com

21–30 of 73 posts

Re: Spring Core on JDK9 is vulnerable to remote code execution

#21

There is a lot of bad information out there about this issue. What I have gathered so far, is that this is actually a real problem, but it may not affect most configurations. This[0] seems to be the original vulnerability analysis, and this is the example vulnerable app[1]. The main issue seems to be, that since java 9, WebDataBinder can be abused to access the classloader via the "class.module.classloader", you migh…

If you can access the classloader that's pretty bad, it's likely people will find other gadgets.

It's insane to me though that class.* isn't completely disallowed. What is the legitimate use case for deserializing allowing web requests to call setters in the reflection API?

Also, agree it is impressive to me how much bad information I've seen.

Re: Spring Core on JDK9 is vulnerable to remote code execution

#22

I am still deeply skeptical that this exploit really exists, or if it does, it is extremely exaggerated. I can’t really articulate the reasons why. Part of it is the fact that a lot of the people reporting on it self-admit that they are unfamiliar with Java and Spring. One “PoC” repo I’ve seen is just simple API misuse. API misuse is a CVE in the application that does the misusing, NOT the library that is misused (in…

I've spent most of my day on this and can confirm there is serious potential to this. It's not a log4shell but it's serious.

You're potentially vulnerable if you use POJOs as request parameters[0] with Spring MVC and Java 9+. To support complex POJOs (like a POJO in a POJO), Spring uses the `.` separator. Therefore, you can have a request GET /somePath?innerPojo.field=foo that will get mapped properly [1].

Now, in [2], the `getCachedIntrospectionResults()` result has a `class` parameter that I believe should not be exposed. In this object, there's a bunch of parameters that can be set, that's where the problem is. In the POC seen across the web today, it was modifying the `AccessLogValve` of Tomcat. The exploit mentioned in [3] relies on passing a parameter like this :

GET /somePath?class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp

This will access the `class` object and uses the `getModule` method of the `Class` object to get the `Module` class. Now, this class has the `ClassLoader` exposed via a getter BUT it's exposed as opposed to the `Class` class[4]! In the POC, it's an instance of `WebAppClassLoaderBase` (when using Tomcat, under some circumstances). This class has a `getResources` method that is accessed here, along with `getContext`, `getParent`, etc. all the way up to the last delimiter which invoke the `setSuffix` method of the `AccessLogValve` instance [5]. Rinse and repeat this to set the tone for the JSP vulnerability and you have a RCE.

Now, this needs some specific preconditions. However, there are probably hundred of other mutable objects accessible this way that could lead to pretty nasty bugs, vulnerability of information disclosures.

Finally, I can confirm that the workaround with `@InitBinder` mentioned in [6] works.

EDIT : Looks like a regression from CVE-2010-1622 that was fixed in [7].

[0] https://docs.spring.io/spring-framework/docs/3.2.x/spring-fr...

[1] https://gist.github.com/jebeaudet/127e6fb0b59e06c0642d2f362e...

[2] https://github.com/spring-projects/spring-framework/blob/mai...

[3] https://www.cyberkendra.com/2022/03/spring4shell-details-and...

[4] https://github.com/spring-projects/spring-framework/blob/mai...

[5] https://github.com/Oreste-Luci/apache-tomcat-8.0.26-src/blob...

[6] https://www.cyberkendra.com/2022/03/springshell-rce-0-day-vu...

[7] https://github.com/spring-projects/spring-framework/commit/3...

Re: Spring Core on JDK9 is vulnerable to remote code execution

#23
post #21

There is a lot of bad information out there about this issue. What I have gathered so far, is that this is actually a real problem, but it may not affect most configurations. This[0] seems to be the original vulnerability analysis, and this is the example vulnerable app[1]. The main issue seems to be, that since java 9, WebDataBinder can be abused to access the classloader via the "class.module.classloader", you migh…

If you can access the classloader that's pretty bad, it's likely people will find other gadgets. It's insane to me though that class.* isn't completely disallowed. What is the legitimate use case for deserializing allowing web requests to call setters in the reflection API? Also, agree it is impressive to me how much bad information I've seen.

Yea it didn't help that this was posted a bit after https://spring.io/blog/2022/03/29/cve-report-published-for-s... and that the original article mentioned a commit on the class `SerializationUtils` which in the end has no connection to this.

I believe accessing the `class` object here is a mistake. You can see my analysis here where I trace the POC https://news.ycombinator.com/item?id=30862953 but like you said, there are other problematic code paths for sure with this.

Re: Spring Core on JDK9 is vulnerable to remote code execution

#24
post #8

(Author that named "Log4Shell" here) FYI, this is confusing because there are 2 different RCEs that have been published within the last 24 hours. One has a CVE and the other doesn't. OP's post by Praetorian is discussing the RCE dubbed "Spring4Shell". It's the RCE without a CVE yet , hence the name, and it affects Spring Core. It's likely fairly widespread/severe, but the "mitigating details" are still unknown. That…

I have never seen that class SerializationUtils used in the wild. Now if it was in Jackson...

Re: Spring Core on JDK9 is vulnerable to remote code execution

#26

Earlier quoted context omitted.

Any kind of writable reflection facility, and any kind of eval() should be added to the set of "unsafe" features.

At some point, mvc frameworks have to do some magic to dynamically load classes. This should be done at runtime, but can’t imagine it’s an easy problem to solve.

Frameworks like Quarkus and Micronaut do this at compile time. They dynamically load things and record it, then insert the resulting bytecode statically in the build artifact. I believe the core motivator is performance, but it has the added benefit of eliminating most of the runtime magic that leads to vulnerabilities like this.

Re: Spring Core on JDK9 is vulnerable to remote code execution

#27
post #10

I am still deeply skeptical that this exploit really exists, or if it does, it is extremely exaggerated. I can’t really articulate the reasons why. Part of it is the fact that a lot of the people reporting on it self-admit that they are unfamiliar with Java and Spring. One “PoC” repo I’ve seen is just simple API misuse. API misuse is a CVE in the application that does the misusing, NOT the library that is misused (in…

I'm skeptical as well because everyone is saying they've reproduced it, but there's no CVE and none of them want to post the source code to reproduce it. It's all "use this closed source docker image" or "it was in this now deleted github" or "it was in this now deleted twitter leak".

> but there's no CVE

The notion of a National Vulnerability Database is noble, but creating a CVE is an incredibly slow moving and bureaucratic process. In situations like this, or Log4Shell, information evolves rapidly and is often outdated by the time it makes it to NVD. Log4Shell specifically was a disaster, where the original advisory text contained incorrect information that was corrected relatively quickly by Apache but did not update in NVD for weeks. This actively hurt the remediation efforts as people treated the description in NVD as the authoritative source for information and ignored evidence to the contrary.

Re: Spring Core on JDK9 is vulnerable to remote code execution

#28

Earlier quoted context omitted.

Any kind of writable reflection facility, and any kind of eval() should be added to the set of "unsafe" features.

At some point, mvc frameworks have to do some magic to dynamically load classes. This should be done at runtime, but can’t imagine it’s an easy problem to solve.

Not my field, but how can this be so? We had MVC in 1990 written in C or C++.

Re: Spring Core on JDK9 is vulnerable to remote code execution

#29
post #9

I am still deeply skeptical that this exploit really exists, or if it does, it is extremely exaggerated. I can’t really articulate the reasons why. Part of it is the fact that a lot of the people reporting on it self-admit that they are unfamiliar with Java and Spring. One “PoC” repo I’ve seen is just simple API misuse. API misuse is a CVE in the application that does the misusing, NOT the library that is misused (in…

LunaSec founder here. I can understand the suspicion. It's the right mindset to have when looking at CVEs, in general, because 99% of them are overblown. The first title I wrote for the blog post was "There is no vuln" but I was wrong. Only after I spent a few hours digging did my gut change my mind. In this case I wrote the post to discuss 2 different vulns. One was a confirmed RCE with a CVE and the other was a WIP…

The exploit PoC that is doing the rounds works on full tomcat, not embedded tomcat, so if your example vulnerable application is using embedded tomcat that exploit won't work on it without being tweaked.

I've looked at it today as well, for most of the day. Embedded tomcat doesn't have a webapps directory, whereas the full version of tomcat does, so the PoC writes the webshell to webapps//tomcatwar.jsp and that is served up then.

I'm on OSX and I found the temp directory that is created for the embedded tomcat at runtime but there's nothing deployed there, so I can't figure out where to write the webshell to or if it is even possible. I looked at the process with lsof and just followed the trail to find the directory but it's not working.

Anyway, embedded tomcat IS vulnerable, just not sure if it is exploitable.

To check if it is vulnerable you can do run the following curl command: curl "http://localhost:8080/?class.module.classLoader.URLs%5B0%5D=..."

If this returns status:400 then it is vulnerable, if not then it is not. If you have an app deployed to a different context path (so /my-webapp) then you'd need to run: curl "http://localhost:8080/my-webapp?class.module.classLoader.URL..."

I don't think it is common to use @RequestMapping in java and take in a POJO as a parameter to the request, but that is needed in order to be vulnerable to this.

I'm sure there's other gadgets that can be used to exploit this, the example we saw was using tomcat to write a webshell.

Re: Spring Core on JDK9 is vulnerable to remote code execution

#30
Not sure why it's tagged JDK9+, but 'class' attribute is accessible on org.springframework.beans.BeanWrapperImpl.getLocalPropertyHandler() in JDK 8 also. It probably doesn't matter which JDK is being used, as long as this spring-beans dependency is used.

Whether logging JSP exploit in JDK 8 or lower can be used is another question. However, since 'class' is accessible via request parameter, it's already bad and there will probably be some ways to exploiting it. It doesn't matter whether the request is GET or POST, as long as mapped controller method uses a non-primitive request object, 'class' can be accessed. 'class.module' attribute is accessible from Java 9 and above, I tested on Java 11 and can access 'class.module'. Sample code that I used to test this with JDK 8 is below. I just tested whether 'class' attribute can be accessed via request parameter.

curl -X POST localhost:8080/test?class.modifiers=Hello

package com.test;

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RestController;

    @SpringBootApplication
    public class Spring4ShellTestApplication {

    public static void main(String[] args) {
      SpringApplication.run(Spring4ShellTestApplication.class, args);
     }

    }
    @RestController
    class TestController {

    @PostMapping("/test")
     public String test(TestOuterRequest request) {

      String message = "Inner request is null";

      if (request.getInnerRequest() != null) {
       message = "your message was: " + request.getInnerRequest().getMessage();
      }

      System.out.println(message);

      return message;
     }
    }

    class TestOuterRequest {
     private TestInnerRequest innerRequest;

    public TestInnerRequest getInnerRequest() {
      return innerRequest;
     }

    public void setInnerRequest(TestInnerRequest innerRequest) {
      this.innerRequest = innerRequest;
     }
    }

    class TestInnerRequest {
     private String message;

    public String getMessage() {
      return message;
     }

    public void setMessage(String message) {
      this.message = message;
     }
    }
Finally here are the attributes that're exposed on 'class' as accessible properties in JDK 8 (JDK9+ adds 'module' on top of all these)

    annotatedInterfaces
    annotatedSuperclass
    annotation
    annotations
    anonymousClass
    array
    canonicalName
    class
    classes
    componentType
    constructors
    declaredAnnotations
    declaredClasses
    declaredConstructors
    declaredFields
    declaredMethods
    declaringClass
    enclosingClass
    enclosingConstructor
    enclosingMethod
    enum
    enumConstants
    fields
    genericInterfaces
    genericSuperclass
    interface
    interfaces
    localClass
    memberClass
    methods
    modifiers
    name
    package
    primitive
    signers
    simpleName
    superclass
    synthetic
    typeName
    typeParameters
Post reply on HN