ADSCRIPT-007: World-Writable Script Permissions
- Platform
- Active Directory
- Category
- AD Logon Scripts & Network Shares
- Severity
- Critical
- Zero Trust pillar
- Applications & Workloads (weight 2)
- Golden fixtures
- 3
- Branch coverage
- Observed: fixtures prove the verdicts they exercise
- Provenance
- baseline
What it checks
For every file under \\<domain>\NETLOGON and \\<domain>\SYSVOL\<domain>\scripts (and per-GPO scripts folders under SYSVOL\<domain>\Policies\{GUID}\Machine\Scripts and \User\Scripts), the check reads the NTFS DACL via Get-Acl and parses every Access Control Entry. It evaluates FileSystemRights flags that permit modification: WriteData, AppendData, WriteAttributes, WriteExtendedAttributes, Write, Modify, FullControl, ChangePermissions, TakeOwnership, and Delete. Trustees flagged as risky include Everyone (S-1-1-0), Authenticated Users (S-1-5-11), Domain Users (S-1-5-21-<domain>-513), Users (BUILTIN), INTERACTIVE (S-1-5-4), NETWORK (S-1-5-2), and any custom group whose membership is not Tier-0. The expected baseline DACL on a domain-replicated script file grants Read and Execute (ReadAndExecute, ReadData, ReadAttributes, ReadExtendedAttributes, ReadPermissions, Synchronize) to Authenticated Users and Server Operators, and FullControl to SYSTEM, Domain Admins, Enterprise Admins, Creator Owner, and Administrators. Anything that exceeds that surface on a per-file basis is reported even when the share-level permission and parent folder ACL are correct, because NTFS evaluates the effective permission on the file itself.
Why it matters
NETLOGON and SYSVOL are replicated by DFS-R to every domain controller and read by every domain-joined host. A script in those shares is, by design, executed under the security context of whatever principal runs it: the logged-on user for user logon scripts, SYSTEM for computer startup scripts, and frequently a service account or scheduled task identity for legacy login automation. If any non-Tier-0 principal can rewrite the file, that principal can append arbitrary code that will run on the next execution under a far more privileged context. The blast radius is the union of every host that runs the script. For a global logon script, that is the entire workstation fleet. For a computer startup script linked to the Domain Controllers OU, that is every DC, which means immediate Tier-0 compromise and trivial DCSync. The technique is silent: DFS-R will replicate the modified script across the forest within minutes, no security event is generated for an authorized NTFS write, and the malicious payload looks like a legitimate scheduled administrative task. Ransomware crews and red teams have used this primitive for years because it converts any domain user foothold into mass code execution without touching LSASS, kerberoasting, or any noisy primitive that EDR alerts on.
Attack path
1. Reconnaissance: from any domain-joined host, the attacker mounts \\<domain>\NETLOGON and \\<domain>\SYSVOL and enumerates files. PowerView (Get-DomainShare, Find-InterestingDomainShareFile), or a simple Get-ChildItem -Recurse, surfaces every script. 2. ACL audit: for each script the attacker runs Get-Acl <file> | Format-List, or icacls <file>, and looks for ACEs granting Write, Modify, or FullControl to Authenticated Users, Domain Users, Everyone, or any group the attacker is in. SharpHound with the FileACLs collection method automates this at scale. 3. Target selection: the attacker prefers files referenced by the scriptPath attribute on privileged user accounts (Get-ADUser -Filter "scriptPath -like '*'" -Properties scriptPath), or scripts linked to GPOs that target the Domain Controllers OU. A writable script that runs as SYSTEM on a DC is the highest-value primitive. 4. Weaponization: the attacker appends a payload to the existing script. For a .bat / .cmd, that is a single line that downloads and runs a beacon or adds a backdoor account. For a .ps1, the attacker appends a base64 -EncodedCommand that executes in the background and preserves the script's normal output so users see nothing unusual. For a referenced .exe, the attacker overwrites the binary with a wrapper that runs the payload then chains to the original. 5. Replication: DFS-R propagates the modified file to every DC within the default 60 second replication interval. From that moment forward, every logon, every GPO refresh that runs the script, and every scheduled task that invokes it executes the attacker payload under the calling principal. 6. Privilege escalation: when a Domain Admin next logs on to any workstation, the user logon script runs in the DA context and the attacker gets Tier-0. When a startup script linked to the Domain Controllers OU runs, the attacker gets SYSTEM on a DC. The attacker now runs DCSync or extracts the krbtgt hash and forges Golden Tickets. 7. Cleanup: the attacker reverts the script file to its original content and timestamps using touch-style metadata rewrites. The only forensic trace is the DFS-R event log entry showing a replicated file change, which is almost never reviewed.
How Guerrilla assesses it
Guerrilla resolves the domain root via Get-ADDomain, builds the UNC paths \\<domain>\NETLOGON and \\<domain>\SYSVOL\<domain>\scripts, and recursively enumerates files with Get-ChildItem -Recurse -File -Force (the -Force flag includes hidden and system files that attackers commonly use). For each file the check calls Get-Acl and walks Access entries, evaluating FileSystemRights against a write-mask (WriteData, AppendData, WriteAttributes, WriteExtendedAttributes, Write, Modify, FullControl, ChangePermissions, TakeOwnership, Delete). IdentityReference is resolved through Translate([System.Security.Principal.SecurityIdentifier]) so well-known SIDs (S-1-1-0 Everyone, S-1-5-11 Authenticated Users, S-1-5-7 Anonymous Logon) surface even when the trustee cannot be translated to a friendly name. The check also walks per-GPO Machine\Scripts and User\Scripts directories under SYSVOL\<domain>\Policies because legacy script delegation often grants Edit Settings on the GPO container which translates to file write under SYSVOL. Findings are emitted with the full path, the trustee, the rights granted, AccessControlType (Allow vs Deny), whether the ACE is inherited, and the file extension so triage can prioritize executables and interpreted scripts over inert text files.
Recommended value
All script files in NETLOGON and SYSVOL writable only by Domain Admins and SYSTEM; no write access for Domain Users or Authenticated Users
Remediation
Enumerate NTFS permissions on every file in the NETLOGON share and SYSVOL scripts folders. Identify files where Domain Users, Authenticated Users, Everyone, or other broad groups have Write, Modify, or Full Control permissions. Reset permissions using icacls to grant Read and Execute to Authenticated Users and Full Control to Domain Admins and SYSTEM only.
Fixture-proven verdicts
Every verdict below is proven by a golden fixture in the module's gating test suite. This table derives from the last green run; it cannot be edited by hand.
| Scenario | Expected verdict |
|---|---|
| clean | PASS |
| known-bad | FAIL |
| throttled | Not Assessed |
Framework mappings
- NIST SP 800-53
- AC-3, AC-6, CM-5
- ANSSI
- vuln_writable_scripts
- MITRE ATT&CK
- T1222.001, T1059