Today we release another Java tool from the Serially toolkit. This tool can be used for advanced Java Deserialization attacks, when existing gadget chains don’t work or when there is a whitelist mechanism in place (like LookAheadDeserialization). In that case we have to work with the classes that are in the whitelist and thus accepted by the application. Instead of sending a gadget chain containing classes not familiar in the application, the idea is to modify the existing serialized objects that are used by the application during normal operations.
WARNING! This tool will deserialize input that it is given. It is therefore vulnerable to deserialization attacks by definition. Please make sure the input you use is not malicious, and/or use the tool in an isolated sandboxed environment.
The probability to achieve RCE this way is pretty small, however in this kind of attack something like an authorization bypass is much more likely. Let’s discuss an example on how to perform the Java serialized object modifcation. Imagine an object that contains information about a user. It may contain values like ID, username and references to an object that defines roles and permissions. If we spot this object in serialized form on the wire, we can feed it to SerialTweaker in the following way:
We feed the Base64-encoded version of the serialized object directly on the command line as argument of ‘-b’. SerialTweaker will decode it to a raw serialized object and analyze it via a customized implementation of
ObjectInputStream. This customized version captures all classes which are inside the serialized object, so we can create a list of classes that are needed to perform deserialization. Note that in order to deserialize the object locally, the Java runtime must have the required classes in the classpath. Therefore we use the same technique as with EnumJavaLibs: we keep a local repository of jar files and dynamically load what is needed.
So once the analysis finished, SerialTweaker preloads the required libraries. The next step is to attempt deserialization. If it encounters a class that is present in multiple jar files, it will prompt the user to choose which library to load from. In our case, the classes are directly traceable to the jar file “UserDb.jar”, so no prompt is shown. The big integers following the class names are the SerialVersionUID’s of the class.
When deserialized, the contents of class variables are printed. These are values which are normally encoded within the serialized object, and thus values that we can modify. Keep in mind that static and transient variables are not serialized by default. SerialTweaker will print them and allow you to modify them, because there can be implemented a
writeObject() method in the class that does serialize them. But in the default case it will not work to modify these values because they are not serialized. A warning “(not serialized by default)” will be printed after the variable output to remind the user of this behavior.
In our example, the 3rd field of the User class is a reference to a Roles object. SerialTweaker recognizes references and will print nested classes. The Roles class contains a boolean variable, which we would like to change to
Next, the user is prompted if he wants to perform any modifications. We type the id of the field we want to change (3), and the new value for it (T, for true). SerialTweaker prints the modified version of the object to confirm the modification was successful. If we’re done making changes, the modified object is serialized and the Base64 output is printed to the user.
An interesting subject of serialized object modification might be JSF viewstates. When configured to store state client side, JSF websites will ship back- and forward a serialized object with every request. It’s usually a large object containing information about the state of UI elements. Changing these values might give an attacker opportunity to bypass certain restrictions.
SerialTweaker has a special ‘viewstate mode’, which will grab and decrypt (with ‘-k’) the viewstate from a given URL. Use the ‘-v’ flag to supply the URL.
There are already existing tools out there that can modify serialized objects. The difference is that they work by modifying the serialized object directly, working on a much lower level. This method is error-prone, because the serialized object contains various length fields and references, which need to be updated accordingly. SerialTweaker can make much more advanced modifications, but it comes with a price. You need to have the classes in your classpath in order to be able to deserialize them. Modifying values inside custom classes is therefore not possible with this approach.
The local repository of jar files is expected in
~/.serially/jars and should be indexed by using JavaClassDB.py from the EnumJavaLibs project.
The tool is released on our GitHub page.