Skip to content

Commit

Permalink
Merge pull request #21 from qtc-de/develop
Browse files Browse the repository at this point in the history
Update documentation
  • Loading branch information
qtc-de authored Dec 8, 2021
2 parents 0e5a68c + 215f0de commit 7d26261
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 34 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -546,9 +546,9 @@ on them:
[+] Portscan finished.
```

The ``scan`` action uses *remote-method-guesser's* port argument as an indicator which ports to scan. Using ``-``
as a port value results in a scan for all common *RMI* ports. You can also specify numbers, ranges and lists.
Additionally, you can specify further port specifications after the ``scan`` action:
By default, the scan actions uses a preconfigured list of common *RMI ports*. To customize the list of ports to scan,
you can use the ``--ports`` option. This option accepts plain numbers and number ranges for port specifications.
The dash character (``-``) can be used to reference the default port list.

```console
[qtc@devbox ~]$ rmg scan 172.17.0.2 --ports 0-100 1000-1100 9000-9020 35000-36000 40000-45000
Expand Down Expand Up @@ -613,7 +613,7 @@ from incoming client connections without disrupting any services. To forward con
corresponding target as an additional argument. Targets can be specified in two different ways:

1. The IP address and port of an RMI registry together with the bound name of the corresponding *JMX instance*:
```console
```console
[qtc@devbox ~]$ rmg roguejmx 172.17.0.1 4444 --forward-host 172.17.0.2 --forward-port 9010 --forward-bound-name jmxrmi
[+] Statring RogueJMX Server on 172.17.0.1:4444
[+] --> Assigned ObjID is: [6633018:17cb5d1bb57:-7ff8, -8114172517417646722]
Expand All @@ -622,7 +622,7 @@ corresponding target as an additional argument. Targets can be specified in two
```

2. The IP address and port of the *JMX* service itself together with it's *ObjID* value:
```console
```console
[qtc@devbox ~]$ rmg roguejmx 172.17.0.1 4444 --forward-host 172.17.0.2 --forward-port 41001 --forward-objid '[-40935072:17cd9fc77c4:-7ff8, 6731522247396892423]'
[+] Statring RogueJMX Server on 172.17.0.1:4444
[+] --> Assigned ObjID is: [6633018:17cb5d1bb57:-7ff8, -8114172517417646722]
Expand All @@ -639,7 +639,7 @@ to *deserialization attacks*. These attacks can target different *RMI components
* *RMI registry*
* *DGC*
* *Activator*
* User defined *RemoteObjects* (*Application level*)
* User defined *RemoteObjects* (*application level*)


##### Well Known RMI Components
Expand Down
6 changes: 4 additions & 2 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@ In this folder you can find more detailed documentation on *remote-method-guesse
work in progress and will be updated from time to time. So far, the following topics are documented:

* *Java RMI*
* [Security Manager List](./rmi/security-manager-list.md)
* [AccessControlContext List](./rmi/access-control-contexts.md)
* [Known Remote Objects](./rmi/known-endpoints.md)
* [Serialization Filter List](./rmi/serialization-filter-list.md)
* [Unicast Remote Object](./rmi/unicast-remote-object.md)

* *remote-method-gusser*
* [Actions](./rmg/actions.md)
* [Plugin System](./rmg/plugin-system.md)
* [Activation System](./rmg/activation-system.md)
* [Media](./rmg/media.md)
* [Method-Guessing](./rmg/method-guessing.md)
* [Plugin System](./rmg/plugin-system.md)


### Java RMI - Attack Surface
Expand Down
2 changes: 1 addition & 1 deletion docs/rmg/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ In this folder you can find more detailed documentation on *remote-method-guesse

* [Actions](./actions.md)
* [Activation System](./activation-system.md)
* [Plugin System](./plugin-system.md)
* [Media](./media.md)
* [Method-Guessing](./method-guessing.md)
* [Plugin System](./plugin-system.md)
3 changes: 1 addition & 2 deletions docs/rmg/actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -639,8 +639,7 @@ When targeting *RMI* services via *SSRF*, there are two requirements that need t

The two requirements mentioned above restrict *SSRF* attacks on *Java RMI* endpoints quite a bit. However, when both conditions
are met, you can fully utilize the *RMI* service via *SSRF*. The *remote-method-guesser* repository also contains an [SSRF example
server](docker pull ghcr.io/qtc-de/remote-method-guesser/rmg-ssrf-server:1.0), that can be used to practice *SSRF* attacks against
*Java RMI*.
server](/docker/ssrf-server), that can be used to practice *SSRF* attacks against *Java RMI*.

To perform the different checks of *remote-method-guesser's* ``enum`` action via *SSRF*, you can use the ``--scan-action`` option.
Without specifying this option, the *SSRF* payload generated for the ``enum`` action is similar to the payload created when using
Expand Down
4 changes: 3 additions & 1 deletion docs/rmg/media.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

----

This document provides some more usage examples for *rmg* in ``gif`` format.
This document provides some more usage examples for *remote-method-guesser* in ``gif`` format.
Notice: Some of the usage examples are probably outdated and do not conform to the current
version of *remote-method-guesser*.


### Registry Bypass
Expand Down
2 changes: 1 addition & 1 deletion docs/rmi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
In this folder you can find more detailed documentation on *Java RMI* features
that are related to *remote-method-guesser*:

* [AccessControlContext List](./access-control-contexts.md)
* [Known Remote Objects](./known-endpoints.md)
* [Security Manager List](./security-manager-list.md)
* [Serialization Filter List](./serialization-filter-list.md)
* [Unicast Remote Object](./unicast-remote-object.md)
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
### RMI Security Managers
### Access Control Contexts

----

During remote class loading attacks, the existence and configuration of a *SecurityManager* is a crucial point that can limit
the impact of the vulnerability. Whereas remote class loading attacks on the application level fully depend on a user defined
*SecurityManager*, internal RMI communication uses *SecurityManagers* per default with different configurations. This document
provides a short list of the default *SecurityManagers* with their corresponding configuration. The source code samples for the filters were
copied from the current state (at the time of writing) of the [openjdk GitHub repository](https://github.com/openjdk/jdk).
During remote class loading attacks, the presence and configuration of a *SecurityManager* is a crucial point that can limit
the impact of a vulnerable server. Without a *SecurityManager* present, *Java RMI* is not allowed to access codebases that
were not explicilty allowed during startup (*server side codebases*). Attempting a codebase attack on a server that does not
use a *SecuriyManager* results in the famous ``no security manager: RMI class loader disabled`` error message.

When writing *RMI* applications from scratch, adding a *SecurityManager* is fully optional. This is probably the most common
usage scenario and servers that do not use a *SecurityManager* are encountered quite often. However, when using pre-existing
*RMI* components, they may inlcude a *SecurityManager* by default. One example for this situation is the default ``rmiregistry``
utility that is shipped with *Java* installations. This utility starts an *RMI registry* service and sets a *SecurityManager*
by default.

Even with a *SecurityManager* present, codebase attacks can still be restricted by the ``AccessControlContexts`` that are
defined for the targeted component. Whereas the *SecurityManager* configuration on the application level fully depends on a
user defined policy, internal *RMI* communication uses separate and preconfigured ``AccessControlContexts`` for the different
*RMI* components.

In this document, some of the default ``AccessControlContexts`` used by internal *RMI* communication are explained in more
detail. The code samples in this documet were copied from the current state (at the time of writing) of the [openjdk GitHub
repository](https://github.com/openjdk/jdk).


### LoaderHandler - Security Manager
Expand All @@ -16,7 +30,7 @@ copied from the current state (at the time of writing) of the [openjdk GitHub re
* The ``LoaderHandler.java`` class is responsible for remote class loading and its *SecurityManager* settings
are therefore probably the most important.
* Within it's ``loadClass`` method, the ``LoaderHandler`` stops class loading on its own and delegates the request
to the parent class loader if no *SecurityManager* is defined:
to the parent class loader when no *SecurityManager* is defined:
```java
SecurityManager sm = System.getSecurityManager();
if (sm == null) {
Expand Down Expand Up @@ -46,16 +60,15 @@ copied from the current state (at the time of writing) of the [openjdk GitHub re

* When a *SecurityManager* is defined, the actual loader is created within an ``AccessControlContext`` that includes
permissions only for the specified codebase. That means:
* File system permissions for the corresponding folder on the file system if the codebase is a file system URL.
* Network permissions for the corresponding remote host, if the codebase is a remote URL.
* File system permissions for the corresponding folder on the file system, if the codebase is a file system *URL*.
* Network permissions for the corresponding remote host, if the codebase is a remote *URL*.

* The ``AccessControlContext`` is created by the ``getLoaderAccessControlContext`` function:
```java
private static AccessControlContext getLoaderAccessControlContext(
URL[] urls)
{
[...]

// createClassLoader permission needed to create loader in context
perms.add(new RuntimePermission("createClassLoader"));

Expand All @@ -64,7 +77,6 @@ copied from the current state (at the time of writing) of the [openjdk GitHub re

// add permissions reuiqred to load from codebase URL path
addPermissionsForURLs(urls, perms, true);

[...]
}
```
Expand All @@ -86,17 +98,17 @@ copied from the current state (at the time of writing) of the [openjdk GitHub re
* Summarized: Without a manually defined security policy, classes loaded in remote class loading attacks are always
restricted by the ``LoaderHandler``. Effectively, they are only allowed to access their own codebase, to read
*java* properties and to create new class loaders with the same security permissions. Furthermore, the parent
``AccessControlContext`` (e.g. the one of the RMI registry or the DGC) must also allow access to the requested
codebase.
``AccessControlContext`` (e.g. the one of the *RMI registry* or the *DGC*) must also allow access to the requested
operation.


### RMI Registry - Security Manager

----

* The RMI registry defines it's ``AccessControlContext`` in the ``RegistryImpl`` class, within the ``getAccessControlContext`` function.
* The *RMI registry* defines it's ``AccessControlContext`` in the ``RegistryImpl`` class, within the ``getAccessControlContext`` function.
* Apart from the default permissions, custom permissions can be added by specifying a custom policy file.
* Relevant permission definitions:
* Relevant permission definitions are:
```java
perms.add(new SocketPermission("*", "connect,accept"));
perms.add(new SocketPermission("localhost:"+port, "listen,accept"));
Expand All @@ -107,8 +119,27 @@ copied from the current state (at the time of writing) of the [openjdk GitHub re
perms.add(new FilePermission("<<ALL FILES>>", "read"));
```

* With these permission definitions, the RMI registry allows remote class loading in general. However, the ``<<ALL FILES>>`` permission
* With these permissions, the *RMI registry* allows remote class loading in general. However, the ``<<ALL FILES>>`` permission
does not effectively apply, as it is overwritten by the ``AccessControlContext`` used by the ``LoaderHandler``.
* The *RMI registry* may uses a *SecurityManager* by default. Whether this is the case depends on the mechanism the
*RMI registry* is initialized. When using the ``createRegistry`` function from the ``RegistryImpl`` class to create the
registry, a *SecurityManager* is always used:
```java
public static RegistryImpl createRegistry(int regPort) throws RemoteException {
// Create and install the security manager if one is not installed already.
if (System.getSecurityManager() == null) {
System.setSecurityManager(new SecurityManager());
}
[...]
```
This is the function used by the ``rmiregistry`` utility that shipped with *Java* installations. However,
when using the ``createRegistry`` function from the ``LocateRegistry`` to create the registry, the corresponding
object is created directly without using a *SecurityManager*:
```java
public static Registry createRegistry(int port) throws RemoteException {
return new RegistryImpl(port);
}
```


### Distributed Garbage Collector (Inbound) - Security Manager
Expand All @@ -117,7 +148,7 @@ copied from the current state (at the time of writing) of the [openjdk GitHub re

* The ``AccessControlContext`` for *inbound DGC traffic* is defined in ``DGCImpl.java`` within a *static* block.
* Custom policy files are ignored by the *DGC* and only the hard coded permissions are used.
* The hard coded permissions are rather straight forward:
* The hard coded permissions are rather strict:
```java
Permissions perms = new Permissions();
perms.add(new SocketPermission("*", "accept,resolve"));
Expand All @@ -126,18 +157,18 @@ copied from the current state (at the time of writing) of the [openjdk GitHub re
```

* This means, that the *DGC* does always reject remote class loading attempts, as it's security policy does not even allow
remote connections.
outbound connections.
* Additionally (although not really related to the *SecurityManager*), ``UnicastServerRef`` checks whether a call is targeting
the *DGC* during the dispatching process. If the target is the *DGC*, ``useCodebaseOnly`` is explicitly set to ``true`` for
the ``MarshalInputStream`` of the call.
the ``MarshalInputStream`` processing the call.
```java
Class<?> clazz = Class.forName("sun.rmi.transport.DGCImpl_Skel");
if (clazz.isAssignableFrom(skel.getClass())) {
((MarshalInputStream)in).useCodebaseOnly();
}
```

* Therefore, remote class loading should never work on a modern *DGC*.
* Therefore, remote class loading should never work on a modern *DGC* instance.


### Distributed Garbage Collector (Outbound) - Security Manager
Expand All @@ -159,6 +190,7 @@ copied from the current state (at the time of writing) of the [openjdk GitHub re
}
```

* The corresponding ``AccessControlContext`` is used for all calls to the ``dirty`` and ``clean`` methods.
* The corresponding ``AccessControlContext`` is used for all calls to the ``dirty`` and ``clean`` methods and allows
outbound connections only.
* As the ``LoaderHandler`` class requests ``connect,accept`` socket permissions within it's ``addPermissionsForURLs`` function,
remote class loading would probably be rejected by the ``LoaderHandler``.

0 comments on commit 7d26261

Please sign in to comment.