Full Report
The Second Most Important Data Source You're Probably Not CapturingIn Part 2, we enabled process creation logging with command lines. That's a big step forward. But here's the thing about PowerShell:…
Analysis Summary
# Best Practices: PowerShell and Script Logging
## Overview
This guidance addresses the visibility gap between process creation (knowing a script ran) and script execution (knowing what the script actually did). By capturing native PowerShell logs, organizations can de-obfuscate malicious commands in real-time and provide forensic evidence that traditional process monitoring (Event ID 4688) misses.
## Key Recommendations
### Immediate Actions
1. **Enable Module Logging (Event ID 4103):** Captures pipeline execution details as PowerShell executes.
2. **Enable Script Block Logging (Event ID 4104):** Captures the full content of code blocks as they are processed. This is the "Gold Standard" for seeing through obfuscation.
3. **Enable Transcription Logging:** Records every input and output in a PowerShell session to a text file for a permanent audit trail.
4. **Configure Log Size:** Increase the "Microsoft-Windows-PowerShell/Operational" log size to at least **1GB** to prevent rapid roll-over.
### Short-term Improvements (1-3 months)
1. **Centralize Log Collection:** Ship Event IDs 4103 and 4104 to a SIEM or central log aggregator.
2. **Implement Keyword Alerting:** Set up alerts for high-risk strings like `Invoke-Expression`, `IEX`, `Mimikatz`, and `-enc`.
3. **Secure Transcription Stores:** If using Transcription, ensure the destination folder is "Write-Only" for users to prevent attackers from deleting their own tracks.
### Long-term Strategy (3+ months)
1. **Advanced Correlation:** Integrate PowerShell events with Process Creation (4688) and Network Connection logs (Sysmon) to map the full attack lifecycle.
2. **PowerShell Constrained Language Mode (CLM):** Move toward restricting PowerShell functionality for non-administrative users to reduce the attack surface.
3. **AMSI Integration:** Ensure Anti-Malware Scan Interface (AMSI) is active alongside logging to block known-bad scripts before execution.
## Implementation Guidance
### For Small Organizations
- Focus on **Script Block Logging (4104)** specifically. It provides the highest security value with the least configuration overhead.
- Store logs locally with a large buffer (2GB) if a SIEM is not available.
### For Medium Organizations
- Use **Group Policy Objects (GPO)** to enforce logging across all workstations and servers.
- Enable **Transcription** for sensitive administrative servers (Jump boxes, Domain Controllers).
### For Large Enterprises
- Use **Selective Module Logging** to reduce noise from known-good automated scripts.
- Implement automated parsing of 4104 events to identify "Entropy" or signs of heavy obfuscation that bypass signature-based tools.
## Configuration Examples
### Group Policy Path
`Computer Configuration > Policies > Administrative Templates > Windows Components > Windows PowerShell`
### Specific Settings
- **Turn on PowerShell Script Block Logging:** Enabled (Check "Log Script Block Execution Start/Stop events" for deep forensics).
- **Turn on PowerShell Module Logging:** Enabled (Add `*` to Module Names to capture everything).
- **Turn on PowerShell Transcription:** Enabled (Specify a secure UNC path).
## Compliance Alignment
- **NIST SP 800-53:** AU-2 (Event Logging) and AU-12 (Audit Generation).
- **CIS Controls:** Control 8 (Audit Log Management) and Control 10 (Malware Defenses).
- **MITRE ATT&CK:** Directly addresses "Command and Scripting Interpreter: PowerShell" (T1059.001).
## Common Pitfalls to Avoid
- **Logging Only powershell.exe:** Attackers can run PowerShell code via other hosts (like `powershell_ise.exe` or custom .NET apps). Native logging captures the engine activity regardless of the host.
- **Ignoring Obfuscation:** Don't rely on command-line triggers. Attackers use Base64 and character replacement which Script Block Logging automatically "unwraps."
- **Small Log Buffers:** PowerShell logs are verbose. Default sizes (usually 15MB-20MB) can overwrite themselves in minutes during a heavy script run.
- **Relying Solely on AMSI:** AMSI can be bypassed. Logging provides the "black box" recording of what happened even if the bypass was successful.
## Resources
- **Microsoft Documentation:** `docs.microsoft[.]com/en-us/powershell/module/microsoft.powershell.core/about/about_logging`
- **NSA Guidance:** Hardware-and-Firmware-Security/Embracing-Micro-Segmentation-and-Restricting-PowerShell[.]pdf
- **MITRE ATT&CK Framework:** `attack.mitre[.]org/techniques/T1059/001/`