Java安全(一)

Java安全(一)

先学点基础知识

反射

反射(Reflection)是 Java 的重要机制之一。通过反射,我们可以在程序运行过程中,利用 Class 对象去动态的查看和操作一个类,对我们后续学习类加载机制至关重要,因此,我们选择首先学习反射。

Class对象

Java 反射是直接对 Class 对象进行操作的,Class 对象就是 JVM 在运行时用来描述一个类的信息对象,这里有四种方式获取。

  1. <类名>.class
    java
    public class Test {
        public static void main(String[] args) {
            Class<?> clazz = Test.class;
        }
    }
    
  2. Class.forName()
    这个需要我们知道一个类的完整类名。
    java
    public class Test {
        public static void main(String[] args) throws ClassNotFoundException {
            Class<?> clazz = Class.forName("com.Test");
        }
    }
    
  3. <实例>.getClass()
    通过实例后的对象获取。
    java
    public class Test {
        public static void main(String[] args) {
            Test test = new Test();
            Class<?> clazz = test.class;
        }
    }
    
  4. 类加载器
    同样需要完整的类名。
    java
    public class Test {
        public static void main(String[] args) throws ClassNotFoundException {
            Class<?> clazz = ClassLoader.getSystemClassLoader().loadClass("com.test");
        }
    }
    

这里需要注意的一点是,在对数组对象获取 Class 时,写法有所不同。

java
Class<?> clazz = double[].class;
Class<?> clazz = Class.forName("[D");
Class<?> clazz = Class.forName("[[D");

在调用内部类时,需要使用$来代替.,如com.Test类有一个叫做Hello的内部类,那么调用时类名就为:com.Test$Hello。

API

对于一个类,我们获得到 Class 对象后,就可以通过反射 API 获得一切信息。

  1. 获取父类
    clazz.getSuperclass();
  2. 获取字段
    java
    Field[] field1 = clazz.getDeclaredFields();
    // 当前类:所有字段,不包括父类
    
    Field[] field2 = clazz.getFields();
    // 当前类 + 父类:所有 public 字段
    
    Field field4 = clazz.getDeclaredField("name");
    // 当前类:找名字叫 name 的字段,不管 public/private/protected
    
    Field field3 = clazz.getField("name");
    // 当前类 + 父类:找名字叫 name 的 public 字段
    
  3. 获取方法
    java
    Method[] method1 = clazz.getDeclaredMethods();
    // 当前类:所有方法,不包括父类
    
    Method[] method2 = clazz.getMethods();
    // 当前类 + 父类:所有 public 方法
    
    Method method4 = clazz.getDeclaredMethod("hello");
    // 当前类:找名字为 hello 的方法,不管 public/private/protected
    
    Method method3 = clazz.getMethod("hello");
    // 当前类 + 父类:找名字为 hello 的 public 方法
    
  4. 获取构造方法
    java
    Constructor<?>[] constructor1 = clazz.getDeclaredConstructors();
    // 当前类:所有构造方法,不包括父类
    
    Constructor<?>[] constructor2 = clazz.getConstructors();
    // 当前类:所有 public 构造方法,不包括父类
    
    Constructor<?> constructor4 = clazz.getDeclaredConstructor(String.class);
    // 当前类:找参数类型为 String 的构造方法,不管 public/private/protected
    
    Constructor<?> constructor3 = clazz.getConstructor(String.class);
    // 当前类:找参数类型为 String 的 public 构造方法
    

下面通过 java.lang.Runtime 类进行演示,该类有个 exec 方法可以执行命令,因此许多 payload 都有这个。

类加载机制

Classloder

双亲委派机制

序列化与反序列化

新故事即将发生
Linux 提权

评论区

评论加载中...