October 8, 2012
Recently I stumbled upon a Java Rich Client pentest project. Fortunately, the communication was made via HTTP, so it was possible to manipulate requests and response with our favorite tool, Burp.
After a little bit of Google searching, I came across this very well-written article about Java serialization and tried out his tool: BurpDSer. After scratching my head off for a few hours, installing dependencies, and still not getting it to work (there’s some problem with IRB Shell not popping up), I began searching for alternative solutions. Luckily I found this excellent SANS blog which outlined high level steps to make a Burp Deserialization plugin. So I put together a simple implementation of that idea. I hope it will be helpful for pentesters as well as developers in dealing with serialized Java applications.
In this blog post, I will cover following information:
- Setup Burp proxy
- Inspect Java client
- Run BurpJDSer
- Fuzz for server errors
- Bypass client side controls
- Remediation path
BurpJDSer is a Burp plugin that will deserialize/serialize Java request and response to and from XML with the help of Xtream library. BurpJDSer utilizes native Java technology to deserialize/serialize Java request, thus no additional software is required.
Let’s consider this dummy Java app that communicates with a servlet via HTTP. It’s a very simple search box which sends SearchObject to a server. Server responses with a SearchResult object back. If it indicates that client has admin privilege, the gray text will become red.
Step 1: Set up Burp proxy
- If the program is started from the command line (java –jar client.jar), add the following flags:Dhttp.proxyHost=127.0.0.1 -Dhttp.proxyPort=<Burp port>
- If the program is started from browser (Java Web Applet), make sure JVM set to use browser proxy settings (Windows Control Panel > Java > Network Settings) or explicitly set to use Burp proxy.
- If the program communicates via HTTPS, import PortSwigger Root Certificate to your favorite browser.
Also consider these instructions from Burp author if the above method fails to intercept HTTP traffic: http://blog.portswigger.net/2009/04/intercepting-thick-client.html
Step 2: Download and Inspect Client jar
- Download the Java client to your computer. This can be done viewing HTML response from the page that loads Java applet. A sample applet tag that reveals location of the client jar file: <applet code=”com.example.client” archive=”SerializedClient.jar”/>
- Use any Java decompiler to decompile the target jar file. My favorite is JD-GUI from http://java.decompiler.free.fr/
- What to look for: any hardcoded passwords, backdoors, communication methods, SQL queries,etc.
Step 3: Run the BurpJDSer plugin
- Download all the executables here: https://github.com/khai-tran/BurpJDSer/tree/master/executables
- Run this command:
java -Djava.io.tmpdir=<tmp_folder> -classpath burp.jar;burpjdser.jar;xstream-1.4.2.jar;<client_jar> burp.StartBurp
Step 4: Inspecting traffic
- When setup properly, we should see some traffic captured by Burp.
- Essentially, what the plugin does is to convert serialized request to XML for you to modify, than convert back from XML to serialized object before sending to the server
- Similarly for the response, the plugin will deserialize to XML and then serialize back to Java object so that it won’t break the client.
- In this example, SSN is included in the response, but not shown in the client.
Step 5: Fuzzing for server error with Repeater and Intruder
- This plugin will also perform conversion of Java object when processed in Burp Repeater/Intruder for your convenience
- Fuzz for server vulnerabilities such as SQL Injection, Command Injection, Authorization Bypass, etc.
Step 6: Test for client-side authorization bypass
The plugin also has support for serializing requests/responses from XML to Java format. This may come in handy in case you need to bypass client check or enable hidden features of the client. Below is an example of how to do this
- Intercept server response
- Find and modify hidden parameter to access hidden priviledges. In this example, I set isAdmin parameter to “true” in order to bypass client-side restriction.
- Don’t rely on Java serialization as a method of encryption
- Don’t include redundant data in the response, even if it’s not displayed on client GUI
- Obfuscate your code: choose a obfuscator that also encrypts String constants such as ZelixClassMaster
- Validate input serialized data
- Consider sealing and signing serialized objects with javax.crypto.SealedObject
The source code and executable are available at: https://github.com/khai-tran/BurpJDSer. Feel free to leave comments there. Thanks to Scott and Antti for your feedback on the tool.