ADGPO-013: Scripts in GPOs Analysis

Plataforma
Active Directory
Categoría
AD Group Policy
Severidad
High
Pilar de Zero Trust
Governance (peso 1)
Fixtures de referencia
3
Cobertura de ramas
Observada: los fixtures prueban los veredictos que ejercitan
Procedencia
baseline

Qué comprueba

The check uses Get-GPO -All to enumerate every Group Policy Object in the domain, then for each GPO calls Get-GPOReport -ReportType Xml and parses the resulting GroupPolicyObject document. It walks four script extension nodes: Computer/ExtensionData/Extension/Script with type "Startup", the same node with type "Shutdown", User/ExtensionData/Extension/Script with type "Logon", and the same node with type "Logoff". For each script entry it captures the Command (which may be a relative filename, a fully qualified UNC path, an http or https URL, or a LOLBin invocation), the Parameters string, the RunOrder, and the gPCFileSysPath plus relative path under \\domain\SYSVOL\domain\Policies\{GUID}\Machine\Scripts\Startup or \Shutdown or \User\Scripts\Logon or \Logoff. The script body is then read from SYSVOL and matched against a set of indicators: cleartext password assignments, ConvertTo-SecureString -AsPlainText, net user /add, schtasks /create, certutil -urlcache, bitsadmin /transfer, powershell -enc, IEX/Invoke-Expression of Net.WebClient.DownloadString, references to non-SYSVOL UNC paths, references to http or https URLs, and references to filesystem locations writeable by Authenticated Users. File ACLs on the script artifact in SYSVOL are read with Get-Acl and flagged if any non-Tier-0 principal has Modify or Write rights.

Por qué importa

Every GPO script is a pre-authorized code execution channel that runs without user interaction and without a UAC prompt. Startup and Shutdown scripts run as SYSTEM, which means they bypass AppLocker default rules, can write to HKLM, can install services, and can dump LSASS. Logon and Logoff scripts run in the user context but execute on every machine the user touches, which gives an attacker domain-wide lateral movement for the cost of editing one file in SYSVOL. The blast radius is defined by where the GPO is linked: a script in a GPO linked to the Domain Controllers OU executes on every DC, a script in a GPO linked to the Domain Root executes on every domain-joined machine, and a script in a GPO linked to a server OU executes on every server in that OU. Because SYSVOL is world-readable by Authenticated Users, the script contents are also a credential disclosure surface: hardcoded service-account passwords, API keys, KeePass master strings, and Bearer tokens placed in startup scripts have repeatedly been found by attackers running Get-GPPPassword-style sweeps and by tools like Snaffler that crawl SYSVOL for high-signal regex. Finally, scripts that reference http or https URLs or non-SYSVOL UNC paths introduce a supply-chain dependency: anyone who controls the remote location, including an attacker who poisons DNS, ARP, LLMNR, or NBNS, can substitute the script body and obtain code execution on every target.

Ruta de ataque

1. Reconnaissance: the attacker, holding any domain-authenticated credential, mounts \\domain\SYSVOL\domain\Policies and recursively reads every Scripts\Startup, Scripts\Shutdown, User\Scripts\Logon, and User\Scripts\Logoff folder. Tools like Snaffler, ManySnaffler, and PowerView Get-DomainGPO -ResolveLinks identify which scripts execute where and surface plaintext secrets in the script bodies. 2. Credential harvesting: scripts frequently contain hardcoded passwords for service accounts mapping drives, joining domains, installing software with -Credential, or running scheduled tasks with stored credentials. These flow directly into a credential database with no need to coerce authentication or relay a hash. 3. GPO write rights: the attacker pivots from disclosed credentials, from membership in Group Policy Creator Owners, or from a delegated Edit settings permission to write access on a target GPO. Get-GPPermission and BloodHound (GPOLocalGroup edges) identify the target. 4. Script substitution: the attacker overwrites an existing startup script inside the GPO's SYSVOL Scripts\Startup folder with a payload of their choice, or adds a new entry to gpscripts.ini and drops a new file. Because the script reference already exists in the GPO, no GPO modification event fires on the AD object itself; only an SMB write to SYSVOL is generated. SharpGPOAbuse --AddComputerScript automates this. 5. Path-substitution variant: if the existing script Command references an http URL or a non-SYSVOL UNC path, the attacker poisons that resource instead of editing SYSVOL. Responder, mitm6, and DNS cache poisoning all enable this without any AD write right. 6. Replication and execution: SYSVOL replicates the modified script through DFSR (or FRS on legacy domains) to every domain controller. At the next Group Policy refresh, or at the next reboot for Startup, or at the next interactive logon for Logon, the script executes. On a GPO linked to the Domain Controllers OU this is code execution as SYSTEM on every DC. 7. Persistence and cleanup: the attacker reverts the script to the original content after the payload runs, leaving the GPO version number bumped twice but the visible Command string unchanged. The SYSVOL file modification timestamp is the only durable artifact, and it is rarely audited.

Cómo lo evalúa Guerrilla

Guerrilla imports the GroupPolicy and ActiveDirectory modules, calls Get-GPO -All -Domain $env:USERDNSDOMAIN, and for each GPO calls Get-GPOReport -Guid $gpo.Id -ReportType Xml. The XML is cast to [xml] and the script nodes are extracted from $report.GPO.Computer.ExtensionData.Extension.Script (filtered to Type Startup and Shutdown) and $report.GPO.User.ExtensionData.Extension.Script (filtered to Type Logon and Logoff). For each script entry, the gPCFileSysPath from the GPO is combined with the script relative path to resolve the full SYSVOL location, and Get-Content reads the script body. Indicator matching is performed with a regex pack that covers cleartext credential keywords (password\s*=, pass\s*:, ConvertTo-SecureString.*AsPlainText, -Credential.*new-object.*PSCredential), download cradles (DownloadString, DownloadFile, Invoke-WebRequest, Invoke-RestMethod, certutil.*urlcache, bitsadmin.*transfer, curl, wget), encoded payloads (powershell.*-enc, -EncodedCommand, FromBase64String), LOLBin executions (regsvr32, rundll32, mshta, wmic, cscript, wscript invoked against remote or temp paths), and unsafe path references (http://, https://, \\\\[^\\]+\\ where the host is not the local domain, %TEMP%, %APPDATA%, C:\Users\Public). The check then runs Get-Acl on the script file in SYSVOL and flags any ACE granting Modify, Write, or FullControl to a principal outside the Tier-0 boundary (Domain Admins, Enterprise Admins, SYSTEM, the GPO owner principal, and the SYSVOL share owner). Output rows include GpoName, GpoId, ScriptType (Startup/Shutdown/Logon/Logoff), Command, Parameters, FullPath, IndicatorsFound (string array), AclRisk (bool), LinkedScopes, and a RiskScore field that weights Startup and Shutdown on DC-linked GPOs as Critical, anything with hardcoded credentials as Critical, download cradles as High, and unsafe path references as High.

Valor recomendado

All GPO scripts reviewed, signed where possible, and free of hardcoded credentials or unsafe operations

Remediación

Enumerate all scripts configured in GPOs (Startup, Shutdown, Logon, Logoff) from the Scripts section of GPO reports. Review script content for hardcoded credentials, LOLBins usage, external resource references, and unsafe operations. Implement script signing where supported. Ensure script file permissions restrict modification to authorized administrators only.

Veredictos probados con fixtures

Cada veredicto de esta tabla está probado por un fixture de referencia en la suite de pruebas que valida el módulo. La tabla se deriva de la última ejecución en verde; no puede editarse a mano.

Escenarios de veredicto de ADGPO-013
EscenarioVeredicto esperado
cleanPASS
known-badWARN
throttledNot Assessed

Mapeos a marcos de referencia

NIST SP 800-53
CM-6, SI-7, CM-5
MITRE ATT&CK
T1059, T1484.001