PowerShell Best Practices: Reducing Attack Surface Against Advanced Payloads

Practical PowerShell hardening guidance for enterprise environments — logging, Constrained Language Mode, AMSI, and configuration strategies that reduce exposure to advanced payload delivery.

PowerShell Best Practices: Reducing Attack Surface Against Advanced Payloads

PowerShell is the most powerful and the most abused tool in the Windows ecosystem. It provides deep access to .NET, WMI, COM, and the Windows API. It executes entirely in memory. And it is installed on every modern Windows system. For defenders, the question is not whether to allow PowerShell — it is how to configure it so that legitimate administrative use continues while malicious abuse is detected and constrained.

This article goes beyond the basics. It covers the specific hardening measures, logging configurations, and operational practices that reduce your organization's exposure to advanced PowerShell-based payloads. If you have already read the PowerShell Payloads in Security Testing reference, this article builds on that foundation with implementation-level detail.

What Changed Recently

PowerShell security has improved significantly since the v2 era, but the threat landscape continues to evolve:

  • PowerShell v2 removal progress — Windows Server 2025 and Windows 11 24H2 removed the PowerShell v2 engine by default. This closes a major bypass path (v2 had no AMSI, no Script Block Logging). However, older systems and custom images may still have v2 available.
  • AMSI bypass evolution — New AMSI bypass techniques appear regularly. While Microsoft patches known bypasses, the cat-and-mouse continues. Defenders cannot rely on AMSI alone.
  • CLM bypass research — Constrained Language Mode bypasses are actively researched. AppLocker-based CLM enforcement has known limitations that WDAC-based enforcement addresses.
  • Script Block Logging improvements — PowerShell 7.x includes enhanced logging capabilities. Ensure your logging configuration covers both Windows PowerShell (5.1) and PowerShell 7.x if both are present.

The Core Hardening Controls

1. Script Block Logging

Script Block Logging records the full text of every PowerShell script block that executes, including dynamically generated code. This is the single most important PowerShell monitoring control.

Configuration:

  • Group Policy: Computer Configuration → Administrative Templates → Windows Components → Windows PowerShell → Turn on PowerShell Script Block Logging
  • Enable "Log script block invocation start / stop events" for execution timing data

What it catches:

  • Decoded payloads after base64 or other encoding is removed
  • Dynamically assembled script blocks (e.g., Invoke-Expression with concatenated strings)
  • AMSI bypass attempts (the bypass code itself is logged before AMSI is disabled)

What to watch for:

  • Event ID 4104 with suspicious content: encoded commands, AMSI bypass patterns, download cradles, credential access commands
  • High-entropy script blocks (base64 or encrypted content)
  • Script blocks from unexpected paths or with unusual sizes

2. Constrained Language Mode (CLM)

CLM restricts PowerShell to a safe subset: no .NET type access, no COM objects, no Add-Type, no arbitrary method invocation. This removes the capabilities that make PowerShell attractive for attacks.

Enforcement methods:

  • AppLocker — When AppLocker is configured with script rules, PowerShell enters CLM for scripts that are not explicitly allowed. This is the most common deployment method but has known bypass paths.
  • WDAC (Windows Defender Application Control) — WDAC-enforced CLM is more robust than AppLocker-based enforcement because WDAC policies are kernel-enforced and resistant to user-mode bypass.

Recommendation: Deploy WDAC-based CLM if possible. If using AppLocker, be aware of its limitations and supplement with other controls.

What CLM prevents:

  • .NET reflection (used for in-memory assembly loading)
  • COM object creation (used for process manipulation, registry access)
  • Type accelerators and custom type definitions
  • Invoke-Expression with complex script blocks in most scenarios

3. AMSI (Antimalware Scan Interface)

AMSI provides real-time inspection of PowerShell content before execution. The content — after any deobfuscation performed by the PowerShell engine — is sent to the registered antimalware provider.

Hardening AMSI:

  • Ensure your AV/EDR is registered as an AMSI provider
  • Monitor for AMSI bypass indicators: modifications to amsiInitFailed, patching of AmsiScanBuffer, and reflection-based attacks on the AMSI assembly
  • Keep your AV/EDR signature database current — AMSI is only as good as the scanning engine behind it

Limitations:

  • AMSI can be bypassed. Treat it as one layer, not a complete solution.
  • AMSI does not inspect content in PowerShell v2 (hence the importance of removing v2)

4. PowerShell Remoting Restrictions

PowerShell Remoting (WinRM/PSRemoting) is frequently used for lateral movement. Hardening remoting:

  • Just Enough Administration (JEA) — Restrict remote PowerShell sessions to only the cmdlets and parameters needed for specific administrative tasks
  • Constrained endpoints — Configure PowerShell session configurations that limit available commands
  • Authentication restrictions — Require Kerberos authentication, disable Basic auth, and use Credential Guard to protect credentials in transit
  • Network segmentation — Restrict WinRM ports (5985/5986) to specific administrative subnets

5. Remove PowerShell v2

PowerShell v2 is the single biggest bypass for all modern PowerShell security controls. It has no AMSI, no Script Block Logging, and no CLM support.

Verification:

Get-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2

Removal:

Disable-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2Root

Alert on v2 usage: Monitor for powershell.exe -Version 2 command-line arguments. Any use of the v2 engine in a production environment is suspicious.

Operational Best Practices

Logging Architecture

  • Forward all PowerShell logs (Event IDs 4103, 4104, 4105, 4106) to your SIEM
  • Include both Windows PowerShell (5.1) and PowerShell 7.x log sources
  • Retain logs for at least 90 days — advanced threats may not be detected immediately
  • Configure Transcription Logging to a secured file share for forensic analysis

Detection Rules

Build detection rules for these high-value indicators:

| Indicator | Event Source | Confidence | |---|---|---| | Base64-encoded commands (-EncodedCommand) | Process creation (Sysmon EID 1) | Medium — also used legitimately | | Download cradles (DownloadString, DownloadFile) | Script Block Log (EID 4104) | High | | AMSI bypass strings (amsiInitFailed) | Script Block Log (EID 4104) | High | | Reflection-based loading ([Reflection.Assembly]::Load) | Script Block Log (EID 4104) | High | | Credential access (Get-Credential, Mimikatz patterns) | Script Block Log (EID 4104) | High | | CLM bypass attempts | Script Block Log (EID 4104) | High | | PowerShell v2 invocation (-Version 2) | Process creation (Sysmon EID 1) | High |

Testing Your Configuration

After implementing hardening measures, validate them:

  1. Attempt AMSI bypass techniques in your lab — does your detection fire?
  2. Try loading a .NET assembly under CLM — does it fail?
  3. Attempt PowerShell v2 execution — is it blocked?
  4. Execute encoded commands — do they appear decoded in Script Block Logging?
  5. Test JEA constraints — can a restricted session escape its boundaries?

The Veil Framework provides a structured way to generate PowerShell-based payloads for this validation. Use the Veil-Evasion module to produce payloads that test specific detection boundaries, and follow the sandbox lab guide for safe testing practices.

Common Implementation Mistakes

  1. Enabling logging but not collecting logs — Script Block Logging is useless if the events are not forwarded to a SIEM and actively monitored.
  2. CLM without WDAC — AppLocker-based CLM has known bypasses. WDAC provides stronger enforcement.
  3. Blocking PowerShell entirely — Removing PowerShell is rarely practical and often creates more problems than it solves. Hardening is more effective than prohibition.
  4. Not testing after deployment — Hardening configurations can break legitimate administrative workflows. Test in a lab, deploy in stages, and have a rollback plan.
  5. Ignoring PowerShell 7.x — If PowerShell 7 is installed alongside Windows PowerShell 5.1, both need logging and CLM enforcement. Attackers will use whichever version has weaker controls.

Related Reading


PowerShell is not the enemy — unmonitored, unconstrained PowerShell is. Every hardening measure described here adds a layer that attackers must bypass. The more layers, the more noise they generate, and the more chances your detection has to catch them.