眾所周知,Java目前影響最大的是反序列化漏洞,,換一句話說(shuō)Java安全是從反序列化漏洞開(kāi)始,但反序列化漏洞又可以基于反射,,這次筆者帶你走進(jìn)Java安全的大門,。Java反序列化的payload大多與反射機(jī)制密切相關(guān),但僅僅是因?yàn)檫@個(gè)嗎,?答案肯定是片面的,。反射作為大多數(shù)編程語(yǔ)言里必不可缺的組成部分,對(duì)象可以通過(guò)反射獲取其他的類,,類可以通過(guò)反射拿到所有的方法(包括私有方法),,獲取到方法可以調(diào)用。一句話,,反射給Java等類似的靜態(tài)語(yǔ)言賦予了“靈魂”,。ps:本文實(shí)驗(yàn)代碼都上傳JavaLearnVulnerability項(xiàng)目,為了讓更多人知道,,麻煩動(dòng)動(dòng)小手star一下,。Java反射操作的對(duì)象是java.lang.Class對(duì)象,,如果想要使用Java反射,首先得獲取Class對(duì)象,。下面我們看一段代碼,。 public static void main(String[] args) throws Exception { Class cls = Class.forName(className); cls.getMethod(methodName).invoke(cls.newInstance()); } ps:當(dāng)然反射不可能僅僅只是這些方法,,下面中筆者有提及其他的方法,,當(dāng)然不可能是全部都一一道來(lái),正所謂授之與魚,,不如授之于漁,。更多方法建議大家去看JDK文檔,在線的文檔百度一搜就有,。首先筆者構(gòu)造了兩個(gè)類students和classdemo1,。實(shí)體類students源碼:public class Students { private Integer age = 18; private String name = 'samny'; private Integer CardId = 332323223; private Integer id = 10012; private String hello = 'hello world';
public Students(Integer age, String name, Integer cardId, Integer id, String hello) { this.age = age; this.name = name; this.CardId = cardId; this.id = id; this.hello = hello;
}
@Override public String toString() { return 'Students{' + 'age=' + age + ', name='' + name + '\'' + ', CardId=' + CardId + ', id=' + id + ', ags='' + hello + '\'' + '}'; }
public Students() {
}
public Integer getAge() { return age; } // 以下省略set,get以及toString方法,。
}
實(shí)體類classdemo1的源碼:public class classdemo1 { private String name; public void print(){ System.out.println('parameterlessMethod:hello');
} public void print2(String name){ System.out.println( 'parameterMethod: hello' + name); } }
反射方法獲取Students類。實(shí)例化所需要的類集合Class[]classes = newClass[]{Integer.class,String.class,Integer.class,Integer.class,String.class}; 通過(guò)構(gòu)造器構(gòu)造類Constructorconstructor =cls.getDeclaredConstructor(classes); 通過(guò)調(diào)用有參構(gòu)造器實(shí)例化類Objectstr = constructor.newInstance(18, “samny”, 32326663, 10021,“hello!!”);
public static void reflectmethod1(){ try {
// 獲取對(duì)象
Class cls = Class.forName('samny.reflection.Students');
// // 獲取構(gòu)造器方法 Class[] classes = new Class[]{Integer.class,String.class, Integer.class,Integer.class,String.class}; Constructor constructor = cls.getDeclaredConstructor(classes);
Object str = constructor.newInstance(18, 'samny', 32326663, 10021, 'hello!!'); System.out.println(str); // 或者下面這樣子輸出 // System.out.println(constructor.newInstance(18, 'samny', 32326663, 10021, 'hello!!'));
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) { e.printStackTrace(); } }
常規(guī)開(kāi)發(fā)人員實(shí)例化類構(gòu)造類demopublic static void Sts(){ Students students = new Students(); students.setAge(18); students.setName('samny'); students.setCardId(32336666); students.setId(1001); students.setAgs('helloooo!!'); System.out.println(students.toString()); }
對(duì)比一下效果是沒(méi)有任何的區(qū)別,,但反射操作只需要知道類名就可以完全操作類甚至是類中的私有方法之后文章會(huì)詳細(xì)說(shuō)明,,本文不做說(shuō)明。 反射調(diào)用類中的無(wú)參和有參方法,。之前說(shuō)過(guò)的知識(shí)就不在說(shuō)明 開(kāi)頭就說(shuō)了,,invoke是執(zhí)行獲取類得到方法的方法 但調(diào)用有參方法和無(wú)參方法有點(diǎn)細(xì)微的差別 getMethod方法的第一個(gè)參數(shù)是類方法名稱,第二個(gè)是類對(duì)象,。這里先留個(gè)疑問(wèn),,如果是多個(gè)類對(duì)象呢? invoke函數(shù)的第一個(gè)參數(shù)是實(shí)例化的類對(duì)象,,第二個(gè)是參數(shù)值 常規(guī)方法的調(diào)用,,直接Class.method()即可 public static void reflectmethod2(){ try { Class cls = Class.forName('samny.reflection.classdemo1'); // 無(wú)參方法調(diào)用 Object ob = cls.newInstance(); // Method mt = cls.getMethod('print'); 有沒(méi)有null均可 Method mt = cls.getMethod('print',null); mt.invoke(ob,null); // 有參方法調(diào)用 Method mt2 = cls.getMethod('print2', String.class); mt2.invoke(ob,'world');
} catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } }
P神-Java安全漫談-反射篇 www.sec-in.com 在這里,探索技術(shù)與熱愛(ài)
|