loading...
JAVA反序列化利用
Published in:2023-01-01 | category: Java 反序列化

0x00前言

提起反序列化不是什么新鲜的名词了,无论是php还是java,最终的目的都是执行恶意代码达到RCE或权限控制的目的,总结下JAVA的反序列化的一些知识点,巩固一下。

0X01序列化与反序列化

序列化:将对象转换为字节流并存储到指定文件

反序列化:读取文件并将字节流还原为对象

ObjectOutputStream类 —-> writeObject() 序列化(OOS)

ObjectInputStream类 —-> readObject() 反序列化(OIS)

序列化实现:

反序列化实现:

0x02序列化实现

java类需要实现serialize接口或者实现Externalizable,否则执行的时候会抛出异常

1
2
public interface Serializable {
}

子类继承父类时父类需要实现上述接口,若无实现则需要子类提供一个无参的构造函数并创建对象

记住:序列化是序列化对象而不是序列化类

并且静态变量不能被序列化,因为静态变量优先于对象存在,随着类的加载而加载,所以不会被序列化

条件

共同条件 继承Serializable

入口类 source(重写readObject 参数类型宽泛 最好jdk自带)

调用链gadget chain

执行类sink (rce ssrf写文件等等)

0x03反序列化的利用

在java反序列化中,会调用执行readObject()方法中的代码,攻击者可以构造恶意代码序列化后发送给服务端,服务端进行反序列化并执行readlObject()方法

利用点

1、入口类的readObject直接调用危险方法

2、入口类参数中包含可控类,该类有危险方法readObject时调用

3、入口类参数中包含可控类,该类有调用其他有危险方法的类readObject时调用

4、构造函数/静态代码块等类加载时隐式执行

验证是否存在反序列化可以使用常见的反序列化链

URLDNS链:HashMap.readObject() -> HashMap.putVal()->HashMap.hash()->URL.hashcode()->URLStreamHandler().hashCode().getHostAddress->URLStreamHandler().hashCode().getHostAddress.getByName()

0x04序列化数据的特征

一段数据以rO0AB开头,基本可以确定这串就是JAVA序列化base64加密的数据

如果以ac ed开头,那么它就是这一段JAVA序列化的16进制

0x05JAVA反射

实现JAVA反序列化时不能忽略的一个点就是JAVA内置的的反射机制,它的作用就是让JAVA具有动态性

作用

1、修饰已有动态属性

2、动态生成对象

3、动态调用方法

4、操作内部类和私有方法

操作反射的5中类

  • java.lang.Class: 代表类
  • java.lang.reflect.Constructor: 代表类的构造方法
  • java.lang.reflect.Field: 代表类的属性
  • java.lang.reflect.Method: 代表类的方法
  • java.lang.reflect.Modifier:代表类、方法、属性的描述修饰符。

AccessObject类中有一个setAccessible()方法,作用是使得非public属性或方法可见,而Constructor、Field、Method都继承这个类

Constructor

方法 含义
getConstructors() 获得类的所有public构造方法
getDeclaredConstructors() 获得类的所有构造方法
getConstructor(Class[] parameterTypes) 获得类的特定public构造方法
getDeclaredConstructor(Class[] params) 获取类的特定构造方法

Field

方法 含义
getFields() 获得类的所有public属性
getDeclaredFields() 获得类的所有属性
getField(String name) 获得类的特定public属性
getDeclaredField(String name) 获取类的特定属性

Method

方法 含义
getMethods() 获得类的所有public成员方法
getDeclaredMethods() 获得类的所有成员方法
getMethod(String name, Class[] parameterTypes) 获得类的特定public成员方法
getDeclaredMethod(String name, Class[] parameterTypes) 获取类的特定成员方法

example

该学生类属性

获取对象的类

1
Class clazz = Class.forName("src.Student");//也可使用forName方法

获取对象构造方法

其中传入的参数是获取student类中带有int类型和String类型参数的构造方法

获取对象的属性

获取对象的方法

当在漏洞利用时通常需要修改对象属性达到攻击目的,贴一段代码

1
2
3
4
5
6
public static boolean setField(Object object, String fieldName, Object fieldValue) {
Class clazz = object.getClass();
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
return field.set(object, fieldValue);
}

0x06工具

https://github.com/frohoff/ysoserial

yeoserial库

在渗透测试或者做CTF题目的时候需要注意看源代码的依赖名称和依赖版本从而选择正确的反序列化链

0x07总结

1、实现序列化时需要实现serialize或Externalizable接口否则报错

2、子类继承父类若无实现接口则需要提供空白参数的构造方法

3、静态常量和类的属性不能被序列化,序列化的只能是对象,静态则优先于对象,随着类加载而加载

4、JAVA反序列化往往配合JAVA反射进行构造恶意代码的目的,一般不能遗漏setAccessible

5、Ysoserial工具使用的时候需根据源代码的依赖名称和版本选择正确的链子

Prev:
Clash最新漏洞复现
Next:
APPLE黑苹果教程
catalog
catalog