Tools

Java’s BaRMIe Back Door

A week ago I released a tool that I have been working on to enable security professionals to interact with applications that utilise Java’s Remote Method Invocation (RMI). This is the first in a series of blog posts covering RMI security and the tool I released, BaRMIe.

Source code for the tool can be found over at GitHub, along with binary releases. Slides for my talk at 44CON 2017 where I presented the results of my research can be found on SlideShare.

Why?

“RMI is outdated”

“Is that still a thing?”

“No one uses RMI anymore”

I first came across RMI during a pentest when nmap reported an “rmiregistry” service. I thought Remote Method Invocation alone sounded like something worth investigating further, but this service turned out to be really easy to attack. A few lines of code compiled against the RMI client’s JAR files was all it took and the service gave me unauthenticated access to the server’s file system (list, read, write, and delete files). Surprised by how easy that was, I wanted to find out how often RMI is used so insecurely and what else I could do with it.

RMI Security

My initial research quickly led to the discovery of many more instances of RMI being used insecurely. A key part of the problem seems to be that RMI was built to serve a specific purpose: invoking Java methods within another Java Virtual Machine (JVM). It was not built with security in mind. We can liken this to HTTP, except that HTTP is far more mature with a much larger user base. Over time a demand for security has led to HTTP evolving to support security. Modern web developers don’t even need to be particularly security aware because application frameworks bake security features in by default. RMI has none of this. Furthermore, the implementation of RMI is so simple and transparent that developers need not even be aware that they are interacting with a remote server.

The RMI protocol has no standard security features. Additional effort is required to incorporate security features like authentication and session management in front of classes/objects that are exposed over RMI.

Attacking RMI

My first attack against an RMI service required code compiled against the JAR files for the original client application. I wasn’t satisfied with that, I really wanted a zero-knowledge attack, which was one of the reasons I started researching the protocol. I later came across Adam Boulton’s presentation from AppSec USA 2008 – Security Assessing Java RMI – where he spoke about a zero-knowledge attack against RMI services. Unfortunately that attack relies on significant brute forcing over the network.

In the absence of a practical zero-knowledge attack, we need details of remote classes including method names, parameter types, and return types, in order to interact with an RMI service. The goal of BaRMIe is to build a set of common classes and methods that are exposed over RMI. Using these, we can enumerate an RMI endpoint to identify known classes and use them to attack the service.

BaRMIe supports three types of attacks against RMI services:

  1. Insecure Methods: RMI services often expose dangerous functionality that can be called directly provided the class/method details are known. Examples include unauthenticated file reading and writing.
  2. Deserialization via Object-type Parameters: RMI uses Java serialization making it a target for deserialization attacks. If a remote method accepts a parameter of the type ‘java.lang.Object’ then it can be used to deliver a deserialization payload.
  3. Deserialization via Illegal Method Invocation: Java does not verify that supplied method parameters are compatible with the actual method parameter type before deserializing the supplied method parameter. This weakness means that any non-primitive remote method parameter can be replaced with an arbitrary object using a TCP proxy, effectively triggering an illegal method call except that a deserialization payload is triggered before Java fails to execute the illegal method call.

Each of these attacks is facilitated using minimal RMI stub classes and interfaces that allow BaRMIe to call the target remote methods. BaRMIe also includes TCP proxying code to support deserialization attacks by enabling payloads to be injected at the network level.

In the next blog post on BaRMIe I’ll look at the technical aspects in more detail and cover some of the code and techniques used by BaRMIe to enumerate and attack RMI services. In the meantime, check it out!

Discussion

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.