【入坑JAVA安全】Java反射機制

0x01 基本概念

Java反射機制是在運行狀態時,對於任意一個類,都能夠獲取到這個類的所有屬性和方法,對於任意一個對象,都能夠調用它的任意一個方法和屬性(包括私有的方法和屬性),這種動態獲取的信息以及動態調用對象的方法的功能就稱爲java語言的反射機制。

java反射機制給漏洞利用提供了很多便利,我們可以在很多java漏洞的exp中看到它的影子,所以,學習java安全是繞不開它的。

0x02

前面我們知道了反射機制能夠做什麼,但是java具體是怎麼實現這一點的呢?這幾涉及到java中的幾個類:Class、Constructor、Method、Field,有過面向對象編程經驗的同學都知道,一個類一般是抽象出了某一類事物的特徵,例如下面這個Person類就抽象出了一個人的特徵,並實現了一些操作這些特徵的方法:

class Person{
    private String name;
    private int age;
    private  double  height;
    private double  weight;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public double getWeight() {
        return weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }

    public void show(){
        System.out.println("xxxxxx");
    }
}

那麼我們剛剛說的那幾個和反射相關的類同樣是這樣的——Class類抽象出了java中類的特徵並提供了一些方法,Constructor抽象出了java中所有的構造函數的特徵以及提供一些方法…(最開始接觸java安全的時候我就經常會被java的Class類型搞昏)

知道了這幾個類之後,我們再回到怎麼實現調用一個對象的任意方法這個問題上來,分三步走:

  1. 首先獲得這個對象對應的Class類的實例
  2. 因爲Class這個類存儲着一個類的所有信息:屬性、方法、構造函數…所以我們可以通過Class類的實例來獲取你想要調用的那個方法
  3. 拿到了對應的方法過後,我們可以給這個方法傳入對應的參數來調用它。

上面是一個大體的流程,現在我們來看一下用代碼怎麼實現這三個流程:

爲了後續更好地闡述,我們以通過反射調用下面這個User類的setName()方法爲例:

class User{
    private String name;
    private int age;

    @Override
    public String toString(){
        return "User{" + "name=" +name + ", age="+age+"}";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

1.獲得User對象的Class類實例

有三種方式獲得Class類實例:

1.調用Class類的靜態方法forName獲取某個類的Class類實例:
Class clz = Class.forName("com.axin.User");

2.訪問某個類的class屬性,這個屬性就存儲着這個類對應的Class類的實例:
Class clz = com.axin.User.class;

3.調用某個對象的getClass()方法:
Class clz = (new User()).getClass();

2.獲取setName方法

我們之前已經提到了Method這個類,java中所有的方法都是Method類型,所以我們通過反射機制獲取到某個對象的方法也是Method類型的。通過Class對象獲取某個方法:

clz.getMethod(方法名,這個方法的參數類型)

例:
Method method = clz.getMethod("setName", String.class);

3.調用setName方法

Method類中有一個invoke方法,就是用來調用特定方法的,用法如下:

在這裏插入圖片描述

第一個參數是調用該方法的對象,第二個參數是一個可變長參數,是這個方法的需要傳入的參數,描述的不夠直觀,直接看代碼:

接着上文代碼:
method.invoke((new User()), "axin");

或者

User user = new User();
method.invoke(user, "axin");

流程走完了,讓我們來看看整體程序:

在這裏插入圖片描述

可以看到我們成功調用setName方法,並設置name爲“axin”。

0x03

除了調用一個對象的任意方法,我們還可以獲得某個對象對應的類名、所有的屬性以及所有的方法名,由於這些內容在編寫exp中使用較少,就不寫在這裏了。

歡迎關注我的微信公衆號,一個安全研究員:

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章