Back to Articles

Building a Lightweight RPC Shell for Apache Axis2: When Metasploit Is Too Much

[ View on GitHub ]

Building a Lightweight RPC Shell for Apache Axis2: When Metasploit Is Too Much

Hook

Sometimes the best penetration testing tools aren't the ones that exploit vulnerabilities—they're the ones that use legitimate features in unauthorized ways.

Context

Apache Axis2 has been a mainstay of enterprise SOAP web services since the mid-2000s, powering everything from financial systems to government portals. For penetration testers, compromised Axis2 servers present an interesting challenge: you've gained deployment credentials or upload access, but now what? The typical answer is reaching for Metasploit Framework with its comprehensive Axis2 modules. But Metasploit carries baggage—a large footprint, extensive dependencies, and the overhead of a full exploitation framework when you just need simple command execution.

This is where rpcshell enters the picture. Created by security researcher Bryan Alexander (hatRiot), it's a minimalist approach to post-deployment command execution on Axis2 servers. Rather than exploiting a vulnerability, rpcshell uses Axis2's legitimate web service deployment mechanism to achieve persistence and remote code execution. It's the penetration testing equivalent of walking through the front door with valid credentials instead of picking the lock. The tool consists of just two components: a malicious Axis2 service packaged as helper.jar and a client shell that communicates with it over RPC. No exploits, no payloads—just a cleverly weaponized web service that turns Axis2's own architecture against itself.

Technical Insight

Target Server

Deploy AAR/JAR

Register Endpoints

SOAP RPC Call

Command String

Execute Command

stdout/stderr

Base64 Encoded

Response

RPC Shell Client

Apache Axis2 Server

Malicious Web Service

helper.jar

Operating System

Runtime.exec

System architecture — auto-generated

The architecture of rpcshell reveals an elegant abuse of Axis2's service deployment model. At its core, Axis2 allows administrators to deploy arbitrary web services by uploading JAR or AAR (Axis Archive) files to the server. These services expose methods as SOAP endpoints that clients can invoke remotely. What rpcshell does is package a service that exposes dangerous methods—specifically, methods that execute system commands and return results.

The helper.jar component implements a simple Axis2 service with methods for command execution. When deployed, it registers RPC endpoints that accept command strings, execute them using Java's Runtime.exec(), and return base64-encoded output. The client component (rpcshell.java) acts as an interactive shell, sending commands to these endpoints and decoding responses. Here's the conceptual flow of a command execution:

// Simplified representation of the server-side service
public class RPCHelper {
    public String executeCommand(String cmd) throws Exception {
        Process proc = Runtime.getRuntime().exec(cmd);
        BufferedReader reader = new BufferedReader(
            new InputStreamReader(proc.getInputStream()));
        
        StringBuilder output = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            output.append(line).append("\n");
        }
        
        // Base64 encode to handle binary output and special characters
        return Base64.getEncoder().encodeToString(
            output.toString().getBytes());
    }
}

The client shell connects to this deployed service and invokes the executeCommand method via Axis2's RPC mechanism. From a network perspective, this looks like legitimate SOAP traffic—XML envelopes containing method calls and responses. The base64 encoding serves dual purposes: it handles binary output gracefully and provides minimal obfuscation (though certainly not security through obscurity).

One critical architectural constraint is Java version compatibility. The helper.jar must be compiled with a Java version that matches or is older than the target server's runtime. Axis2 1.3+ supports Java 1.6 through 1.8, and class file version mismatches will cause deployment failures. This means reconnaissance to identify the target's Java version is essential before compilation. The repository uses Axis2 1.3 libraries specifically to maintain backward compatibility with older deployments while still functioning on modern 1.6.3 versions.

The deployment process itself exploits Axis2's administrative interface. If you have credentials to the Axis2 management console or can upload files to the services directory, you simply deploy helper.jar as you would any legitimate service. No exploit needed—you're using the application exactly as designed, just for unauthorized purposes. This is why rpcshell requires "deployment access" rather than finding and exploiting a vulnerability. It's post-access tooling, not an initial compromise vector.

The communication protocol is deliberately simple. Commands are transmitted as string parameters in SOAP calls, and responses come back base64-encoded. There's no session management, no encryption layer, no advanced features like file upload or download. This minimalism is intentional—every feature adds complexity and potential failure points. For ad-hoc penetration testing where you need quick command execution to enumerate a system or escalate privileges, this stripped-down approach is actually advantageous. You're not managing complex state or debugging elaborate protocols; you're just running commands and reading output.

Gotcha

The most significant limitation is that rpcshell is not a shell in the traditional sense. Don't expect tab completion, environment variable persistence, or even the ability to change directories in a meaningful way. Each command executes in its own process context, so running 'cd /tmp' followed by 'pwd' won't show /tmp—you're back to the default working directory. This is a fundamental constraint of Runtime.exec() and there's no workaround within this architecture. For anything beyond basic enumeration commands, you'll need to chain operations in single command strings or escalate to a proper reverse shell.

The unencrypted communication is a massive red flag for any environment with network monitoring. Base64-encoded commands and responses are trivial to decode—any IDS/IPS with SSL/TLS inspection or even basic packet analysis will immediately spot suspicious SOAP traffic containing encoded system commands. There's no attempt at encryption or stealth. This makes rpcshell suitable only for environments where you're confident network monitoring is absent or you don't care about detection (such as authorized penetration tests with explicit scope).

Service naming conflicts create operational friction. If deployment fails because a service named "RPCHelper" already exists, you'll need to rename both the service class and update the client code to match. The repository documentation mentions this but doesn't provide tooling to automate renaming, so you're manually editing Java source and recompiling. For rapid testing scenarios where you might deploy and redeploy multiple times, this becomes tedious. Additionally, the Java version compatibility requirement means you need to maintain build environments with multiple Java versions if you're testing diverse targets.

Verdict

Use if: You have deployment credentials or upload access to an Axis2 server and need lightweight, standalone command execution without Metasploit's overhead. This tool shines in authorized penetration tests where detection isn't a concern and you just need quick enumeration or privilege escalation commands. It's also valuable for understanding how legitimate application features can be weaponized—a lesson applicable beyond just Axis2. Skip if: You need stealth (the unencrypted base64 traffic is trivially detectable), require a full-featured shell with session management and file transfer, or don't already have deployment access to the target server. For production red team engagements or any scenario where operational security matters, reach for something with encryption and more sophisticated tradecraft. And if you need comprehensive post-exploitation capabilities, just use Metasploit or the author's own Fuze tool—rpcshell's minimalism is a feature for some use cases but a limitation for others.

// ADD TO YOUR README
[![Featured on Starlog](https://starlog.is/api/badge/developer-tools/hatriot-rpcshell.svg)](https://starlog.is/api/badge-click/developer-tools/hatriot-rpcshell)