验证漏洞
pom.xml添加cc1
1 | <dependency> |
CC1分析
我将整个分析过程分成两部分,一部分是构造命令执行,另一部分是触发链。
命令执行
Transformer接口类,供后续其他类重写利用
ConstantTransformer
直接返回构造函数传进来的Object
InvokerTransformer
可以看到这里 用getClass()获取了类,getMethod() 获取了方法, invoke反射执行。所以这里可以通过反射执行任意类的任意方法。
Demo1:
成功利用InvokerTransformer.transform
执行命令,但是这里是手动传入Runtime.getRuntime()
来执行命令的,为了在反序列化时能被触发,我们还需找另一种自动构造的方法。
ChainedTransformer
可以看到在这里的chainedTransformer.transform
里是可以循环触发transform
,参数可控,并且第一次的值再传递给第二次调用
因此可通过其来构造一条InvokerTransformer链子。
(new class[0] 用来告诉反射getMethod找到一个无参函数, new Object[0] 是为了根据传入参数自动获取类型,这里代替Null。这里之所以放这两个东西,主要就是类似占位符,因为反射去调用getMethod()时 ,它的构造函数要求传入两个参数。)
第一行通过ConstantTransformer.transform
返回java.lang.Runtime
第二行通过InvokerTransformer.transform
反射取得getRuntime()
第三行通过invoke
反射取得java.lang.Runtime.getRuntime()
最后一行直接反射调用exec()
,并传入命令参数
触发命令链
找在什么地方能调用到ChainedTransformer
的transform
TransformerMap
在decorate()
中实例化了TransformedMap
在transformValue()和checkSetValue(),transformKey()有调用 transform
valueTransformer
参数可控,因此可以通过TransformedMap.transformValue()
来触发ChainedTransformer.transform()
再找找看什么地方有这个transformValue()的调用
在put方法中直接粗暴的就调用了
所以构造如下payload,直接Put时就执行命令
但是在反序列化漏洞环境中是从readObject()入手,所以需要另一种可以序列化构造的,在readObject()
进入的payload
完整payload
接下来是通过构造红框链来触发chainedTransformer.transform()
LazyMap
LazyMap
和 TransformMap
类似
只不过 TransformMap 是put
方法触发,而LazyMap是get
方法
看到当key不存在为空时,则会调用transform(key)方法。
将上一个payload的put改成LazyMap::get
,同样可以触发漏洞
AnnotationInvocationHandler
在D:\Java\Java1.7\JDK\jre\lib\rt.jar!\sun\reflect\annotation\AnnotationInvocationHandler.class
中 利用 AnnotationInvocationHandler
组件,它是用来处理注解的其构造函数有两个参数,一个是Annotation
(Target.class == 元注解类) 另一个为Map
(TransformedMap)。
(JDK中,所以的注解类型都继承自这个Annotation)
重点看起readObject()
var1为传入的反序列化流,var2为该类构造函数传入的第一个Annotation值,var4为我们封装的Map链.enrtySet().iterator()
所以 最后Map链.enrtySet().iterator()
会返回AbstractInputCheckedMapDecorator.java
对象给var4,并将 Map链对象放进 parent
.
要注意 如何才能保证var7不为空,从而进入if分支
已知var2为传入的注解类,var7为Map链。
从 var5 var6 var7 var4 可知 要满足var7非空得满足以下2个条件:
1.传入的var2 也就是注解类得有 member Type元素(也就是为什么传入Target.class的原因)
2.put 进map的 key值 要与 memberTypes中的Key值相同
var5是AbstractInputCheckedMapDecorator中MapEntry
类,所以最后 var5.setValue
相当于调用了 AbstractInputCheckedMapDecorator.MapEntry.setValue()
这里的parent
即是TransformedMap
,相当于TransformedMap->checkSetValue()
TransformedMap
中的valueTransformer
又等于chainedTrasformer
链
至此,就将readObject()和前面的链联系起来了
最后模拟服务端通过 readObject 接收反序列化数据 直接RCE
1 | package CC1; |
CC1链实际中用的不多,因为有限制。
AnnotationInvocationHandler
的readObject()
复写这个地方在高版本是进行了改动。