安全矩阵

 找回密码
 立即注册
搜索
查看: 3938|回复: 0

入门JAVA反序列化

[复制链接]

855

主题

862

帖子

2940

积分

金牌会员

Rank: 6Rank: 6

积分
2940
发表于 2022-2-27 17:21:46 | 显示全部楼层 |阅读模式
原文链接:入门JAVA反序列化

简单举个例子:比如上司让你用java设计一个登录页面,且登录账号密码要保存在本地,但是又不能让用户直接看见明文信息。
在这里,我们就会用到java的序列化。
操作流程:我们可以先将用户的账号信息做序列化操作,这样就算用户打开看到的只会是一片乱码,而登录账号再次调用的话只需要对保存信息做反序列化操作即可。
用比较官方语言总结一下就是:序列化将对象的状态信息转换为可以存储或传输的形式的过程,在序列化期间,对象将其当前状态写入到临时或持久性存储区,而反序列化就是从存储区中读取该数据,并将其还原为对象的过程,称为反序列化。(下面会有代码演示)
Java中的序列化和反序列化API实现序列化:ObjectputStream类 --> WriteObject()
注意:该方法对参数指定的obj对象进行序列化,把字节序列写到一个目标输出流中,按java的标准约定是给我就一个.ser扩展名。
反序列化:ObjectInputStream类 -->readObject()
注:该方法从源输入流中读取字节序列,再把题目反序列化为一个对象,再将其返回。
这里我们使用代码来进行进行简单演示:
  1. public class SerializeDemo {
  2.     public static void main(String[] args) throws IOException {
  3.         Employee e = new Employee();
  4.         e.name = "zhangsan";
  5.         e.age = 20;
  6.         e.address = "shenzhen";
  7.             // 1.创建序列化流
  8.             ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("employee.txt"));
  9.             // 2.写出对象
  10.             outputStream.writeObject(e);
  11.             // 3.释放资源
  12.             outputStream.close();

  13.     }
  14. }
复制代码


这里将将Employee对象写入到了employee.txt文件中。

这个就是一个序列化操作。
而反序列化操作呢,我们用以下代码实现:
  1. //如果能找到一个对象的class文件,我们可以进行反序列化操作,调用 ObjectInputStream 读取对象的方法:
  2. public class DeserializeDemo {
  3.     public static void main(String[] args) throws IOException, ClassNotFoundException {
  4.         // 1.创建反序列化流
  5.         FileInputStream fileInputStream = new FileInputStream("employee.txt");
  6.         ObjectInputStream inputStream = new ObjectInputStream(fileInputStream);
  7.         // 2.使用ObjectInputStream中的readObject读取一个对象
  8.         Object o = inputStream.readObject();
  9.         // 3.释放资源
  10.         inputStream.close();
  11.         System.out.println(o);
  12.     }
  13. }
复制代码

运行后打印出的结果就是我们之前序列化前的数据,反序列化操作就是从二进制文件中提取对象。


参考文章:https://www.cnblogs.com/yyhuni/p/14755940.html
看了半天源码是不是还是有点懵,不慌,我们来研究一下下面这个靶场,就懂了。
靶场详解反序列化如何ide如何查看jar文件源码:(后面有用)https://blog.csdn.net/yang123456 ... ls/122290512webgoat靶场下载(推荐还是用8.1.0版本,因为高版本对jar版本也高)https://github.com/WebGoat/WebGoat/releases/tag/v8.2.2

第一步:使用ide打开webgoat.jar,查看这一关的关键代码(如何打开,方法如上):

读取对象和写入对象操作。

命令执行函数操作。
简单来看关键代码,总结流程就是对你输入的数据进行一个接收,然后对数据进行对象还原,再进行命令执行。
如何判断数据是否为序列化?
一般以rO0AB开头,基本可以认定这串数据就是JAVA序列化base64加密的数据;或者如果以aced开头,那么他就是这一段java序列化的16进制。

现在我们想一想:现在如果我要攻击他,我应该如何构造payload呢?
解:因为这个数据是序列化后再bs64编码的,所以如果我们要重构这串数据的话,我们就直接构造恶意语句,先将语句进行反序列化,再进行bs64加密,即可。
这里如果手工生成的话十分麻烦,不方便,这里我们就使用一个工具来帮助我们,这个也是在java反序列化中常用的。

项目地址:https://github.com/frohoff/ysoserial
[官网貌似没有编译好的,需要自己编译,不过公众号可以回复java反序列化,有成品]
按照ysoserial支持的插件,查找webgoat是否安装了对应的jar包,这里只有两个:
Hibernate和spring-core 但是spring-core的版本不一致,所以就选择Hibernate


【复制出来很简单,直接选中复制,粘贴到其他文件夹中就ok。】
将Hibernate的jar包复制到ysoserial工具的目录下,jar包名字中必须是有core的,是插件的核心


命令(弹一个计算器): java -Dhibernate5 -cp hibernate-core-5.4.6.Final.jar;ysoserial.jar ysoserial.GeneratePayload Hibernate1 calc.exe > payload.bin

这里保存成bin文件是因为我们还需要进行一次bs64编码。
  1. 命令执行简单翻译一下就是这样的:
  2. java -Dhibernate5 -cp hibernate-core-5.4.6.Final.jar;  
  3. //表示hibernate5的插件
  4. ysoserial.jar ysoserial.GeneratePayload Hibernate1 calc.exe > token.bin  
  5. //生成Hibernate1插件反序列化漏洞的payload,执行calc.exe命令,将payload保存在payload.bin文件中。
复制代码

生成的payload


这个就是序列化后的一个结果,此外我们还需要进行一个bs64的编码,这里用脚本或者直接工具进行bs64编码都可以。
编码后的结果就是这样:

然后我们将这串字符填入其中,就会直接弹出计算器。

命令是可以自己随意修改的,一般是反弹shell。现在应该java反序列化有所了解吧。
原理、修复方法简单小结(面试常问)在我们面试中,总有面试官问到Java反序列化,但作为菜鸡的我不知道咋回答,下面我就简单总结一下下。(大家可以按自己的来,我只是简单写一下)。
1.漏洞原理:Java序列化指Java对象转换为字节序列的过程,反序列化指字节序列恢复为Java对象的过程,如果Java应用对用户输入,即不可信数据做了反序列化处理,那么攻击者可以通过构造恶意输入,让反序列化产生非预期的对象,非预期的对象在产生过程中就有可能带来任意代码执行。
2.漏洞举例说明:例如说明shiro的反序列化导致的命令执行,Apache Shiro框架提供了RememberMe的功能,关闭浏览器再次访问时无需再登录即可访问。由于默认使用了cookieremembermanager,服务器处理cookie的流程是,得到rememberMe的cookie值 --> Base64解码 --> AES解密 --> 反序列化,而问题就出在这里,然而AES的密钥是硬编码的,如果没有修改默认的密钥,就导致了攻击者可以构造恶意数据造成反序列化的RCE漏洞,所以我们的攻击流程就是构造恶意命令-->序列化-->AES加密-->base64编码-->发送cookie。(是不是和我们刚刚做的靶场案例流程十分相似)。
3.漏洞修复说明:(1)类的白名单校验机制:对所有传入的反序列化对象,在反序列化过程开始前,对类型名称做一个检查,不符合白名单的类不进行反序列化操作。(2)禁止JVM执行外部命令Runtime.exec,可以通过扩展 SecurityManager 可以实现。


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2025-4-24 04:33 , Processed in 0.016118 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表