Application Security

Finding classes for exploiting Unsafe Reflection / Unchecked Class Instantiation vulnerabilities in Java with Joern

During a pentest engagement we found a Java application vulnerable to unsafe reflection [1]. This application allowed us to instantiate an arbitrary class with a controlled string passed to its constructor as argument. When we became aware of the dependencies used by the application, we posed the following question: How could we automate the process to find good classes?

For good class we mean classes that match the criteria (the constructor receives a string) and has security implications (could be used to exploit the application). This blogpost will document how we automated this process.

Motivation – CVE-2022-21724

The vulnerability we encountered during a pentest was PostgreSQL JDBC Driver Unchecked Class Instantiation (CVE-2022-21724) [9], in which an arbitrary class could be instantiated, taking a controllable argument of type string via JDBC URL. An example of payload can be seen below:


When looking for writeups we found some interesting attacks [10] [11] using classes from Spring and other libraries, such as:


However none of these classes were available in our target. Fortunately we managed to get access to the list of libraries used by the application with another vulnerability and with that we decided to automate the process of finding good classes for our attack.

Static Analysis

To address our problem we can employ static analysis with data flow, which aims to identify paths from data sources to data sinks where processing occurs. In this particular scenario, we define our sources and sinks as follows:

source – classes with constructors that accept string as arguments

sink – any method that could be used to exploit the application

After understanding the problem and defining our sources and sinks, we realized the need for a tool to aid in this analysis. Since we anticipated the need to analyze dependencies in cases where only the compiled Java code would be available, we sought a tool capable of running analysis directly on JAR files. Consequently, we opted to use Joern [2], which offers support for JAR files, as seen in [3].


For those who are unfamiliar with Joern, it is a code analysis platform that utilizes a structure known as Code Property Graph (CPG) [4]. This platform enables us to execute queries on code using a Scala-based language, facilitating comprehensive code analysis. We can also use Joern to perform dataflow analysis, for instance, take a look at this code snippet:


public class Example1 {
    public Example1(String arg) throws IOException {     
    public void foo(String arg) throws IOException {

We can use the following Joern script to find the path from source to sink:

@main def main(code: String) = {
    // Get constructors that accepts string as arg
    val cons = cpg.method.isConstructor.signatureExact("void(java.lang.String)").l
    // Get all calls to Runtime.exec
    val name = "java.lang.Runtime.exec:java.lang.Process(java.lang.String)"
    val calls = cpg.method.fullNameExact(name).callIn.l

    // Source is the string passed to constructor
    val source = cons.parameter.order(1).l
    // Sink is the argument passed to Runtime.exec
    val sink = calls.argument(1).l
    // Print the path from source to sink    

When running the script, we should obtain a result similar to the table below:

joern --script --params

 nodeType          | tracked                        | lineNumber| method | file    
 MethodParameterIn | <init>(this, String arg)       | 4         | <init> | <unknown> 
 Identifier        |                  | 5         | <init> | <unknown> 
 MethodParameterIn | foo(this, String arg)          | 9         | foo    | <unknown> 
 Identifier        | Runtime.getRuntime().exec(arg) | 10        | foo    | <unknown> 

This example illustrates the type of analysis we will be conducting, with the distinction that instead of running it against the source code, we will execute it against the compiled code. It is worth mentioning that during our tests, we encountered an issue with Joern where it failed to capture paths when the source data was assigned to a class’s field member in compiled code. We have reported this issue [5] [6].


To validate the process of identifying suitable classes, we conducted experiments on several well-known Java libraries. To accomplish this, we used the following methodology:

  1. Enumerate interesting sinks
  2. Download the libraries
  3. Static analysis approach
  4. Dynamic analysis approach

Enumerate interesting sinks

To choose the sinks to be used in the dataflow analysis, we enumerated some of the most common types of vulnerabilities and attacks in Java applications with direct server-side impact. The list can be seen below:

  1. Command Injection
  2. Expresion Language Injection (EL, OGNL, MVEL, SpEL, JEXL)
  3. Deserialization
  4. File read/write
  5. JDBC Driver Connect
  6. SSRF
  7. JNDI
  8. XML Beans
  9. XXE
  10. SQL Injection
  11. Code Loading (System.loadLibrary, etc)
  12. Code Eval

Then, for each one, we select a set of methods that can lead to such vulnerabilities when called with user-controlled data.

Download the libraries

We created a script ( to download the most relevant Java libraries in order to run our experiments. In short, it goes over an ordered list [8] of popular/relevant libraries and downloads each JAR file to a local directory.

Static analysis approach

After enumerating the sinks and downloading the JARs, we have developed a Joern script ( that accepts two folders as arguments. One folder represents the location of the JAR files, while the other folder is designated for storing the results.

To execute the script, use the following command:

joern --script --params inDir=jars,outDir=result 

The script will generate the results in JSON format. The output files will contain paths that link sources to sinks. To enhance readability, we have also created a separate script ( that facilitates the interpretation of the output.

Some of the problems we had when developing and running this analysis were:

  1. We encountered an issue with Joern where it failed to capture paths when the source data was assigned to a class’s field member in compiled code [5] [6];
  2. It was slow if you did not have a good amount of RAM memory available. Also, bigger files would take more processing time. We skipped some of the larger libraries we downloaded;
  3. We encountered some Java constructs that were not handled well by Joern and would make it unable to correctly track data flow, leading to miss good constructors (false negatives).

Despite these problems, the analysis was still able to find good results.

Dynamic analysis approach

One way to validate the results would be to directly access the source code (if available) or decompile the JAR file and attempt to follow the identified paths. However, this approach would only be feasible for a limited number of results or when the paths are relatively small, which is not the case in our scenario. Instead, we opted for dynamic validation. We developed a code that accepts a class and its corresponding argument, and attempts to instantiate it.

We then automated the process of retrieving the results, extracting the constructors, and instantiating them using a pre-established list of arguments. This list consisted of values carefully selected to validate various scenarios, including accessing servers, creating files, executing system commands, and more. We also logged all execution to be able to manually inspect it. The script can be seen at

In the GIF, the upper part of screen shows the script running and the lower part shows a live inspection of the generated log (tail -f /tmp/tester.dd-mm-yyyy_HHhMMmSSs.log).

This dynamic validation approach allowed us to verify the findings more efficiently and effectively.


Due to the amount of results obtained, we reviewed only a small part of them and below are just a few of the interesting constructors we found:

MySQL Client Arbitrary File Reading

Package: mysql-connector-java-8.0.11.jar

Class: com.mysql.cj.jdbc.admin.MiniAdmin

Arg: jdbc:mysql://rogue_server

XXE, SSRF and Arbitrary File Reading

Package: mybatis-3.5.13.jar

Class: org.apache.ibatis.parsing.XPathParser

Arg: XXE exfiltrate payload

Insecure Deserialization

Package: jasperreports-6.20.5.jar

Class: net.sf.jasperreports.export.SimpleExporterInput

Arg: file path to serialized exploit

Arbitrary File Content Leak Through Error

Package: dnsjava-3.5.2.jar


Arg: /etc/passwd


Package: itextpdf-


  • com.itextpdf.text.pdf.codec.GifImage
  • com.itextpdf.text.pdf.RandomAccessFileOrArray

Arg: URL


Package: itext-4.2.1.jar


  • com.itextpdf.text.ImgWMF
  • com.lowagie.text.pdf.codec.GifImage

Arg: URL

Possible Webroot Path Leak Through Error

Package: hutool-core-5.8.19.jar


Arg: some non existing file name (e.g. xxx)

Command Injection

Package: jline-2.14.6.jar


  • jline.internal.TerminalLineSettings
  • jline.UnixTerminal

Arg: $(command)


In this blog we presented a simple approach to automate the discovery of interesting classes to be used when attacking unsafe reflection in Java applications. We showed how to use Joern to execute a customized dataflow analysis suited for our needs.

An interesting research titled “A New Attack Interface In Java Applications” presented by Xu Yuanzhen and Peter Mularien at Blackhat Asia 2023 [7] shows other examples of the process of finding good classes to exploit similar vulnerabilities via JDBC URLs.

Follow-up work could be to run our analysis in the Java code itself, to discover interesting constructors that do not depend on an external library. Another one could be to take advantage of the script to find security vulnerabilities in Java applications by just redefining the source to represent user-controlled data such as HTTP request parameters, for example.

Gabriel Quadros – Security Analyst
Ricardo Silva – Security Analyst

Nova call to action


About author


A team of professionals, highly connected on news, techniques and information about application security
Related posts
Application Security

Mitigating Vulnerabilities: Elevating Security Proficiency in Software Development

In the ever-evolving digital landscape, the significance of software security cannot be overstated.
Read more
Application Security

The Importance of Supply Chain to Application Security

When we think about software development, we usually think about complex technical concepts…
Read more
Application Security

What is WAAP (Web Application and API Protection)

Welcome to the world of Web Application and API Protection (WAAP), an advanced security approach…
Read more

Deixe um comentário