Java安全之原生readObject方法解读

0x00 前言

在上篇文章分析shiro中,遇到了Shiro重写了ObjectInputStreamresolveClass导致的一些基于InvokerTransformer去实现的利用链没法使用,因为这需要去定义一个InvokerTrans数组,而该数组传入到Shiro重写后的resolveClass方法中会报错。但是在此之前,并没有去对readObject方法去做一个解读和分析。所以也不知道他具体的实现。包括在分析利用链的时候,只知道到调用了ObjectInputStream.readObject方法后,如果readObject被重写的话,就会调用重写后的readObject方法,但是我们也并不知道在内部是怎么样去做一个实现的。那么下面来分析一下readObject的功能实现。

0x01 readObject方法分析

在前面先贴一张readObject的执行流程图,这是一张weblogic的反序列化执行流程图。第一个readObject直接忽略,到下篇文weblogic再做讲解。

这里写一段测试代码去进行反序列化操作,然后进行动态跟踪。

User实体类:

package com.nice0e3;

import java.io.Serializable;

public class User implements Serializable {
private String name;
private int age; @Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", 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;
} public User() {
} public User(String name, int age) {
this.name = name;
this.age = age;
}
}

ReadTest类:

package com.nice0e3;

import java.io.*;

public class ReadTest {
public static void main(String[] args) throws IOException, ClassNotFoundException {
User user = new User();
user.setName("nice0e3");
user.setAge(20);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("1.txt"));
oos.writeObject(user);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("1.txt"));
Object o = ois.readObject();
}
}

然后将断点落在ObjectInputStream.readObject方法中,进行执行测试类代码动态跟踪。

这里对enableOverride进行了一个判断,不为flase的话就会去返回readObjectOverride方法,而在构造方法中就定义该值为flase。

下面就直接执行到了这步

调用了readObject0方法,选择跟进查看一下内部的实现。

在这里会去获取序列化信息第一个字节,如果为TC_RESET就会调用bin.readByte()handleReset();方法。

查看TC_RESET内容。

而该值转换Byte后,为121,我们序列化数据的第一个字节为151,这里就跳过不执行了。

接下来代码中定义了一个switch去做一个判断,TC_OBJECT的值转换后刚刚好为115。那么就会执行到这一步。

在这里面会调用readOrdinaryObject方法,进行跟进。

在该方法中还会去调用readClassDesc方法,继续跟进。

看到这里发现就很有意思了,获取我们序列化数据的第二个字节,然后又进行一次switch,这次走到了readNonProxyDesc方法中,跟进!

在这又调用了resolveClass方法然后传入readDesc参数。还是跟进方法。

这里返回了

Class.forName(name, false, latestUserDefinedLoader());

latestUserDefinedLoader()方法返回的是sun.misc.VM.latestUserDefinedLoader()说明指定了该加载器。

返回到readOrdinaryObject方法中继续做分析。

直接定位到这一步,该方法对反序列化的操作进行实现。

这里的slotDesc.hasReadObjectMethod()获取的是readObjectMethod这个属性,如果反序列化的类没有重写readobject(),那么readObjectMethod这个属性就是空,如果这个类重写了readobject(),那么就会进入到if之中的

slotDesc.invokeReadObject(obj, this);

如果readobject()方法被重写则是走到这一步

0x02 Shiro resolveClass方法分析

在shiro里面resolveClass方法被进行了重写,导致大部分利用链都使用不了,查看一下该方法实现。

这里去调用了ClassUtils.forName方法进行跟踪。

这里是调用了THREAD_CL_ACCESSOR.loadClass,查看一下THREAD_CL_ACCESSOR是什么。

跟进查看一下该类。

这里调用getClassLoader方法获取类加载器,而在这里获取到的是ParallelWebappClassLoader,那么下面调用的肯定也就是ParallelWebappClassLoader.loadClass

参考文章

https://blog.csdn.net/niexinming/article/details/106665753

https://www.anquanke.com/post/id/192619#h2-2

0x03 结尾

其实在前面的一些cc链的调试铺垫下,再去调试其他的一些漏洞,都会比较熟练。本文也是为了下文去做了一个较好的铺垫。

Java安全之原生readObject方法解读的更多相关文章

  1. JAVA反序列化漏洞修复解决方法

    MyObject类建立了Serializable模块,而且重新写过了readObject()变量,仅有建立了Serializable模块的类的目标才能够被实例化,沒有建立此模块的类将无法使他们的任意状 ...

  2. Effective Java 第三版——88. 防御性地编写READOBJECT方法

    Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...

  3. 编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则)

    编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则) 目录 建议1: 不要在常量和变量中出现易混淆的字母 建议2: 莫让常量蜕变成变量 建议3: 三元操作符的类型务 ...

  4. java四种创建对象的方法

    1.用new语句创建对象,这是最常见的创建对象的方法.   2.运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance ...

  5. 使用ObjectInputStream的readObject()方法如何判断读取到多个对象的结尾

    摘自http://blog.csdn.net/fjdingsd/article/details/46765803 使用ObjectInputStream的readObject()方法如何判断读取到多个 ...

  6. Java常见序列化与反序列方法总结

    很多商业项目用到数据库.内存映射文件和普通文件来完成项目中的序列化处理的需求,但是这些方法很少会依靠于Java序列化.本文也不是用来解释序列化的,而是一起来看看面试中有关序列化的问题,这些问题你很有可 ...

  7. Java实现mongodb原生增删改查语句

    Java实现mongodb原生增删改查语句 2018-03-16 自动化测试时,需校验数据库数据,为了快速自动化,在代码中用原生增删改查语句操作mongodb 结构 代码 0 pom.xml < ...

  8. java.lang.system 类源码解读

    通过每块代码进行源码解读,并发现源码使用的技术栈,扩展视野. registerNatives 方法解读 /* register the natives via the static initializ ...

  9. Java使用序列化的私有方法巧妙解决部分属性持久化问题

    部分属性持久化问题看似很简单,只要把不需要的持久化的属性加上瞬态关键字(transient关键字)即可,没错,这也是一种解决方案,但在有的时候行不通,例如在一个计税系统和人力系统对接的时候,计税系统需 ...

随机推荐

  1. windows下命令行设置静态IP

    windows 10 预览版出现无法设置静态IP的bug,只能通过命令行进行设置,开启powershell,然后执行下列的命令即可 下面的"以太网 3" 为你设置的网卡的网卡名称, ...

  2. LeetCode283移动零问题java高效解法

    一.题目: 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序. 示例: 输入: [0,1,0,3,12] 输出: [1,3,12,0,0] 说明: 1.必须 ...

  3. linux系统中 SElinux安全子系统

    1.SElinux 是什么? SElinux(Security-Enhanced Linux)是美国国家安全局在linux开源社区的帮助下开发的一个强制访问控制(Mandatory Access Co ...

  4. 利用代理IP池(proxy pool)搭建免费ip代理和api

    先看这里!!!---->转载:Python爬虫代理IP池(proxy pool) WIIN10安装中遇到的问题: 一.先安装Microsoft Visual C++ Compiler for P ...

  5. invalid PID number "" in "/usr/local/nginx/logs/nginx.pid"

    解决办法: $ sudo nginx -c /usr/local/etc/nginx/nginx.conf $ sudo nginx -s reload

  6. 面试BAT问的最多的27道MyBatis 面试题(含答案和思维导图总结)

    前言 关于MyBatis总结了一个思维导图希望对大家有帮助 什么是 Mybatis? Mybatis 是一个半 ORM(对象关系映射)框架,它内部封装了 JDBC,开发时只需要关注 SQL 语句本身, ...

  7. 关于Boom 3D“夜间模式”的妙用

    Boom 3D的"夜间模式"不仅能够优化音效,减小高分贝声音的突然刺激,让你夜晚的聆听效果更加舒适,还能将音效运用到各种环境中. 下面小编就给大家讲一讲如何更好的利用Boom 3D ...

  8. 鸿蒙OS的系统调用是如何实现的? | 解读鸿蒙源码

    本文将首先带您回顾"系统调用"的概念以及它的作用,然后从经典的Hello World开始,逐行代码层层分析--鸿蒙OS的系统调用是如何实现的. 写在前面 9月10号 华为开发者大会 ...

  9. OpenCV计算机视觉学习(12)——图像量化处理&图像采样处理(K-Means聚类量化,局部马赛克处理)

    如果需要处理的原图及代码,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice 准备 ...

  10. P1163 银行贷款

    考虑从一个月转移到下一个月.假设前一个月的欠款是 \(s\),月利息为 \(d\),月末还款为 \(b\),那么下一个月的欠款就是 \(s\left(1+d\right)-b\). 很容易看出月利息越 ...