This is a follow up blog post to my previous post on auditing Google Web Toolkit (GWT). Today we are going to focus on a specific vulnerability that I found in a GWT endpoint that Matthias Kaiser helped me exploit. Please note that the code has been changed to protect the not so innocent whilst they patch.
I explain a semi-complex expression language injection vulnerability which is triggered in a Google Web Toolkit (GWT) endpoint.
Within the WEB-INF/web.xml file, I found the following endpoint mapping:
We can see that the above code references the server mapping. Since GWT works by defining client classes that denote which methods are available for the client to access, let’s start by looking at the corresponding client class com.aaa.bbb.ccc.ddd.client.SomeService:
There are three functions that look interesting that we can reach, lets strip them out of the server code and see what each one does. Reading the Java code in the main jar archive that contains the class SomeServiceImpl we find the following code:
Ok, so we can set a session attribute named MibWidgetBeanName with a string we can control. So far, nothing interesting. Let’s investigate the setMibNodesInfo function:
This function accepts a List type using a complex type MIBNodeModel. The mibNodeModelList2MibNodeList function will check to see if what we supplied was a valid List and return different strings based on what values are contained within the first element of the List.
If there are no values supplied in the our List, it will define a List and return it with a default instances of MIBNodeModel. Then, the getBeanByName function is callled. Let’s go ahead and investigate this function.
Since this is a private method, it’s not reachable via the client interface and we cannot call it directly. We can see on line 8 that we get that attribute MibWidgetBeanName again and store it into a string called localObject2.
This localObject2 variable is later used on line 14 for retrieving an expression. Classic expression injection vulnerability. Well, not so classic, but somewhat obvious after decompiling the code.
First of all, the observing reader will notice that this is not a reflective type of expression language injection. Meaning you cannot view the results of code executing to verify the vulnerability. Thus, I clasify it as a blind expression language injection vulnerability.
I digress by demonstrating an example. Suppose we have a vulnerability in a Java Servlet Faces (JSF) application that looks like so:
An attacker could simply perform the following request:
Since a browser translates the + as a space, we encode the + so that what we are really sending is 9+1 and upon server response, if we see a value of 10 then we know that we have an expression language injection vulnerability since the math operation executed. This is the method Burp Suite uses to detect template injection vulnerabilities.
However, given our vulnerable code above, we cannot easily determine an expression language injection vulnerability, or could we? After experimenting with the JSF api I found some very neat functions that allow us to fully determine the presence of a EL Injection vulnerability without making outgoing HTTP requests.
The oracle documentation states that you can use the getExternalContext method on the FacesContext instance. This method returns a ExternalContext type which can allow us to set specific reponse object properties. When I was investigating this, two functions came to mind:
Therefore, we could set the string to the following Java code:
…and if the response was a 302 redirect to https://srcincite.io/ then we can confirm the code is vulnerable.
Testing the vulnerability
The first request we need to do is to set the session attribute MibWidgetBeanName
With a server response of //OK[,0,6] we know that our GWT injection was successful. Then, the second request to trigger the stored in a session string, expression language injection. However, before we send that request, since we are using complex types for the setMibNodesInfo function, we need to look up the policy file that defines the available types allowed to send. Within the [strong name].gwt.rpc file, I found the following type value for ArrayList: java.util.ArrayList/382197682.
Now we can go ahead and use that type in the request:
The corresponding response, looks like this:
Updating the MibWidgetBeanName session attribute with that code and re-triggering the setMibNodesInfo function, launches commands as SYSTEM against my target:
Onto triggering the expression language injection…
There is almost no way this vulnerability would have been discovered from a black-box perspective. Common tools such as Burp Suite have no chance of currently detecting such vulnerabilities especially considering this particular case where the string is stored in a session attribute.
As web technologies progress forward, our need for automation increases and a lack of tools, skills and knowledge in this area allows many applications to stay vulnerable to critical code execution vulnerabilities for years.