Jump to content
Nytro

When EL Injection meets Java Deserialization

Recommended Posts

0. The story

A target during my pentest was using Java Server Faces (JSF) with an UI framework namely Jboss Richfaces. After exploiting the target using CVE-2013-2165 on Richfaces 4 (covered at my last post), I caught Codewhitesec’s blog post [1] about a new 0-day vulnerability in the Richfaces library. @mwulftange made a well-written research summary into his discovery with many of the details worth paying attention to, especially for a new learner in Java security like myself. Most parts sound ambiguous and unclear to me at the time, so I decided to give it a deeper look, reproduce the analysis and turn it into a working exploit.

The vulnerability, which was assigned CVE-2018-12532, couples Expression Language (EL) Injection with Java deserialization in Richfaces 4.x. Unlike a common vulnerability that triggers after a couple of requests, this takes some more effort to get to the RCE. This blog post aims to help with the path to achieve a reliable RCE exploit, based on the experience of exploiting it in public applications.

In short, I’m gonna talk about a technique to get around the main obstacle in exploiting the vulnerability – incompatible library restrictions in deserialization process. There will also be some insights on Java EL expression and its limitations, along with a payload to reliably get through them.

1. The treasure…

I recommend reading through the the other blog first for an overview of the vulnerability. Briefing through it, the vulnerability lies in the arbitrary injection of EL expression into Java serialized object, which Richfaces fetches from user input without any proper protection.

Richfaces’ security history (a.k.a. CVE history) all originate from the way a resource handler processes a request, which is as follows:

-> Get processing class, say X from URI & get serialized state object for X from parameter do
-(1)-> deserialize state object
--(2)-> create an instance of X and restore its state
---(3)-> process X and produce corresponding response (images, videos, tables...)

And the corresponding vulnerabilities.

  • CVE-2013-2165 is an arbitrary deserialization issue, originating from phase (1)
  • CVE-2015-0279 is the injection of EL into serialized object, originating from phase (3)
  • The latest CVE-2018-12532 is simply a bypass of the previous CVE-2015-0279
  • The technique to be mentioned lies in phase (2)

 
Since CVE-2018-12532 is a mitigation bypass, exploting it would mostly be just the same as exploiting CVE-2015-0279. For that, it’s necessary to credit Takeshi Terada on the discovery of CVE-2015-0279 since it is the base for the vulnerability. Unfortunately his report to the Jboss team (also the only resource about the vulnerability) has yet to produce a reliable exploit and enough vulnerability information.

The EL injection vulnerability lies in a call to MethodExpression.invoke() in org.richfaces.resource.MediaOutputResource#encode. Matching to the above flow, X in this case is the class org.richfaces.resource.MediaOutputResource, and its state object is the EL expression itself. So in theory to exploit the vulnerability, we need to point the request’s endpoint to MediaOutputResource and construct a suitable serialized object to reach the vulnerable code line.

2. … in the middle of the sea

The interesting thing is that Richfaces utilizes the deserialization process to produce the expression input, unlike the usual flow which is to take a string input and turn it into an expression afterwards. This process raised some concerns to exploit the vulnerability, as quoted from the original researcher.

Exploitation of this vulnerability is not always that easy. Especially if there is no existing sample of a valid do state object that can be tampered with. Because if one would want to create the state object, it would require the use of compatible libraries, otherwise the deserialization may fail.

The deserialization failure he’s referring to is caused by either

  • Non existent classes in the target application’s classpath, meaning some classes exist in the local environment but are not present on the target’s application, or
  • If the classes do exist, an additional problem is mismatching UIDs, coming from the idea of Stream Unique Identifier. Simply talking, to successfully deserialize, the class in the serialized stream and the class in the current classpath must have the same variable serialVersionUID specified explicitly in the code. Or if the developer doesn’t specify one, it must have identical class signature (method names, types, modifiers…) which the application would use to compute the UID. Check out the reference above for the exact calculation.

 
This would mean a real pain in real-world exploits if the vulnerable application is using some unsual combination of libraries stack. If you have tried to exploit deserialization in JSF Myfaces before, these obstacles would look very much like trying to use the 2 gadgets Myfaces1 and Myfaces2 in ysoserial. The author of the gadgets did try to list some combinations of available EL implementations to overcome it there, but it won’t work reliably from the way I see.

While doing code reviews during the analysis, I came up with a way to overcome this in Richfaces 4, which makes exploiting the vulnerability more practical.

 

Articol complet: https://tint0.com/when-el-injection-meets-java-deserialization/

   
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...