Exploring the Vulnerability That Affected Equifax Using ShiftLeft Technology

In this blog I discuss using ShiftLeft technology to discover vulnerabilities in Java application code. In so doing I build on two prior blog posts from my colleagues: Fabian Yamaguchi’s introduction to the backbone technology of ShiftLeft, our code-property-graph (CPG); and Vlad Ionescu’s discussion of how a simple coding mistake can lead to major problems. Prophetically, the vulnerability Vlad blogged about was later revealed to have been the culprit behind the now infamous Equifax breach.

The question I want to answer in this blog post is this: How can we discover this vulnerability using ShiftLeft technology?

Background on the Vulnerability

First, let me clarify something about the Apache Struts vulnerability CVE-2017–5638. Although Apache assigned two bulletins to this CVE (S2–045 and S2–046), each maps to the same sink:

parser.evaluate(openChars, expression, ognlEval, maxLoopCount)

The difference is the injection vector, which we call the source. Equifax only committed to the CVE, not to a specific source. To keep it simple I focus on the S2–045 source for this example.

What makes this vulnerability intriguing, not to mention dangerous, is that it stems from improper error handling that causes an exception to be thrown. The issue is that the HTTP-header parameter Content-Type is not properly handled after throwing the error. The header content is then used by another function to construct the error message, which is then interpreted and evaluated as an OGNL expression. An attacker can simply provide such a message via the Content-Type header value and execute system commands.

For example, a request such as the following is enough to trigger the exception and remotely execute an injected payload:

POST /struts2-showcase/fileupload/doUpload.action HTTP/1.1
Host: localhost:8080
User-Agent: firefox
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: [OGNL code]Content-Length: [length]

I have left out the Content-Type payload because my purpose is to find the vulnerability in the bytecode, not to demonstrate exploiting possibilities. Suffice to say (and history has shown) it is not difficult to do, made even more easy by readily available exploits.

Exposing the Vulnerability

The vulnerability requires two steps to expose:

  1. Trigger the exception to find the data flow from the source to a sink where the exception gets handled; and
  2. Determine where the payload (containing the Content-Type header that an attacker can exploit) gets evaluated.

Let’s look at the ShiftLeft Dashboard for an example struts-based application (called “Social App”) that lets users update their profiles (status, pictures, etc.).

The App Summary View provides the security profile for the example app.

In ShiftLeft the data source is called a “Trigger,” and they appear in the left column of the dashboard. In our example we see a set of web triggers. These are the endpoints that trigger an application flow. In this case the /profile/update endpoint triggers an exception if there is failed file upload.

For this example the trigger and source are the same, but this might not always be the case. For example, the actual data source might be external to the app (such as a database), while the trigger is a method in the app that interacts with the source.

In the center-top of the App Summary View you see that the vulnerability is detected and classified based on the OWASP category “Insufficient Attack Protection,” which are prevalent and easy to exploit. In ShiftLeft, a vulnerability discovered during code analysis is a violation. If we see it at runtime via the microagent it is an incident that can trigger an alert.

Finding the Data Source

The S2–045 description states: “Possible RCE when performing file upload based on Jakarta Multipart parser.” With only this little information we are able to find the source by drilling into the Data Flow for the app. Here we see the JakartaMultiPartRequest.parse() method. The HttpServletRequest parameter that is passed to the parse() method is our data source.

Finding the Data Sink

So where to go from here? Now that we have our data source, we need to find the sink. We track all flows from the entry point to its logical output. Let’s focus on the following method that appears as the last line of the Data Flow:

org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest()

If we look at the Apache commons documentation for this method, we see it throws a FileUploadException if there are problems parsing the request or storing files. Since from here we are leaving the application to a library function that is operating correctly, we can take the FileUploadException method as our sink.

At this point we have found a data flow to trigger the exception and expose the vulnerability. The source is the HttpServletRequest parameter of the parse method. The sink is the RequestContext that is the only parameter for the parseRequest method from the apache.commons.fileupload library.

Executing the Payload

Let’s turn our attention to the second part of discovering the vulnerability: determining where the payload gets evaluated. For this we need to know something about Apache Struts.

The struts codebase includes and executes an Interceptor stack. Each interceptor implements an intercept() method. Since we are looking for a file upload operation, the intercept() method of the FileUploadInterceptor class can be used as source for this Data Flow.

From here we follow the flow to the sink and find the parameter expression, which holds our payload in the translateVariables() method. This input is forwarded to the Textparser.evaluate() method where it is executed.

With this we have identified the source intercept(ActionInvocation invocation) (line 237) and the sink TextParser.evaluate (last line), resulting in a complete data flow from the parameter invocation of the intercept method to the expression parameter from the evaluate method. The wrapper class LocalizedMessage is created to hold the exception payload until it is executed.

Conclusion

In this blog I have briefly demonstrated how we use ShiftLeft technology to discover code vulnerabilities by identifying and tracking the flow of sensitive data from source to sink.

To get started with ShiftLeft, sign up at https://www.shiftleft.io and try our Quickstart tutorial where you can use ShiftLeft to analyze a sample app.


Exploring the Vulnerability That Affected Equifax Using ShiftLeft Technology was originally published in ShiftLeft Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

*** This is a Security Bloggers Network syndicated blog from ShiftLeft Blog - Medium authored by Niko. Read the original post at: https://blog.shiftleft.io/discovering-code-vulnerabilities-using-shiftleft-technology-2b5edc4175b9?source=rss----86a4f941c7da---4