Java
An Object-Oriented programming language often used in enterprise environments
Description
Java is an Object-Oriented programming language that compiles into Java bytecode. The Java Virtual Machine (JVM) understands this bytecode and can run it. You code it in .java
files and then there are a few more file types that the compiler goes through:
.java
files are Java Source Code.class
files are the compiled bytecode.jar
files are a package of.class
files (like a ZIP)JVM unpacks
.jar
and runs.class
bytecode
Hello World
Create a file that has the same name as the class:
Then you can either compile and run it directly using java
:
Or compile it to bytecode, and run it later:
Lastly, you can bundle the .class
files into a JAR with some information like the entry point. This requires a Manifest.txt
file with a Main-Class
key set to the main class. This class needs to have the main()
function we defined with its exact function signature.
In the above file, the extra newline at the end is important for some reason, don't forget it!
Afterward, you can bundle the files into a .jar
(source):
Libraries
Any programming language is made powerful by libraries. For Java, there are multiple build tools you can choose from for large projects, like Maven or Gradle. For a simple case, however, we can do this manually just using java
commands.
Inside our source code, we can import the classes from this JAR now with the path from mvnrepository:
After writing the code with this library that you want, use the classpath (-cp
) option while compiling to add the libraries to the compiled version:
Insecure Deserialization
The ObjectOutputStream.writeObject()
method can serialize an instance of an Object (that implements Serializable
) into binary data (ByteArrayOutputStream
). This can then be sent to any other system, which can reconstruct the Object by calling the ObjectInputStream.readObject()
method on the binary data (ByteArrayInputStream
).
Here is an example:
While this is useful and easy to implement, its flexibility has some security risks. The risk is an attacker passing serialized data to a deserializer with different types than the original type, or altering the data to make it malicious. In the above example, it expects to deserialize a Data
Object, but the byte array can hold any type to deserialize into.
After being deserialized, it would obviously not pass as a valid Data
Object, and not have a .name
attribute for example. But some code that still executes is the custom code that parses the byte array into an instance, which might still contain sensitive actions that you can perform at will:
The above could be some library function that the developer of this Example
doesn't know about. The default readObject
can be overridden in this way, with a .defaultReadObject()
still being available to run the default method still. Before or after though, a developer can choose to write any extra code that needs to be executed to correctly deserialize the data. In the above gadget, a dangerous exec(command)
call is included which can now be executed at will by the attacker by creating a malicious serialized object!
To exploit it, the attack must create and serialize a malicious object themselves, and then make the target deserialize it in some way:
When the target deserializes the payload, the command
attribute will be set and the exec()
command in readObject()
will be executed, launching a calculator on Windows.
While this example was very clear, most real-world exploits use multiple chained gadgets to eventually reach a sensitive function with user input. This is possible because attributes can be Objects as well, and their attributes can be more Objects, etc. Creating such a payload is very similar to the example above but just requires more new
objects in arguments like this:
ysoserial
Instead of searching and creating new gadget chains for every deserialization issue you find, often well-known chains in libraries used in many projects can be enough.
The ysoserial
tool contains a collection of payloads that work on different versions and libraries. Depending on which your target uses, any of these can be a quick win.
Use a payload by choosing the name as the first argument, and a fitting command as the second. A payload like CommonsCollections6
requires a command, so the following will generate it:
If you are receiving InaccessibleObjectException
or IllegalAccessError
, this is because Java >12 does not allow the way ysoserial accesses classes.
The --illegal-access=permit
argument can be added to fix it, but after Java 17 even this is not allowed. From there, explicit --add-opens
arguments need to be added which this gist can do for you.
Often the easiest fix however is to simply generate payloads with an older Java version.
DNS Probe using java.net
java.net
A useful payload for confirming an insecure deserialization vulnerability is URLDNS
in ysoserial. This has no dependencies and performs a DNS lookup of a URL you provide.
For a full explanation, see this page. The summary is that the java.net.URL
class has a .hashCode()
method that resolves the given URL and this method is automatically called when it is put into a java.util.HashMap
.
Start a DNS listener using Burp Suite Professional, or using interactsh
. Then generate the payload to execute on your target:
Runtime.exec()
to Shell
Runtime.exec()
to ShellFor a proof-of-concept, executing a simple program like calc.exe
on Windows may be enough. However, for Linux and more complicated payloads, you might require special bash
syntax like |
pipes or >
redirects. Take the following example:
It does not write to /tmp/pwned
, but instead, runs id
with the arguments '>'
and '/tmp/pwned'
:
For a reverse shell or more complicated proof-of-concept, you can circumvent this using a few different tricks.
The first uses $@
together with piping into |sh
to re-enable the use of these symbols, as a string is directly put into the STDIN of sh
. The following payload would work:
Some more tricks include using bash
with Base64 and the {,}
syntax, or using Python or Perl to evaluate code in a single command. Use the generator below to create these payloads easily:
Last updated