Guide du pirate pour les détections basées sur DACL (partie 3)

Cette série de blogs a été rédigée par Megan Nilsen, consultante en sécurité, et Andrew Schwartz, responsable de la pratique TAC.

1 Introduction

Dans ce troisième et dernier volet, nous poursuivons notre exploration des attaques par objet et par attribut et de leur détection. Tout comme la première partie s’est concentrée sur l’étude des organigrammes fournis dans le document DACL des Hacker Recipes, et la partie 2 s’est concentrée sur les attributs modifiables à l’aide de PowerMadLa partie 3 se concentrera sur une collection d’attributs supplémentaires qui n’entrent pas dans le cadre des parties 1 et 2, mais que nous avons identifiés comme présentant un intérêt pour la construction de détections.

Bien que ce billet utilise différents outils d' »attaque », il convient de noter que l’outil est un moyen d’exécuter l’attaque, mais que nous nous concentrons davantage sur les techniques sous-jacentes d’attributs modifiables et sur les détections qui les entourent.

Tout comme les deux (2) premiers messages, voici quelques rappels :

  • Nous partons du principe que l’adversaire a déjà un pied dans le domaine et qu’il a acquis l’accès nécessaire pour apporter des modifications aux objets dont nous allons parler.
  • La post-exploitation n’est pas une priorité.
  • Le renseignement appliqué à l’attribution de l’adversaire n’a pas été cartographié.
  • Un sous-ensemble de la journalisation des événements Windows a été utilisé et tous les points de données télémétriques possibles dans cet ensemble de données n’ont pas été analysés.

2 Configuration de l’enregistrement

Comme indiqué dans la partie 1, à des fins de télémétrie, nous nous appuierons sur l’établissement d’une liste de contrôle d’accès au système (SACL) « Audit » pour chacun de ces attributs et les ID d’événements Windows suivants :

La configuration d’une SACL est une étape supplémentaire qui doit être réalisée même si les événements Windows énumérés ci-dessus sont en cours d’acquisition.

Veuillez vous reporter à la partie 1A pour savoir comment activer et configurer la configuration de la journalisation du SACL et comment activer ou ingérer les ID d’événements Windows ci-dessus.

3 Format du blog

En raison de la longueur de ce billet et du nombre d’attributs couverts, il est important de se rappeler quelques règles de formatage clés de la partie 1 au fur et à mesure que nous avançons dans ce billet.

  • Chaque section contiendra les titres suivants :
  • Nom de l’attribut (nom commun (CN) de l’attribut)
  • Contexte
    • Cette page donne un bref aperçu de ce qu’est l’attribut (LDAP-Display-Name) et les liens pertinents vers la documentation de Microsoft.
  • Modifier l’attribut (Attaque)
    • Couvre la façon dont l' »attaque » a été réalisée, y compris la configuration pertinente pour modifier l’attribut en question, les captures d’écran/commandes et les outils utilisés.
    • Si un audit supplémentaire a été activé pour la mise en place de la détection, il sera probablement également couvert ici – ou, si la configuration supplémentaire était plus complexe, elle sera répartie dans une rubrique précédente ou suivante.
  • Construction des détections
    • Couvrira une variété de détections qui incluront une gamme de complexité
    • Comme indiqué dans l’introduction, tous les points de données télémétriques possibles de cet ensemble de données n’ont pas été analysés. Cependant, nous avons fait de notre mieux pour couvrir les ID d’événements les plus accessibles et les plus importants pour l’élaboration de détections.
    • Si nécessaire, nous fournirons un flux logique pour les détections qui impliquent une plus grande complexité ou des informations supplémentaires pour interpréter ce qui est affiché. Toutefois, la plupart des détections suivront un format similaire et ne seront pas expliquées plus en détail.

4 Attributs

4.1 AdminSDHolder

4.1.1 Contexte

Le AdminSDHolder L’objet AdminSDHolder agit comme un conteneur qui est rempli avec des autorisations par défaut. Ce conteneur est ensuite utilisé comme modèle pour les comptes protégés afin d’empêcher toute altération ou modification involontaire/non autorisée. Les utilisateurs protégés peuvent être définis par la politique du domaine, mais comprennent aussi généralement par défaut des utilisateurs appartenant à des groupes tels que Admins de domaine, Administrateurs, Admins d’entreprise et Admins de schéma.

Les attaquants qui ont obtenu des privilèges suffisants peuvent utiliser ce conteneur pour maintenir la persistance des listes de contrôle d’accès (ACL) à l’espace de stockage. AdminSDHolder sont réappliqués par défaut toutes les 60 minutes.

4.1.2 Modification de l’objet (attaque)

Add-DomainObjectAcl -TargetIdentity ‘CN=AdminSDHolder,CN=System,DC=BREAKFASTLAND,DC=local’ -PrincipalIdentity dacled.egg -Rights All -verbose 

Chiffre 1 – Modifier l’objet

4.1.3 Construction de la détection

4.1.3.1 Détection avec les ID d’événements 5136 et 4662
index=main ((EventCode=5136 Class=container DN="CN=AdminSDHolder,CN=System,DC=BREAKFASTLAND,DC=LOCAL" LDAP_Display_Name=nTSecurityDescriptor) OR (index=main Account_Name!=*$ Object_Type="%{19195a5b-6da0-11d0-afd3-00c04fd930c9}" Object_Name="%{754fb287-55d2-4d68-b7fc-0332e1746740}"  EventCode=4662 Access_Mask = 0x40000))
| eval Logon_ID=if(EventCode==4662,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))
| eval user=if(EventCode==4662,mvindex( Account_Name,-1), mvindex( Account_Name,-1))
| eval DACL=if(EventCode==5136,mvindex( Value,-1), mvindex( Value,-1))
| join type=outer Logon_ID
    [ search index=main Account_Name!=*$ Object_Type="%{19195a5b-6da0-11d0-afd3-00c04fd930c9}" Object_Name="%{754fb287-55d2-4d68-b7fc-0332e1746740}"  EventCode=4662 Access_Mask = 0x40000
    | eval Props=Properties
    | eval AccessMask=Access_Mask
    | eval ObjectType=Object_Type
    | eval ObjectName=Object_Name
    |table Account_Name,Logon_ID,Props,AccessMask,ObjectType, ObjectName] 
| table  _time, Logon_ID, Account_Name, Props, AccessMask, ObjectType, ObjectName,  DN, GUID, DACL, Class, Type, LDAP_Display_Name
|stats values by _time, Logon_ID, DACL

Image002 1

Chiffre 2 – Détection à l’aide d’identifiants d’événements multiples (1)

Image003 2

Chiffre 3 – Détection à l’aide d’identifiants d’événements multiples (2)

4.2 ms-DS-Supported-Encryption-Types

4.2.1 Contexte

Le msDS-SupportedEncryptionTypes définit les algorithmes de chiffrement que Kerberos est autorisé à utiliser pour le chiffrement des tickets Kerberos.

4.2.2 Modification de l’attribut (Attaque)

Avant de pouvoir modifier l’attribut msDS-SupportedEncryptionTypes nous devons d’abord comprendre comment les valeurs hexagonales et/ou décimales sont associées aux types de chiffrement. afin de pouvoir correctement modifier l’attribut avec notre cmdlet PowerMad.

Le graphique lié ici indique la valeur décimale, la valeur hexadécimale et les types de chiffrement pris en charge par le msDS-SupportedEncryptionTypes peut être défini comme suit. Pour nos besoins, nous allons utiliser la valeur décimale 24 (valeur hexagonale 0x18) pour modifier l’attribut afin d’activer la fonction support pour les types de cryptage AES 128 et AES 256. Cette valeur a été choisie arbitrairement.

Image004

Chiffre 4 – Modification de l’attribut

Image005

Chiffre 5 – Validation du changement de modification d’attribut

4.2.3 Construction de la détection

4.2.3.1 Détection avec les ID d’événements 5136, 4624 et 4662
index=main ((EventCode=5136 AND LDAP_Display_Name=msDS-SupportedEncryptionTypes)  OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM") OR (EventCode=4662 AND Access_Mask=0x20))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1)) 
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))  
| eval Mod_Value=if(EventCode==5136,mvindex(Value,-1), mvindex(Value,-1))  
| join type=outer Logon_ID    
        [ search (EventCode=5136) OR (EventCode=4624)     
        | stats count by Logon_ID, Account_Name, Source_Network_Address 
        | table Account_Name,Logon_ID, Source_Network_Address ]  
| join type=outer Logon_ID
    [ search index=main Account_Name!=*$  EventCode=4662 Access_Mask = 0x20
    | eval Props=Properties
    | eval AccessMask=Access_Mask
    | eval ObjectType=Object_Type
    | eval ObjectName=Object_Name
    | rex field=Message "(?<Object_Properties>(?ms)(?<=)Properties:(.*?)(?=Additional\s+))"
    |table Account_Name,Logon_ID,Props,AccessMask,ObjectType, ObjectName, Object_Properties] 
| table _time, Mod_Account, Source_Network_Address , Class, DN, Logon_ID, Type, LDAP_Display_Name, Mod_Value, AccessMask, Props, Object_Properties
| where  len(Class)>0
| stats values by _time, Mod_Value

Image006 1

Chiffre 6 – Détection à l’aide de plusieurs ID d’événements (1)

Image007 2

Chiffre 7 – Détection à l’aide de plusieurs ID d’événements (2)

4.3 ms-DS-Reveal-On-Demand-Group (en anglais)

Pour cette section, nous ferons référence au blog À la limite du niveau zéro : le cas curieux du RODC par Elad Shamir (@elad_shamir). L’article de blog susmentionné est un excellent outil pour comprendre les RODC et l’importance de l’interface d’administration. msds-RevealOnDemandGroup attribut.

Toutefois, pour résumer dans le cadre de ce billet, l’attribut msds-RevealOnDemandGroup L’attribut msds-RevealOnDemandGroup stocke les objets (c’est-à-dire les utilisateurs, les ordinateurs, les groupes) dont les mots de passe sont autorisés à être mis en cache sur un contrôleur de domaine en lecture seule (RODC).

4.3.1 Modifier les attributs (Attaque)

Set-ADObject -Identity ‘CN=BREAKFAST-DC-03,OU=Domain Controllers,DC=BREAKFASTLAND,DC=LOCAL’ -Add @{‘msDS-RevealOnDemandGroup’=@(‘CN=Allowed RDOC Password Replication Group,CN=Users,DC=BREAKFASTLAND,DN=LOCAL’, ‘CN=dacled.egg,CN=Users,DC=BREAKFASTLAND,DC=LOCAL’)} -Server 10.0.2.4

Image008

Figure 8 – Modification de l’attribut

Image009

Figure 9 – Validation de la modification de l’attribut

4.3.2 Construction de la détection

4.3.2.1 Détection à l’aide des ID d’événements 5136, 4624 et 4662
index=main ((EventCode=5136 AND LDAP_Display_Name=msDS-RevealOnDemandGroup)  OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM") OR (EventCode=4662 AND Access_Mask=0x20 AND {303d9f4a-1dd6-4b38-8fc5-33afe8c988ad}))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1)) 
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))  
| join type=outer Logon_ID    
        [ search (EventCode=5136) OR (EventCode=4624)     
        | stats count by Logon_ID, Account_Name, Source_Network_Address 
        | table Account_Name,Logon_ID, Source_Network_Address ]  
| join type=outer Logon_ID
    [ search index=main Account_Name!=*$  EventCode=4662 Access_Mask = 0x20
    | eval Props=Properties
    | eval AccessMask=Access_Mask
    | eval ObjectType=Object_Type
    | eval ObjectName=Object_Name
    | rex field=Message "(?<Object_Properties>(?ms)(?<=)Properties:(.*?)(?=Additional\s+))"
    |table Account_Name,Logon_ID,Props,AccessMask,ObjectType, ObjectName, Object_Properties] 
| table _time, Mod_Account, Source_Network_Address , Class, DN, Logon_ID, Type, LDAP_Display_Name, Value, AccessMask, Props, Object_Properties
| where  len(Class)>0
| stats values by _time, Value, Logon_ID

Image010 1

Figure 10 – Détection avec les ID d’événements 5136, 4662 et 4624 (1)

Image011 2

Figure 11 – Détection avec les ID d’événements 5136, 4662 et 4624 (2)

4.4 GPC-Machine-Extension-Names

4.4.1 Contexte

Le gPCMachineExtensionName maintient une liste d’identifiants uniques globaux (GUID) pour lesquels les extensions côté client des objets de stratégie de groupe (GPO) et les snap-ins de la console de gestion Microsoft (MMC) sont requis par les paramètres de la stratégie machine.

En modifiant les GUIDS stockés dans l’attribut, un attaquant pourrait potentiellement utiliser GPO pour extraire un fichier d’un hôte contrôlé à distance et le télécharger vers un contrôleur de domaine.

4.4.2 Modification de l’attribut (Attaque)

Pour cette séquence d’attaque particulière, nous suivrons de très près le chemin de l’attaque tel qu’il est décrit dans ce billet de blog de TrustedSec.

Tout d’abord, nous allons effectuer une reconnaissance pour identifier le nom du GPO que nous allons modifier.

Image012

Figure 12 – Effectuer une reconnaissance

Comme vous pouvez le voir, le « DisplayName » de la GPO est AttackGPO, mais son nom, et la valeur dont nous aurons besoin pour effectuer nos modifications, est « {7ECE4273-CEEB-44BA-B777-C5FE3DBES 257} ».

$objs= Get-ADObject -SearchBase “CN=Policies,CN=System,DC=BREAKFASTLAND,DC=LOCAL” -LDAPFilter “(objectclass=*)” -Credential $creds -Server 10.0.2.4 -Properties displayName,gPCMachineExtensionNames

$dcgpos =$objs | ?{$_.displayName -like “Attack”}

$dcgpos

Image013

Figure 13 – Effectuer une reconnaissance

Avec un nom de GPO et un GUID en main, nous pouvons maintenant lancer notre attaque.

Note : Pour mener cette attaque correctement, il faut remplacer l’élément gPCMachineExtensionNames avec la chaîne [{GUID}{GUID}] ne fonctionnera évidemment pas correctement. Cependant, étant donné que nous ne nous intéressons qu’à la détection des modifications apportées à l’objet, et pas nécessairement à la conception d’une attaque fonctionnelle, cela suffit à générer les données de journalisation dont nous aurons besoin pour la détection au sein de notre SIEM. Pour exécuter correctement cette attaque, nous vous recommandons de lire les références liées à cette section (ou les liens courts ci-dessus), car elles font un travail fantastique en vous guidant à travers la séquence d’attaque désignée. Il est également important de noter quee GPO a été créé dans le but d’effectuer ces modifications, soyez prudent si vous exécutez l’attaque suivante dans un environnement de production.

$dcgomain = $dcgpos | ?{$_.Name -eq “{7ECE4273-CEEB-44BA-B777-C5FE3DBE5257}”}

$gpcme = “[{GUID}{GUID}]” + $dcgpomain.gPCMachineExtensionNames

Set-ADObject -Replace @{gPCMachineExtensionNames=$gpcme} -Server 10.0.2.4 -Credential $creds -Identity $dcgpomain.DistinguishedName

Get-ADObject -Credential $creds -Server 10.0.2.4 -Identity $dcgpomain.DistinguishedName -Properties displayName, gPCMachineExtensionNames

Image014

Figure 14 – Modification de la GPO

Et nous pouvons confirmer par Active Directory Service Interface Editor (ADSI) que la modification a été apportée au bon GPO :

Image015

Figure 15 – Validation des modifications

4.4.3 Construction de la détection

4.4.3.1 Détection avec les ID d’événements 5136 et 4624
index=main ((EventCode=5136 AND LDAP_Display_Name=gPCMachineExtensionNames)  OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM"))  
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1))  
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))   
| join type=outer Logon_ID     
        [ search (EventCode=5136) OR (EventCode=4624)      
        | stats count by Logon_ID, Account_Name, Workstation_Name  
        | table Account_Name,Logon_ID, Workstation_Name ]   
| table _time, EventCode, Mod_Account, Workstation_Name , Class, DN, Logon_ID, Type, LDAP_Display_Name, Value 
| where  len(Class)>0 

Image016 1

Figure 16 – Requête finale pour la modification de gPCMachineExtensionName (1)

Image017 2

Chiffre 17Requête finale pour la modification de gPCMachineExtensionName (2)

4.5 GPC-File-Sys-Path

4.5.1 Contexte

gpC-File-Sys-Path est un autre attribut basé sur les GPO qui, comme l’attribut gPCMachineExtensionNamepeut donner accès aux « droits clonés dans le dossier spécifique au GPO sur le système de fichiers où se trouve le SYSVOL associé » (Un atout dans la manche, p. 30) lorsqu’un utilisateur se voit accorder un accès en écriture pour un GPO.

Vous pouvez voir dans l’image ci-dessous que l’élément gPCFileSysPath renvoie à l’emplacement du Sysvol.

Image018

Figure 18 – gPCFileSysPath avant modification

4.5.2 Modification de l’attribut (Attaque)

En utilisant exactement le même chemin d’attaque que nous avons fait pour l’attaque gPCMachineExtension nous pouvons utiliser la reconnaissance déjà effectuée et créer simplement une nouvelle variable avec laquelle stocker notre changement. Ensuite, nous effectuons et confirmons la modification avec la même commande PowerShell, en ajustant la commande pour ajouter notre nouvelle variable.

$gpfsp = \\imposter.LOCAL\SysVol\imposter.LOCAL\Policies\{7ECE4273-CEEB-44BA-B777-C5FE3DBE5257} + $dcgpomain.gPCMachineExtensionNames
 
Set-ADObject -Replace @{gPCFileSysPath=$gpfsp} -Server 10.0.2.4 
-Credential $creds -Identity $dcgpomain.DistinguishedName
 
Get-ADObject -Credential $creds -Server 10.0.2.4 -Identity $dcgpomain. DistinguishedName -Properties displayName, gPCFileSysPath

Image019

Figure 19 – Modification de l’attribut gPCFileSysPath

4.5.3 Construction de la détection

4.5.3.1 Détection avec les ID d’événements 5136 et 4624
index=main ((EventCode=5136 AND LDAP_Display_Name=gpcFileSysPath)  OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM")) 
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1)) 
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))  
| join type=outer Logon_ID    
        [ search (EventCode=5136) OR (EventCode=4624)     
        | stats count by Logon_ID, Account_Name, Workstation_Name 
        | table Account_Name,Logon_ID,  Workstation_Name ]  
| table _time, EventCode, Mod_Account,  Workstation_Name , Class, DN, Logon_ID, Type, LDAP_Display_Name, Value
| where  len(Class)>0

Image020 1

Figure 20 – Détection finale de gPCFileSysPath (1)

Image021 2

Figure 21 – Détection finale de gPCFileSysPath (2)

4.6 NT-Security-Descriptor

4.6.1 Contexte

Le NTSecurityDescriptor stocke les données relatives à un objet, telles que la propriété et les autorisations, dans un attribut « Format de la chaîne du descripteur de sécurité. »

4.6.2 Activation de l’audit

Pour ces détections particulières, nous devrons activer l’audit à deux (2) endroits. Tout d’abord, vous devrez activer l’audit à partir de certsrvqui peut être ouvert via le gestionnaire de serveur sur votre contrôleur de domaine.

Image022

Chiffre 22 – Activation de l’audit de certsrv

Pour l’audit de l’accès aux objets, nous devons également naviguer vers nos modèles dans ADSI edit et activer l’audit pour le modèle de certificat dont nous souhaitons suivre les événements – dans ce cas, le modèle de certificat Utilisateur modèle.

Image023

Chiffre 23 – Activation de l’audit des objets

4.6.3 Modification de l’attribut (Attaque)

Pour cette attaque, nous utiliserons un modèle de certificat vulnérable à une attaque ESC4 en utilisant l’outil Certipy pour trouver et localiser tous les modèles de certificats disponibles sur le domaine. Pour plus d’informations sur les vulnérabilités et les exploits liés aux modèles de certificats, veuillez consulter le document Certipy GitHub.

certipy find -u [email protected] -p <yourpassword> -scheme ldap -dc-ip 10.0.2.4

Image024

Chiffre 24 – Recherche de modèles AD CS

Dans ce cas, nous pouvons rapidement identifier que le Utilisateur est vulnérable à l’ESC4.

Remarque : En règle générale, dans la nature, nous recherchons le groupe qui dispose des « autorisations dangereuses », à savoir les utilisateurs du domaine, les utilisateurs authentifiés ou les ordinateurs du domaine. Dans le cas présent, le seul groupe disposant des autorisations nécessaires pour rétrograder le modèle vulnérable à l’ESC4 est le groupe Domain Admins, ce qui est suffisant pour exécuter l’attaque visant à modifier l’attribut.

Image025

Chiffre 25 – Modèle vulnérable ESC4

Nous rétrogradons ensuite le modèle ESC4 pour qu’il soit vulnérable à ESC1 et sauvegardons l’ancienne configuration du modèle dans le dossier User.json.

certipy template -username [email protected] -p <yourpassword> -template ‘User’ -scheme ldap -save-old -dc-ip 10.0.2.4

Image026

Chiffre 26 – Déclassement de ESC4 en ESC1

Ensuite, nous demandons un certificat en utilisant le modèle ESC1. Dans ce cas, l’utilisateur demandeur est sous.chefun utilisateur non privilégié, qui demande le certificat au nom d’un compte d’administrateur de domaine, head.chef. Ceci est spécifié à l’aide de l’option UPN drapeau.

certipy req -username [email protected] -p <> -upn head.chef.breakfastland.local -template ‘User’ -ca BREAKFASTLAND-BREAKFAST-DC-01-CA -target BREAKFAST-DC-01.BREAKFASTLAND.LOCAL -dc-ip 10.0.2.4

Image027

Chiffre 27 – Demande de certificat

Et maintenant, nous restaurons le certificat, toujours en utilisant Certificat. Comme vous pouvez le voir dans la sortie, il modifie le fichier ntSecurityDescriptor . Selon le article de Rapid7 qui a inspiré cette section, c’est la spécification de l’UPN qui déclenche la procédure d’appel d’offres. ntSecurityDescriptor à mettre à jour.

certipy template -username [email protected] -p <yourpassword> -template -User -configuration User.json -dc-ip 10.0.2.4

Image028

Chiffre 28 – Restaurer le certificat/modifier l’attribut ntSecurityDescriptor

4.6.4 Construction des détections

4.6.4.1 Détection à l’aide de l’ID d’événement 4898
index=main EventCode=4898
| table time, EventCode, host, DomainController, Security_Descriptor, Message

Image029 1

Chiffre 29 – Détection du changement de ntSecurityDescriptor via l’ID d’événement 4898 (1)

Image030 2

Figure 30 – Détection du changement de ntSecurityDescriptor via l’ID d’événement 4898 (2)

4.6.4.2 Détection à l’aide des ID d’événements 5136, 4662 et 4624
index=main ((EventCode=5136 AND LDAP_Display_Name=ntSecurityDescriptor)  OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM") OR (EventCode=4662 AND Access_Mask=0x20))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1)) 
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))  
| join type=outer Logon_ID    
        [ search (EventCode=5136) OR (EventCode=4624)     
        | stats count by Logon_ID, Account_Name, Source_Network_Address 
        | table Account_Name,Logon_ID, Source_Network_Address ]  
| join type=outer Logon_ID
    [ search index=main Account_Name!=*$  EventCode=4662 Access_Mask = 0x20
    | eval Props=Properties
    | eval AccessMask=Access_Mask
    | eval ObjectType=Object_Type
    | eval ObjectName=Object_Name
    | rex field=Message "(?<Object_Properties>(?ms)(?<=)Properties:(.*?)(?=Additional\s+))"
    |table Account_Name,Logon_ID,Props,AccessMask,ObjectType, ObjectName, Object_Properties] 
| table time, ModAccount, Source_Network_Address , Class, DN, Logon_ID, Type, LDAP_Display_Name, Value, AccessMask, Props, Object_Properties
| where  len(Class)>0
| stats values by time, Value, LogonID

Image031 1

Figure 31 – Détection avec les ID d’événements 5136, 4624 et 4662 (1)

Image032 2

Chiffre 32 – Détection avec les ID d’événements 5136, 4624 et 4662 (2)

4.6.4.3 Détection à l’aide des ID d’événements 5136, 4662 et 4624 – ICP

Dans ce cas, des modifications d’attributs supplémentaires sont initiées lors de l’exécution de cette attaque. Pour les prendre en compte, vous pouvez également créer une détection qui ajoute les attributs supplémentaires de l’infrastructure à clé publique (PKI) à la détection.

index=main ((EventCode=5136 AND (LDAP_Display_Name="*pki*" OR LDAP_Display_Name=ntSecurityDescriptor))  OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM") OR (EventCode=4662 AND Access_Mask=0x20))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1)) 
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))  
| join type=outer Logon_ID    
        [ search (EventCode=5136) OR (EventCode=4624)     
        | stats count by Logon_ID, Account_Name, Source_Network_Address 
        | table Account_Name,Logon_ID, Source_Network_Address ]  
| join type=outer Logon_ID
    [ search index=main Account_Name!=*$  EventCode=4662 Access_Mask = 0x20
    | eval Props=Properties
    | eval AccessMask=Access_Mask
    | eval ObjectType=Object_Type
    | eval ObjectName=Object_Name
    | rex field=Message "(?<Object_Properties>(?ms)(?<=)Properties:(.*?)(?=Additional\s+))"
    |table Account_Name,Logon_ID,Props,AccessMask,ObjectType, ObjectName, Object_Properties] 
| table time, ModAccount, Source_Network_Address , Class, DN, Logon_ID, Type, LDAP_Display_Name, Value, AccessMask, Props, Object_Properties
| where  len(Class)>0
| stats values by time, LDAPDisplay_Name, Value, Logon_ID

Image033 1

Chiffre 33 – Détections de changements d’objets supplémentaires (objets ICP) (1)

Image034 2

Chiffre 34 – Détections de changements d’objets supplémentaires (objets ICP) (2)

4.7 Certificat CA

4.7.1 Contexte

Le cACertificat L’attribut cACertificate stocke les certificats qui ont été enregistrés auprès d’autorités de certification (CA) de confiance.

4.7.2 Activation de l’audit/mauvaise configuration du domaine

Pour l’attaque suivante, nous suivrons l’article de blog réalisé par décodeur (@décodeur_it).

Note : Nous ne suivrons pas la séquence complète de l’attaque, car la modification de l’attribut est effectuée dans les premières étapes du post. Pour simuler le patch complet de l’attaque, veuillez suivre la marche à suivre complète ici.

Pour préparer notre attaque, nous devrons d’abord donner à un utilisateur standard « GenericAll » les privilèges sur le fichier NTAuthCertificates . Cette opération peut être effectuée via ADSI edit ou via PowerShell.

Dans ce cas, nous utilisons imposter.oatmeal comme notre compte mal configuré.

Image035

Chiffre 35 – Mauvaise configuration de l’objet

Ensuite, nous devrons construire l’entrée SACL pour l’objet NTAuthCertificates afin de recevoir les données d’enregistrement dans Splunk.

Image036

Chiffre 36 – Mise en place du SACL

Une fois cette étape franchie, nous pouvons lancer notre attaque pour modifier l’attribut.

4.7.3 Modification de l’attribut (Attaque)

Pour commencer, nous allons créer une fausse autorité de certification auto-signée.

Image037

Chiffre 37 – CA Création (1)

Comme indiqué dans le blog du décodeur, vous pouvez laisser tous les champs vides, à l’exception de « Common Name ».

Image038

Chiffre 38 -Création de la CCA (2)

Une fois la fausse autorité de certification créée, nous pouvons maintenant déplacer le fichier faux.crt créé sur un hôte Windows connecté à un domaine et utiliser le fichier binaire natif certutil pour mettre à jour le cACertificat avec la valeur de la clé publique supplémentaire.

Il est important de noter ici que nous sommes connectés à l’hôte Windows en tant que compte imposter.oatmeal, qui est le compte que nous avons « mal configuré » pour avoir des autorisations spéciales sur l’objet que nous modifions.

Image039

Chiffre 39 – Pousser la fausse autorité de certification vers le domaine

Et maintenant, si nous jetons un coup d’œil à notre cACertificat nous pouvons voir qu’il a été modifié avec la valeur du faux certificat.

Image040

Chiffre 40 – Attribut Post Modification

4.7.4 Construction des détections

4.7.4.1 Détection avec les ID d’événements 5136, 4662 et 4624
index=main ((EventCode=5136 AND LDAP_Display_Name=cACertificate)  OR (EventCode=4624 AND Account_Name!="*$" AND Account_Name!="ANONYMOUS LOGON" AND Account_Name!="SYSTEM") OR (EventCode=4662 AND Access_Mask=0x20))
| eval Logon_ID=if(EventCode==4624,mvindex(Logon_ID,-1), mvindex(Logon_ID,-1)) 
| eval Mod_Account=if(EventCode==4624,mvindex(Account_Name,-1), mvindex(Account_Name,-1))  
| eval Changed_Value=if(EventCode==5136,mvindex(Value,-1), mvindex(Value,-1))  
| join type=outer Logon_ID    
        [ search (EventCode=5136) OR (EventCode=4624)     
        | stats count by Logon_ID, Account_Name, Source_Network_Address 
        | table Account_Name,Logon_ID, Source_Network_Address ]  
| join type=outer Logon_ID
    [ search index=main Account_Name!=*$  EventCode=4662 Access_Mask = 0x20
    | eval Props=Properties
    | eval AccessMask=Access_Mask
    | eval ObjectType=Object_Type
    | eval ObjectName=Object_Name
    | rex field=Message "(?<Object_Properties>(?ms)(?<=)Properties:(.*?)(?=Additional\s+))"
    |table Account_Name,Logon_ID,Props,AccessMask,ObjectType, ObjectName, Object_Properties] 
| table _time, Mod_Account, Source_Network_Address , Class, DN, Logon_ID, Type, LDAP_Display_Name, Changed_Value, AccessMask, Props, Object_Properties
| where  len(Class)>0
| stats values by _time, Changed_Value

Image041 1

Figure 41 – Détection avec les ID d’événements 5136, 4662 et 4624 (1)

Image042 2

Chiffre 42 – Détection avec les ID d’événements 5136, 4662 et 4624 (2)

4.8 Primary-Group-ID

4.8.1 Contexte

Le primaryGroupID contient l’identifiant du groupe primaire (RID) auquel appartient l’utilisateur ou l’objet informatique.

4.8.2 Modification de l’attribut (Attaque)

Les primaryGroupID est facile à modifier via l’interface graphique d’ADUC.

  • Naviguez d’abord vers ADUC
  • Ouvrez la fenêtre des propriétés de l’objet ordinateur/utilisateur que vous modifiez
  • Naviguez jusqu’à l’onglet « Membre de
  • Cliquez sur « Ajouter »
    • Sélectionnez le nom du groupe dont vous souhaitez faire le groupe principal.
    • Cliquez sur ok, puis sur appliquer.
  • Sélectionnez le groupe nouvellement ajouté dans la case « Membre de ».
    • Cliquez sur le bouton situé sous la case « Définir le groupe principal ».
    • Cliquez sur Appliquer

Image043

Chiffre 43 – Changement de primaryGroupID de COFFEEPOT-PC

4.8.3 Construction des détections

Pour les détections suivantes, nous nous appuyons sur les ID d’événement 4738 et 4742 pour les objets utilisateur et ordinateur respectivement. Veillez à configurer votre SACL sur l’objet que vous essayez d’auditer pour vous assurer que les journaux seront générés et envoyés à votre SIEM.

4.8.3.1 Détection à l’aide de l’ID d’événement 4738 et de l’ID d’événement 4624
index=main AND (EventCode=4738 AND Primary_Group_ID!="-") OR EventCode=4624
| eval logon_id=if(EventCode=4624,mvindex(Logon_ID,1),mvindex(Logon_ID,0))
| eventstats values(EventCode) values(Source_Network_Address) by logon_id
| rename values(*) as *
| eval account_name=mvindex(Account_Name,1)
| sort _time
| where isnotnull(Primary_Group_ID)
| table _time, account_name, logon_id, Source_Network_Address, Primary_Group_ID
| stats values by logon_id, account_name

Image044

Chiffre 44 – Détection avec ID d’événement 4738 et 4624

4.8.3.2 Détection à l’aide de l’ID d’événement 4742 et de l’ID d’événement 4624
index=main AND (EventCode=4742 AND Primary_Group_ID!="-") OR EventCode=4624
| eval logon_id=if(EventCode=4624,mvindex(Logon_ID,1),mvindex(Logon_ID,0))
| eventstats values(EventCode) values(Source_Network_Address) by logon_id
| rename values(*) as *
| eval account_name=mvindex(Account_Name,1)
| sort _time
| where isnotnull(Primary_Group_ID)
| table _time, account_name, logon_id, Source_Network_Address, Primary_Group_ID
| stats values by logon_id, account_name

Image045

Chiffre 45 – Détection avec ID d’événement 4742 et 4624

4.8.3.3 Détections de primaryGroupID avec filtrage RID

Il est important de noter que les requêtes précédentes ne filtrent que les Primary Group ID qui ne sont pas égaux à « – » (null). Cependant, pour les organisations qui peuvent rencontrer des volumes élevés d’événements pour ces EventID, vous pouvez ajuster votre filtrage pour rechercher ou exclure certains groupes RID.

Par exemple, vous pourriez modifier la détection ci-dessous de manière à ce que seuls les comptes d’utilisateurs ayant leur primaryGroupID modifié en 512 (Domain Admins) repris par la requête :

index=main AND (EventCode=4738 AND Primary_Group_ID="512") OR EventCode=4624
| eval logon_id=if(EventCode=4624,mvindex(Logon_ID,1),mvindex(Logon_ID,0))
| eventstats values(EventCode) values(Source_Network_Address) by logon_id
| rename values(*) as *
| eval account_name=mvindex(Account_Name,1)
| sort _time
| where isnotnull(Primary_Group_ID)
| table _time, account_name, logon_id, Source_Network_Address, Primary_Group_ID
| stats values by logon_id, account_name

5 Conclusion

Nous espérons que cette série d’articles de blog permettra aux professionnels et aux organisations non seulement de prendre conscience de l’étendue de la surface d’attaque d’Active Directory (AD), mais aussi de savoir comment détecter les attaques courantes dont abusent les testeurs d’intrusion, les membres de l’équipe rouge et les acteurs de la menace.

Du point de vue de la sécurité, nous espérons également que l’un des principaux enseignements de ces articles est l’importance d’auditer fréquemment les autorisations de lecture ou d’écriture de ces attributs. Des outils tels que Bloodhound, PingCastleet PurpleKnight peut aider à identifier et à vérifier un grand nombre de ces problèmes faciles à résoudre.

Un autre point essentiel à retenir lorsque vous essayez de mettre en œuvre les détections fournies dans ces trois (3) articles de blog dans votre propre environnement SIEM est que toutes les détections ont été élaborées dans un environnement de laboratoire. Un environnement de production réel nécessitera des réglages supplémentaires pour éliminer les faux positifs.

Bien que la meilleure pratique et la préférence soient d’auditer tous les attributs, nous reconnaissons, comprenons et opérons avec les contraintes des coûts de licence SIEM. Nous avons voulu mettre en évidence et donner la priorité à certaines des attaques/abus les plus importants et n’avons donc pas couvert tous les attributs. Nous reconnaissons que nous n’avons pas utilisé de « renseignements » pour déterminer la priorité des attributs dans les différents articles. Nous avons plutôt commencé par les attributs les plus « communs » (en commençant par le tableau des abus de DACL de Hacker Recipes) que les équipes rouges et les testeurs de pénétration peuvent abuser, et nous avons terminé par les attributs les moins communs ou « oubliés ».

Comme les détections n’ont pas été construites pour toutes les attaques/abus possibles, les modèles de détection contenus dans ces articles peuvent être utilisés pour développer les cas d’utilisation décrits au fur et à mesure que de nouvelles attaques/techniques sont publiées, ou pour couvrir des objets que nous n’avons pas abordés.

Enfin, un grand merci à tous ceux qui ont participé à l’analyse, à la révision et aux suggestions afin de rendre cette série de blogs aussi bonne que possible :

Charlie Bromberg (@_nwodtuhs)

Jonathan Johnson (@jsecurity101)

Jim Sykora (@jimsycurity)

Kevin Clark (@GuhnooPlusLinux)

6 Références :

https://www.thehacker.recipes/ad/movement/dacl

https://stackoverflow.com/questions/73107061/convert-datetime-in-a-command

https://www.youtube.com/watch?v=ExO535CITXs

https://specterops.io/wp-content/uploads/sites/3/2022/06/an_ace_up_the_sleeve.pdf

Événements Windows :

https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4662

https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4624

https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-5145

https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4742

https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4738

AdminSDHolder :

https://viperone.gitbook.io/pentest-everything/everything/everything-active-directory/persistence/adminsdholder

msDS-SupportedEncryptionTypes :

https://learn.microsoft.com/en-us/windows/win32/adschema/a-msds-supportedencryptiontypes

https://techcommunity.microsoft.com/t5/core-infrastructure-and-security/decrypting-the-selection-of-supported-kerberos-encryption-types/ba-p/1628797

msds-RevealOnDemandGroup :

https://eladshamir.com/2023/01/25/RODCs.html

gPCMachineExtensionNames :

https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-gpod/896f59a5-5b72-4fb5-b1d4-8d007fdd6cb3

https://www.trustedsec.com/blog/weaponizing-group-policy-objects-access/

https://community.spiceworks.com/topic/345202-tips-and-tricks-for-total-control-the-inner-workings-of-group-policy

https://labs.withsecure.com/tools/sharpgpoabuse

https://sdmsoftware.com/security-related/sending-gpos-down-the-wrong-track-redirecting-the-gpt/

gPC-File-Sys-Path :

https://specterops.io/wp-content/uploads/sites/3/2022/06/an_ace_up_the_sleeve.pdf

https://learn.microsoft.com/en-us/windows/win32/adschema/a-gpcfilesyspath

NTSecurityDescriptor :

https://learn.microsoft.com/en-us/windows/win32/adschema/a-ntsecuritydescriptor

https://github.com/ly4k/Certipy

https://learn.microsoft.com/en-us/windows/win32/secauthz/security-descriptor-string-format?redirectedfrom=MSDN

https://www.rapid7.com/blog/post/2023/06/02/metasploit-weekly-wrap-up-12/

cACertificat :

https://decoder.cloud/2023/09/05/from-ntauthcertificates-to-silver-certificate/

https://learn.microsoft.com/en-us/windows/win32/adschema/a-cacertificate

https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-wcce/f1004c63-8508-43b5-9b0b-ee7880183745

https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/certutil

primaryGroupID :

https://learn.microsoft.com/en-us/windows/win32/adschema/a-primarygroupid

https://www.qomplx.com/blog/primary-group-id-attacks/

https://dovestones.com/changing-primary-group-primarygroupid/

https://www.semperis.com/blog/how-attackers-can-use-primary-group-membership-for-defense-evasion/

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *