JAVA Object Serialization has been in use in many applications for a long time now. I find many enterprise applications that make use of JAVA Object Serialization to transfer objects from the client to sever and vice-versa. Testing such applications is a pain as it is not as straight forward as normal web applications that make use of simple parameter and value in HTTP POST data.
Some applications g-zip the serialized data before transferring it. Most common protocol for such applications is HTTP and RMI. There aren’t many easy techniques available today to test such applications and even if they do, they have certain shortcomings. At BlackHat EU this year, I discussed a technique that could be used to test such applications using currently available tools.
For testing web applications, the best tool available by far is Burp Proxy. It is one of my preferred tools to perform security assessments. You can refer to the whitepaper and the slides for details of the talk. In this blog post I will discuss the setup and a short introduction of how to carry out such assessments. The pre-requisites for using this technique are:
- Burp Proxy v.1.2.x
- JRuby v.1.4.x
- Buby v. 1.8.x
- Editor of your choice to edit the JRuby code
- Some knowledge of JAVA Object Serialization
First make sure that the usual 'JAVA_HOME' and 'PATH' environment variables are set for JAVA and JRuby. Once you have JAVA and JRuby setup properly, install the Buby gem. The details for installing Buby are given on its help page. Just make sure to copy the 'burp.jar' file in the JRuby load path. You can find the JRuby load path as follows in the IRB shell:
You can download the code that I released at BlackHat for the demo from here. It is a plug-in template that does three things:
- Injects an (J)IRB shell in the Burp Proxy
- Provides a method that de-serializes the JAVA Object stream (this can be modified to suit your needs e.g un-zip stream before de-serializing, etc.)
- Provides helper methods that use JAVA Reflection to access private variables and other useful methods
All the client-side jars should be placed in the lib folder provided by the plug-in. The plug-in will automatically import all the jars contained in this directory on startup. For the purpose of demonstration we would use a simple scenario where the JAVA serialized object is passed in a POST data of a HTTP request from the client to the server and vice-versa as shown in the figure below.
Once this sort of data is intercepted by Burp; our plug-in steps into action. Burp passes the entire message (headers + POST data) as a JAVA byte array to the plug-in which then splits the message into header and data and tries to de-serialize the JAVA Object. Once the JAVA Object is read, the plug-in spawns a (J)IRB shell exposing a variable obj which contains the JAVA Object. Now the pentester has the option of playing around with a complete development environment using the shell and editing the object at will. Once you are done modifying the object, you can use the helper methods to pack the object and create a new message (JAVA byte array) and return it to Burp to pass it to the application server.
For a more detailed demonstration watch the video
Is it possible to apply with java webstart which behaves like a thick java client communicating with the server?ReplyDelete
@pornsookk Yes this can also be applied with java webstart. Any serialized object in java that is transferred over HTTP can be edited by this technique.ReplyDelete
The technique and tool you did is very cool, but I did get stuck when the application run on other JVMs like ibm-java2--jre-50. Anyway, I appreciate your works!! :)ReplyDelete
@pornsookk Glad you find it useful. I haven't tried it on any other JVM than the standard one that is provided by SUNReplyDelete
Thanks for DSER! playing with it, I try to understand how you match "\xac\xed", have to say I don't see the relation with find_index(-84) and find_index(-19).. Sorry for the certainly lame question, being very newbie with ruby, must be something I don't get (I try to gunzip some data before you match p_start so must do a similar search but with gzip magic number)
Hex AC = 172 Dec --> 172-256 = -84ReplyDelete
Hex ED = 237 Dec --> 237-256 = -19
256 is the number of ASCII chars.
raaaahh shit.. ok no excuse for me.. thanks a lot! will let you know if it goes ok when I can test again next week.ReplyDelete
i followed the steps provided above. when i do JRuby Dser.rb, the Burp starts. However, I don't get the interactive shell. Is there any extra setting that i need to follow.ReplyDelete
Great job! Is it still working with the current version of BURP? I am getting "NameError: uninitialized constant DSer::PK" error on the console so I was wondering if my setup was wrong or it does not work with the current burp version.ReplyDelete