如何通过编程方式检测RMI类加载器是否已启用
Great question—this is a common pain point when auditing RMI endpoints without triggering unnecessary payloads or alerting defenses. Let’s break this down clearly, step by step:
1. Detecting if Remote Class Loading is Enabled
You don’t have to jump straight to sending serialized objects. Try these low-impact, targeted methods first:
Inspect RMI Registry Metadata: Start by enumerating the registry (a totally harmless operation) to get a list of exposed objects, then look up one of them to retrieve its stub. The stub may include codebase information if the server was configured with
java.rmi.server.codebase. You can extract this with a simple code snippet:// Connect to the target RMI registry Registry registry = LocateRegistry.getRegistry("target-host", 1099); // List all exposed objects first (harmless) String[] exposedObjects = registry.list(); if (exposedObjects.length > 0) { // Pick the first exposed object to inspect Remote remoteObj = registry.lookup(exposedObjects[0]); CodeSource codeSource = remoteObj.getClass().getProtectionDomain().getCodeSource(); if (codeSource != null) { System.out.println("Server-side codebase detected: " + codeSource.getLocation()); // If this exists, remote class loading is likely allowed (depending on useCodebaseOnly) } else { System.out.println("No server-configured codebase found, or stub is local to your client."); } }Test with a Benign Class: Instead of malicious payloads, create a simple, empty Java class (e.g.,
TestClass.java), compile it, and host it on a web server you control. Then run your RMI client with thejava.rmi.server.codebaseproperty set to your web server’s URL. Attempt a lookup or method call that would require the server to load this class.# Compile your test class javac TestClass.java # Host it (e.g., with Python's simple HTTP server) python3 -m http.server 8000 # Run your RMI client with the codebase flag java -Djava.rmi.server.codebase=http://your-ip:8000/ YourRMIClient- If you see incoming HTTP requests to your web server from the target, the server is accepting remote class loading.
- If you get a
ClassNotFoundExceptionbut no requests, the server’sjava.rmi.server.useCodebaseOnlyproperty is likely set totrue(blocks client-specified codebases).
Analyze RMI Protocol Handshakes: Use a tool like Wireshark to capture the initial RMI handshake between your client and the server. Look for the
java.rmi.server.useCodebaseOnlyflag in the exchanged metadata. This lets you check the server’s configuration without sending any application-level payloads.
2. Can You Retrieve the Remote Codebase?
It depends on the server’s setup:
- If the server explicitly configured
java.rmi.server.codebase, the stubs returned by the registry will include this URL (as shown in the first method above). You can extract this directly from the stub’s code source. - If the server hasn’t set a codebase, there’s no built-in way to retrieve one—you can only test whether the server will accept a client-specified codebase (using the benign class method above).
3. Is Blind Attempt + Exception Handling the Only Option?
No, but it’s a fallback for edge cases:
- The methods above let you avoid blind exploitation, but if the server restricts registry enumeration or doesn’t expose any stubs with codebase info, you may need to make a minimal test attempt. For example, try sending a remote method call with a parameter that references your benign test class. If you get a
ClassNotFoundExceptionbut see the server fetching the class, remote loading is enabled. If you get the exception without any fetch attempt, it’s disabled. - Always prioritize non-intrusive methods first before resorting to test payloads.
Quick Recap
- Start with registry enumeration and stub inspection to gather config info safely.
- Test with a benign, hosted class to check if remote loading is allowed.
- Use packet analysis to spot server flags without application-level requests.
- Only fall back to minimal test attempts if all other methods fail.
内容的提问来源于stack exchange,提问作者user2749971

