Dando continuidade à série de postagens sobre desafios realizados, trago a documentação da máquina Amaterasu (nível Fácil/Easy), disponível gratuitamente no Proving Grounds Play.
Para quem não está familiarizado, os desafios do tipo Capture The Flag (CTF) envolvem máquinas vulneráveis que têm como objetivo testar as habilidades dos participantes em identificar e explorar essas falhas. Os competidores devem encontrar flags (bandeiras), que são provas de que conseguiram comprometer com sucesso os alvos designados.
Enumeração Link to heading
Para iniciar o processo de enumeração, realizei uma varredura de portas via nmap junto ao IP disponibilizado.
Comando: nmap -sV -p- --min-rate 10000 192.168.150.249
Parâmetros:
- -sV permite a identificação dos serviços/versões que estão rodando nas portas que forem identificadas como abertas (open);
- -p- permite o scan de todas as 65.535 portas TCP;
- --min-rate 10000 informa ao nmap para tentar enviar no mínimo 10000 pacotes por segundo, como uma tentativa de acelerar a análise (pode impactar a precisão dos resultados).
A varredura com nmap retornou diversas portas abertas, destacando-se as portas 21, 33414 e 40080. Visando facilitar o processo de análise e exploração, adicionei o IP 192.168.150.249 no arquivo /etc/hosts da máquina do atacante, atribuindo o nome amaterasu.pg ao IP.
O serviço FTP (21) aceitou conexão como anonymous:anonymous, porém não foi possível listar os arquivos:
Ao acessar o servidor web rodando na porta 40080, é possível visualizar a seguinte imagem:
Na sequência, enumerei o servidor web através da ferramenta dirsearch, utilizando a wordlist padrão da ferramenta dirb big.txt.
Comando: dirsearch -w /usr/share/wordlists/dirb/big.txt -x 404 -u http://amaterasu.pg:40080
Parâmetros:
- -w permite informar uma wordlist a ser utilizada para o processo de ataque de dicionário;
- -x 404 exclui o status code 404, o que facilita a análise do output do comando;
- -u permite a informação da URL a ser analisada.
A análise manual das pastas e do arquivo LICENSE identificados não retornou dados de interesse.
Em seguida, realizei uma comunicação com a porta 33414 através do telnet, onde foi possível confirmar que se trata de um servidor web:
Na sequência rodei a ferramenta dirsearch no alvo.
Comando: dirsearch -w /usr/share/wordlists/dirb/big.txt -x 404 -u http://amaterasu.pg:33414
Parâmetros:
- -w permite a informação de uma wordlist a ser utilizada para o processo de ataque de dicionário;
- -x 404 exclui o status code 404, o que facilita a análise do output do comando;
- -u permite a informação da URL a ser analisada.
Como resultado, foi possível identificar dois endpoints. Ao acessar o endpoint /info via navegador foi possível identificar que na porta 33414 roda um serviço chamado Python File Server REST API v2.5:
Ao acessar o endpoint /help via navegador foi possível identificar os endpoints existentes no servidor e por quais métodos é possível fazer requisições:
Exploração e acesso inicial Link to heading
Ao realizar uma requisição para o endpoint /file-upload utilizando o método POST, complementando com o parâmetro -i para visualizar o cabeçalho de resposta, foi possível perceber a falta do parâmetro file, indicado pela mensagem de erro exibida:
Ao efetuar uma nova requisição, dessa vez efetuando o upload de um arquivo de testes através do parâmetro -F, que permite o envio de dados de formulário (adicionando o formato multipart/form-data ao request), foi possível identificar a falta do parâmetro filename:
Na sequência, presumindo que o parâmetro filename diz respeito ao destino do upload, informei o diretório /var/www/html/, onde obtive um erro de código 500. Entretanto, ao informar o diretório /tmp/, a requisição retornou no parâmetro message que o upload teve sucesso:
Ao acessar o endereço http://amaterasu.pg:33414/file-list?dir=/tmp, para visualizar os arquivos do diretório /tmp/, foi possível identificar que o arquivo teste.txt realmente sofreu upload:
Como tenho capacidade de visualizar diretórios, efetuei a visualização do diretório /home o que me possibilitou enumerar o usuário alfredo:
Também efetuei a enumeração dos diretórios e arquivos do usuário alfredo, onde pude visualizar o diretório /home/alfredo/.ssh, indicando que o usuário pode autenticar via ssh:
Ao tentar realizar o upload da minha chave pública de SSH para o diretório /home/alfredo/.ssh, pude notar que o servidor só aceita arquivos com extensão txt, pdf, png, jpg, jpeg ou gif:
Para contornar essa limitação, efetuei uma cópia do id_rsa.pub, dando a nomenclatura id_rsa.txt, onde por fim consegui efetuar o upload do arquivo em um arquivo denominado authorized_keys. Esse arquivo permite o armazenamento das chaves públicas autorizadas a se conectar via SSH.
Por fim, efetuei o acesso via SSH como alfredo:
Uma vez com acesso à máquina, iniciei o processo de análise manual do sistema de arquivos em busca de artefatos que possam contribuir com a minha exploração.
Dentro do diretório /home/alfredo foi possível localizar o arquivo local.txt, contendo a flag de usuário:
Escalonamento de Privilégios Link to heading
Iniciando a análise de vetores de escalonamento de privilégios, analisei o arquivo /etc/crontab, responsável pela configuração do agendador de tarefas cron, onde foi possível identificar uma entrada onde o arquivo /usr/local/bin/backup-flask.sh roda a cada minuto com privilégios de root:
Ao analisar as permissões que o usuário alfredo tem sobre o arquivo, bem como seu conteúdo, foi possível identificar que o script executa algumas ações:
A última linha do arquivo chama atenção por realizar a compactação de todos os arquivos no diretório /home/alfredo/restapi, criando o arquivo /tmp/flask.tar.gz. Como o asterisco representa um wildcard, podemos utilizar essa falta de especificação de destino/arquivos a serem compactados para escalonar privilégios.
Para tal, inicialmente criei um arquivo chamado privesc.sh dentro do caminho (PATH) /home/alfredo/restapi, contendo um comando para escrever no arquivo /etc/sudoers uma regra que dá permissão ao usuário alfredo em todo ambiente (ALL), possibilitando que ele execute comandos como root, sem fornecer senha (NOPASSWD), sem qualquer tipo de restrição (ALL).
Comando: echo 'alfredo ALL=(root) NOPASSWD: ALL' > /etc/sudoers
Na sequência, escrevi uma string vazia em dois arquivos, --checkpoint=1 e --checkpoint-action=sh privesc.sh, fazendo com que a ferramenta tar execute-os como parâmetro:
Como resultado, foi possível escalar privilégios para o usuário root:
Ao acessar o diretório /root foi possível localizar o arquivo proof.txt, contendo a flag de root:
Conclusão Link to heading
No desafio amaterasu pude aprender como realizar o escalonamento de privilégios através da manipulação de wildcard junto à ferramenta tar, onde destaco mais uma vez a importância de atenção aos detalhes, pois apenas uma análise correta do arquivo backup-flask.sh permite o escalonamento com sucesso.