Deserialization
Last updated
Last updated
Serialization is the process of turning some object into a data format that can be restored later. People often serialize objects in order to save them to storage, or to send as part of communications.
Deserialization is the reverse of that process, taking data structured from some format, and rebuilding it into an object. Today, the most popular data format for serializing data is JSON. Before that, it was XML.
In many occasions you can find some code in the server side that unserialize some object given by the user. In this case, you can send a malicious payload to make the server side behave unexpectedly.
You should read: for learn how to attack.
Magic method used with serialization:
__sleep
is called when an object is serialized and must be returned to array
Magic method used with deserialization
__wakeup
is called when an object is deserialized.
__destruct
is called when PHP script end and object is destroyed.
__toString
uses object as string but also can be used to read file or more than that based on function call inside it.
If you look to the results you can see that the functions __wakeup
and __destruct
are called when the object is deserialized. Note that in several tutorials you will find that the __toString
function is called when trying yo print some attribute, but apparently that's not happening anymore.
If you have found a LFI that is just reading the file and not executing the php code inside of it, for example using functions like file_get_contents(), fopen(), file() or file_exists(), md5_file(), filemtime() or filesize(). You can try to abuse a deserialization occurring when reading a file using the phar protocol. For more information read the following post:
When the object gets unpickle, the function \_reduce___ will be executed. When exploited, server could return an error.
For more information about escaping from pickle jails check:
__proto__
and prototype
pollutionIf you want to learn about this technique take a look to the following tutorial:
This library allows to serialise functions. Example:
The serialised object will looks like:
You can see in the example that when a function is serialized the _$$ND_FUNC$$_
flag is appended to the serialized object.
Inside the file node-serialize/lib/serialize.js
you can find the same flag and how the code is using it.
As you may see in the last chunk of code, if the flag is found eval
is used to deserialize the function, so basically user input if being used inside the eval
function.
However, just serialising a function won't execute it as it would be necessary that some part of the code is calling y.rce
in our example and that's highly unlikable.
Anyway, you could just modify the serialised object adding some parenthesis in order to auto execute the serialized function when the object is deserialized.
In the next chunk of code notice the last parenthesis and how the unserialize
function will automatically execute the code:
As it was previously indicated, this library will get the code after_$$ND_FUNC$$_
and will execute it using eval
. Therefore, in order to auto-execute code you can delete the function creation part and the last parenthesis and just execute a JS oneliner like in the following example:
The interesting difference here is that the standard built-in objects are not accessible, because they are out of scope. It means that we can execute our code, but cannot call build-in objects’ methods. So if we use console.log()
or require(something)
, Node returns an exception like "ReferenceError: console is not defined"
.
However, we can easily can get back access to everything because we still have access to the global context using something like this.constructor.constructor("console.log(1111)")();
:
The package doesn’t include any deserialization functionality and requires you to implement it yourself. Their example uses eval
directly. This is the official deserialisation example:
If this function is used to deserialize objects you can easily exploit it:
In the following pages you can find information about how to abuse this library to execute arbitrary commands:
The main problem with deserialized objects in Java is that deserialization callbacks were invoked during deserialization. This makes possible for an attacker to take advantage of that callbacks and prepare a payload that abuses the callbacks to perform malicious actions.
Search inside the code for serialization classes and function. For example, search for classes implementing Serializable
, the use of java.io.ObjectInputStream
or readObject
or readUnshare
functions.
You should also keep an eye on:
XMLdecoder
with external user defined parameters
XStream
with fromXML
method (xstream version <= v1.46 is vulnerable to the serialization issue)
ObjectInputStream
with readObject
Uses of readObject
, readObjectNodData
, readResolve
or readExternal
ObjectInputStream.readUnshared
Serializable
Fingerprints/Magic Bytes of java serialised objects (from ObjectInputStream
):
AC ED 00 05
in Hex
rO0
in Base64
Content-type
header of an HTTP response set to application/x-java-serialized-object
1F 8B 08 00
Hex previously compressed
H4sIA
Base64 previously compressed
You can check if there is installed any application with known vulnerabilities.
Serialization Test
Feel free to use the next script to create all the possible code execution payloads for Windows and Linux and then test them on the vulnerable web page:
Install maven, and compile the project:
Java LOVES sending serialized objects all over the place. For example:
In HTTP requests – Parameters, ViewState, Cookies, you name it.
RMI – The extensively used Java RMI protocol is 100% based on serialization
RMI over HTTP – Many Java thick client web apps use this – again 100% serialized objects
JMX – Again, relies on serialized objects being shot over the wire
Custom Protocols – Sending an receiving raw Java objects is the norm – which we’ll see in some of the exploits to come
A class that implements Serializable
can implement as transient
any object inside the class that shouldn't be serializable. For example:
Some of your application objects may be forced to implement Serializable
due to their hierarchy. To guarantee that your application objects can't be deserialized, a readObject()
method should be declared (with a final
modifier) which always throws an exception:
The java.io.ObjectInputStream
class is used to deserialize objects. It's possible to harden its behavior by subclassing it. This is the best solution if:
You can change the code that does the deserialization
You know what classes you expect to deserialize
Because this call happens before a readObject()
is called, you can be sure that no deserialization activity will occur unless the type is one that you wish to allow.
A simple example of this shown here, where the the LookAheadObjectInputStream
class is guaranteed not to deserialize any other type besides the Bicycle
class:
Harden All java.io.ObjectInputStream Usage with an Agent
If you don't own the code or can't wait for a patch, using an agent to weave in hardening to java.io.ObjectInputStream
is the best solution.
Using this approach you can only Blacklist known malicious types and not whitelist them as you don't know which object are being serialized.
To enable these agents, simply add a new JVM parameter:
There are several products using this middleware to send messages:
So, basically there are a bunch of services using JMS on a dangerous way. Therefore, if you have enough privileges to send messages to this services (usually you will need valid credentials) you could be able to send malicious objects serialized that will be deserialized by the consumer/subscriber. This means that in this exploitation all the clients that are going to use that message will get infected.
You should remember that even if a service is vulnerable (because it's insecurely deserializing user input) you still need to find valid gadgets to exploit the vulnerability.
.Net is similar to Java regarding how deserialization exploits work: The exploit will abuse gadgets that execute some interesting code when an object is deserialized.
Search the source code for the following terms:
TypeNameHandling
JavaScriptTypeResolver
Look for any serializers where the type is set by a user controlled variable.
You can search for the Base64 encoded string AAEAAAD///// or any other thing that may be deserialized in the back-end and that allows you to control the deserialized type. For example, a JSON or XML containing TypeObject
or $type
.
The main options of ysoserial.net are: --gadget
, --formatter
, --output
and --plugin
.
--gadget
used to indicate the gadget to abuse (indicate the class/function that will be abused during deserialization to execute commands).
--formatter
, used to indicated the method to serialized the exploit (you need to know which library is using the back-end to deserialize the payload and use the same to serialize it)
--output
used to indicate if you want the exploit in raw or base64 encoded. Note that ysoserial.net will encode the payload using UTF-16LE (encoding used by default on Windows) so if you get the raw and just encode it from a linux console you might have some encoding compatibility problems that will prevent the exploit from working properly (in HTB JSON box the payload worked in both UTF-16LE and ASCII but this doesn't mean it will always work).
--plugin
ysoserial.net supports plugins to craft exploits for specific frameworks like ViewState
--minify
will provide a smaller payload (if possible)
--raf -f Json.Net -c "anything"
This will indicate all the gadgets that can be used with a provided formatter (Json.Net
in this case)
--sf xml
you can indicate a gadget (-g
)and ysoserial.net will search for formatters containing "xml" (case insensitive)
ysoserial examples to create exploits:
In the previous code is vulnerable to the exploit created. So if you find something similar in a .Net application it means that probably that application is vulnerable too.
Therefore the --test
parameter allows us to understand which chunks of code are vulnerable to the desrialization exploit that ysoserial.net can create.
Don't allow the datastream to define the type of object that the stream will be deserialized to. You can prevent this by for example using the DataContractSerializer
or XmlSerializer
if at all possible.
Where JSON.Net
is being used make sure the TypeNameHandling
is only set to None
.
If JavaScriptSerializer
is to be used then do not use it with a JavaScriptTypeResolver
.
If you must deserialise data streams that define their own type, then restrict the types that are allowed to be deserialized. One should be aware that this is still risky as many native .Net types potentially dangerous in themselves. e.g.
FileInfo
objects that reference files actually on the server can when deserialized, change the properties of those files e.g. to read-only, creating a potential denial of service attack.
Even if you have limited the types that can be deserialised remember that some types have properties that are risky. System.ComponentModel.DataAnnotations.ValidationException
, for example has a property Value
of type Object
. if this type is the type allowed for deserialization then an attacker can set the Value
property to any object type they choose.
Attackers should be prevented from steering the type that will be instantiated. If this is possible then even DataContractSerializer
or XmlSerializer
can be subverted e.g.
Execution can occur within certain .Net types during deserialization. Creating a control such as the one shown below is ineffective.
For BinaryFormatter
and JSON.Net
it is possible to create a safer form of white list control using a custom SerializationBinder
.
Try to keep up-to-date on known .Net insecure deserialization gadgets and pay special attention where such types can be created by your deserialization processes. A deserializer can only instantiate types that it knows about.
Try to keep any code that might create potential gadgets separate from any code that has internet connectivity. As an example System.Windows.Data.ObjectDataProvider
used in WPF applications is a known gadget that allows arbitrary method invocation. It would be risky to have this a reference to this assembly in a REST service project that deserializes untrusted data.
Ruby has two methods to implement serialization inside the marshal library: first method is dump that converts object into bytes streams (serialize). And the second method is load to convert bytes stream to object again (deserialize). Ruby uses HMAC to sign the serialized object and saves the key on one of the following files:
config/environment.rb
config/initializers/secret_token.rb
config/secrets.yml
/proc/self/environ
may also be dangerous.
You can read an explained PHP example here: , here or here
**** can help you generating payloads to abuse PHP deserializations.
Note than in several cases you won't be able to find a way to abuse a deserialization in the source code of the application but you may be able to abuse the code of external PHP extensions.
So, if you can, check the phpinfo()
of the server and search on the internet (an even on the gadgets of PHPGCC) some possible gadget you could abuse.
You can **[find here]() further information** about how to exploit this vulnerability.
For.
Web files with extension .faces
and faces.ViewState
parameter. If you find this in a wabapp, take a look to the .
If you want to learn about how does a Java Deserialized exploit work you should take a look to , , and .
You could try to check all the libraries known to be vulnerable and that **[Ysoserial ]( provide an exploit for. Or you could check the libraries indicated on . You could also use ** to search for possible gadget chains that can be exploited. When running gadgetinspector (after building it) don't care about the tons of warnings/errors that it's going through and let it finish. It will write all the findings under gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt. Please, notice that gadgetinspector won't create an exploit and it may indicate false positives.
Using the Burp extension you can identify which libraries are available (and even the versions). With this information it could be easier to choose a payload to exploit the vulnerability.
.
GadgetProbe is focused on ObjectInputStream
deserializations.
Using Burp extension you can identify vulnerable libraries exploitable with ysoserial and exploit them.
**Java Deserialization Scanner is focused on ObjectInputStream
** deserializations.
You can also use to detect deserializations vulnerabilities in Burp. This plugin will detect not only ObjectInputStream
related vulnerabilities but also vulns from Json an Yml deserialization libraries. In active mode, it will try to confirm them using sleep or DNS payloads.
****
Not all is about checking if any vulnerable library is used by the server. Sometimes you could be able to change the data inside the serialized object and bypass some checks (maybe grant you admin privileges inside a webapp). If you find a java serialized object being sent to a web application, you can use to print in a more human readable format the serialization object that is sent. Knowing which data are you sending would be easier to modify it and bypass some checks.
The most well-known tool to exploit HTTP deserializations is **[ysoserial]() ([download here]().
**Note that this tool is focused on exploiting ObjectInputStream
.
I would start using the "URLDNS" payload before a RCE payload to test if the injection is possible. Anyway, note that maybe the "URLDNS" payload is not working but other RCE payload is.
When creating a payload for java.lang.Runtime.exec() you cannot use special characters like ">" or "|" to redirect the output of an execution, "$()" to execute commands or even pass arguments to a command separated by spaces (you can do echo -n "hello world"
but you can't do python2 -c 'print "Hello world"'
). In order to encode correctly the payload you could .
You can use along with ysoserial to create more exploits. More information about this tool in the slides of the talk where the tool was presented:
****can be used to generate payloads to exploit different Json and Yml serialization libraries in Java.
In order to compile the project I needed to add this dependencies to pom.xml
:
Read more about this Java JSON library:
If you want to test some ysoserial payloads you can run this webapp:
The general idea is to override in order to restrict which classes are allowed to be deserialized.
Example:
Deserialization and ysoserial talk:
Talk about gadgetinspector: and slides:
Marshalsec paper:
Java and .Net JSON deserialization paper: , talk: and slides:
Deserialziations CVEs:
The Java Message Service (JMS) API is a Java message-oriented middleware API for sending messages between two or more clients. It is an implementation to handle the producer–consumer problem. JMS is a part of the Java Platform, Enterprise Edition (Java EE), and was defined by a specification developed at Sun Microsystems, but which has since been guided by the Java Community Process. It is a messaging standard that allows application components based on Java EE to create, send, receive, and read messages. It allows the communication between different components of a distributed application to be loosely coupled, reliable, and asynchronous. (From ).
The tool was created to connect and attack this services sending several malicious objects serialized using known gadgets. These exploits will work if the service is still vulnerable and if any of the used gadgets is inside the vulnerable application.
JMET talk:
Slides:
In this case you can use the tool in order to create the deserialization exploits. Once downloaded the git repository you should compile the tool using Visual Studio for example.
If you want to learn about how does ysoserial.net creates it's exploit you can .
ysoserial.net has also a very interesting parameter that helps to understand better how every exploit works: --test
If you indicates this parameter ysoserial.net will try the exploit locally, so you can test if your payload will work correctly.
This parameter is helpful because if you review the code you will find chucks of code like the following one (from ):
This means that in order to test the exploit the code will call
Take a look to to execute arbitrary code. If you already know the secrets used by the victim machine, **[read this post to know to execute code](exploiting-__viewstate-knowing-the-secret.md).**
Java and .Net JSON deserialization paper: , talk: and slides:
TODO: Review