Skip to content

[Java]: CWE-665 Insecure environment during RMI/JMX Server initialisation - All for one bounty #360

@timoles

Description

@timoles

Query

Link to pull request with your CodeQL query:

Relevant PR: github/codeql#5811

CVE ID(s)

List the CVE ID(s) associated with this vulnerability. GitHub will automatically link CVE IDs to the GitHub Advisory Database.

Report

Describe the vulnerability. Provide any information you think will help GitHub assess the impact your query has on the open source community.

CVE-2016-3427 was reported by Mark Thomas/Pierre Ernst who noticed that the “JMXConnectorFactory.connect” method of the JMX service actually accepts an Map of objects instead of just two strings (username/password). This makes it possible to send a Map that contains a malicious object that will be deserialized on the server side.

This vulnerability has the advantage that it even works against password protected JMX instances. Making it possible to exploit this issue as unauthenticated attacker. (Please note that a successful exploitation requires a valid Java Deserialization gadget (e.g. a vulnerable version of CommonsCollections) in its classloader)

Oracle patched this issue in JDK 8u91. The vulnerability was mitigated by installing a filter that by default only allows the usage of String objects. From the release notes:

A new java attribute has been defined for the environment to allow a JMX RMI JRMP server to specify a list of class names. These names correspond to the closure of class names that are expected by the server when deserializing credentials. For instance, if the expected credentials were a List, then the closure would constitute all the concrete classes that should be expected in the serial form of a list of Strings.

By default, this attribute is used only by the default agent with the following setting:

{   
   "[Ljava.lang.String;",   
   "java.lang.String" 
 }

Using JMX-RMI to monitor Java applications is a common thing. Most applications start the JMX-RMI service by passing certain command line arguments to the Java Runtime Environment. After updating to JDK8u91, these installations were protected.

However, there is also the case where the JMX-RMI service is started within the code itself. This is done by only a small number of applications, mostly as they need more control over the JMX service.

From an attacker perspective, this case is interesting as the fix requires that developers pass the attribute jmx.remote.rmi.server.credential.types as part of the environment to the JMX service. The JDK 8u91 release notes provide a minimal example:

Map<String, Object> env = new HashMap<>(1);
env.put ( 
 "jmx.remote.rmi.server.credential.types",
   new String[]{
    String[].class.getName(),
    String.class.getName()
  }
);

JMXConnectorServer server = JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbeanServer);

In Java 10 this solution was declared deprecated. Instead Oracle introduced the property RMIConnectorServer.CREDENTIALS_FILTER_PATTERN which complies with the filter patterns introduced by JEP290.

Map<String, Object> env = new HashMap<String, Object>();
String my_filter = "java.lang.String;!*"; // Deny everything but java.lang.String
env.put(RMIConnectorServer.CREDENTIALS_FILTER_PATTERN, my_filter);

This is a nice example of missing the "fail savely" design pattern: It moves the burden of fixing the issue to the developer, which must be aware of the potential vulnerability.

Regarding the detection rate of this rule: Right now we're checking if the necessary filters are set in a relative naive/good faith way. The assemption we make here is that the corresponding keys (e.g. RMIConnectorServer.CREDENTIALS_FILTER_PATTERN or jmx.remote.rmi.server.credential.types) are set by developers explicitly. Testing the filter would require parsing of the provided filter pattern.

  • Are you planning to discuss this vulnerability submission publicly? (Blog Post, social networks, etc). We would love to have you spread the word about the good work you are doing

We're planning on creating a blog post about this query and how we went about building it. We already briefly talked about this vulnerability itself here

Result(s)

Provide at least one useful result found by your query, on some revision of a real project.

  • Up until August 2020 Cassandra was vulnerable and this query is able to detect the insecure initialisation of the RMI server. Revisions before that are vulnerable, e.g. this one. The issue was fixed here and Cassandra is no longer vulnerable. (This issue was disclosed by us to a third party vendor forking Cassandra. It got fixed within the main repository shortly after) (Please note that I don't know how to run a specific revision within lgtm.com, if you can help me out here I can provide the link to the query directly.)
  • Tomcat was vulnerable up until November 2016 when this issue was fixed here Revision b0715ef477d7e05c202eb27d93b8e146a61f2a34 would have been vulnerable.
  • These LGTM results also detected potentially insecure configurations
    • For Glassfish the insecure configuration is only present when the authentication is disabled (The authentication method is still reachable, but without authentication the application is at risk anyway (if an attacker can reach the JMX service)).
    • For Hudi we don't see a realistic attack scenario, as the the service has to be configured in a quite particular configuration to be vulnerable. The exploitation of the service seems also difficult, as the RMI implementation seemed to be partially broken (at least for us in our lab).
    • We also disclosed an insecure configuration to Jetty. They don't see this insecure configuration an issue as the vulnerable JMX initialisation is within the Demo code which, according to them, should not be run in production. They also state that the use of jmx-remote-auth (which negates this finding), is document within the operation guide.

Metadata

Metadata

Assignees

No one assigned

    Labels

    All For OneSubmissions to the All for One, One for All bounty

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions