
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.txtThis 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.

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 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 -lThis 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 !

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 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.