java反序列化基础知识

java反序列化:

基础知识:

序列化,反系列化方法:

ObjectOutputStream类的 writeObject() 方法可以实现序列化。

ObjectInputStream 类的 readObject() 方法用于反序列化。

序列化过程就是: 对象 -> ObjectOutputStream (将对象转为字节) -> FileOutputStream (将字节写入磁盘)这里 ObjectOutputStream 装饰了 FileOutputStream,赋予了它“写入对象”的能力。

反序列化过程就是: FileInputStream (从磁盘读字节) -> ObjectInputStream (将字节还原为对象) -> 对象 这里 ObjectInputStream 装饰了 FileInputStream,赋予了它“读取并还原对象”的能力。

装饰:在不修改原有类代码的情况下,动态地给对象添加新的功能

基本序列化,反序列化流程:

假设我们有个people类而且有tostring方法:
class SerializeDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {

        //序列化操作
        System.out.println("----------序列化开始----------");
        People p = new People("John", "Male", 30);
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("People.txt"));
        oos.writeObject(p);
        oos.flush();
        oos.close();

        //反序列化操作
        System.out.println("----------反序列化开始----------");
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("People.txt"));
        People p1 = (People) ois.readObject();
        ois.close();
        System.out.println(p1);
    }
}

漏洞原理:

一些自动执行的方法可以自定义,导致意外代码执行

触发点:

  • readObject():反序列化的起点,反序列化自动调用
  • readResolve():是 Java 序列化机制中的一个钩子方法,在整个对象构造完成后,JVM 会调用 readResolve(),并用它的返回值替代原来的反序列化结果。
  • InvocationHandler.invoke():动态代理类的方法,在调用代理类任意函数时自动调用invoke方法

Gadget链:

定义:可以被链接起来造成反序列化漏洞执行特定功能的类或方法,他们并非恶意代码,但是在链接起来后可以产生危险的行为

构成:

  • 入口点(Entry Point):反序列化的入口例如readObject()方法
  • 触发类(Trigger Class):包含可直接被反序列化调用方法的类
  • 连接类(Chain Class):将触发功能转化成目标功能的中间类
  • 执行类(sink Class):最终造成恶意操作的类(例如Runtime)

Serializable 接口:

Serializable 是java提供的标记接口,位于java.io包中,但是这个接口并没有任何内容(没有定义任何方法),它只是作为一个序列化能力的标识,意味着任何

实现该接口的对象都可以实现序列化和反序列化的操作。

只有实现了Serializable或者Externalizable接口的类的对象才能被序列化为字节序列。(不是则会抛出异常)

动态代理相关类

关键类:

  • java.lang.reflect.Proxy:这是 JDK 动态代理的核心类。通过生成一个代理对象,代理对象会将方法调用转发给指定的InvocationHandler
  • java.lang.reflect.InvocationHandler:这是一个 接口,代理对象的每个方法调用,都会被转发到 InvocationHandler.invoke()

例:

package TestCode;

import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//重写恶意的invoke方法
class ProxyHandler implements Serializable, InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Runtime.getRuntime().exec("calc");  // 会执行 calc
        return null;
    }
}

// 随便写一个接口
interface TestInterface {
    void hello();
}

// 实现类
class Test implements TestInterface {
    public void hello() {
        System.out.println("Test");
    }
}

// 创建动态代理
public class ProxyTest {
    public static void main(String[] args) {
        Test test = new Test();

        TestInterface proxy = (TestInterface) Proxy.newProxyInstance(
                test.getClass().getClassLoader(),
                new Class[]{TestInterface.class},
                new ProxyHandler()
        );

        proxy.hello();
    }
}

命令实现类:

关键类:

  • java.lang.Runtime
  • java.lang.ProcessBuilder
  • javax.script.ScriptEngine

例:


//方法1:Runtime.exec
Runtime.getRuntime().exec("calc.exe");

//方法2:ProcessBuilder
new ProcessBuilder("calc.exe").start();

//方法3:ScriptEngine
ScriptEngineManager manager=new ScriptEngineManager();
ScriptEngine engine =manager.getEngineByName("js");
engine.eval("java.lang.Runtime.getRuntime().exec('calc.exe')");

 //需要注意的是,exec方法返回的是一个ProcessBuilder对象,并不会返回命令执行结果,所以我们还需要用BufferedReader额外获取命令执行结果并渲染返回到页面上

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇