WinRM and PowerShell Remoting Security: How to Harden Remote Management Without Disabling It

Retool's new app builder is where AI-generated code ships safely
Building apps with AI is easy. Getting them to production safely is another story.
WinRM is a legitimate and necessary management protocol in most enterprise environments. The hardening goal is not elimination but containment: configure HTTPS, restrict which sources can reach WinRM on servers, disable WinRM on workstations that do not need remote management, and ensure the audit logging captures WinRM-based lateral movement. Most WinRM-based lateral movement in incident investigations uses HTTP (cleartext transport) and relies on LocalAccountTokenFilterPolicy being set to allow local admin auth -- two settings that are trivial to fix.
Configure WinRM to Use HTTPS
HTTP WinRM (port 5985) sends command output unencrypted. Require HTTPS (5986) for all WinRM connections.
Create an HTTPS listener (requires a machine certificate):
# The machine must have a certificate in the LocalMachine\My store with
# the Subject matching the machine's FQDN (or a wildcard)
# Find the certificate thumbprint
$cert = Get-ChildItem Cert:\LocalMachine\My |
Where-Object { $_.Subject -match $env:COMPUTERNAME }
$thumbprint = $cert.Thumbprint
# Create the HTTPS listener
New-Item -Path WSMan:\LocalHost\Listener -Transport HTTPS `
-Address * -CertificateThumbprint $thumbprint -Force
# Verify
Get-ChildItem WSMan:\LocalHost\Listener
# Should show both HTTP and HTTPS (or HTTPS only if you delete the HTTP listener)
# Optional: Remove the HTTP listener to force HTTPS only
Remove-Item WSMan:\LocalHost\Listener\Listener_* -Force
# Then recreate only the HTTPS listener as above
Enforce HTTPS via Group Policy:
Computer Configuration > Administrative Templates > Windows Components > Windows Remote Management (WinRM) > WinRM Service
- Allow Basic authentication: Disabled
- Allow unencrypted traffic: Disabled
For certificates at scale, use an internal CA with auto-enrollment via Group Policy -- computer certificates enrolled to all domain members provide the HTTPS listener certificates without manual steps.
Restrict WinRM Access via Firewall and Group Policy
Windows Firewall rule to restrict WinRM source IPs:
# Allow WinRM HTTPS only from management server IPs
New-NetFirewallRule -Name 'WinRM-HTTPS-Management' `
-DisplayName 'WinRM HTTPS from management servers only' `
-Direction Inbound -Protocol TCP -LocalPort 5986 `
-RemoteAddress @('10.10.1.50', '10.10.1.51', '10.10.1.0/24') `
-Action Allow -Profile Domain
# Block WinRM from all other sources (default deny posture)
New-NetFirewallRule -Name 'WinRM-BLOCK-OTHER' `
-DisplayName 'Block WinRM from non-management sources' `
-Direction Inbound -Protocol TCP -LocalPort 5985,5986 `
-Action Block -Profile Domain
Deploy these rules via GPO for the Server and Workstation OUs.
Fix LocalAccountTokenFilterPolicy:
# Check current setting (1 = local admins have full WinRM access, 0 = restricted)
Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System' `
-Name LocalAccountTokenFilterPolicy -ErrorAction SilentlyContinue
# Disable local admin WinRM full access (set to 0)
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System' `
-Name LocalAccountTokenFilterPolicy -Type DWord -Value 0
Set TrustedHosts to a specific list (or empty):
# View current TrustedHosts
Get-Item WSMan:\LocalHost\Client\TrustedHosts
# Set to empty (safest for domain-joined machines that use Kerberos)
Set-Item WSMan:\LocalHost\Client\TrustedHosts -Value '' -Force
# Or restrict to specific jump server IPs
Set-Item WSMan:\LocalHost\Client\TrustedHosts -Value '10.10.1.50,10.10.1.51' -Force
# Deploy via Group Policy:
# Computer Configuration > Administrative Templates > Windows Components > WRM (WinRM) > WinRM Client
# Trusted Hosts: specify the allowed list
Briefings like this, every morning before 9am.
Threat intel, active CVEs, and campaign alerts, distilled for practitioners. 50,000+ subscribers. No noise.
Disable WinRM on Workstations
Workstations generally do not need inbound WinRM. Disabling it removes a lateral movement target.
Disable via Group Policy (applied to Workstations OU):
Computer Configuration > Windows Settings > Security Settings > System Services
- Windows Remote Management (WS-Management): Disabled
Or via Administrative Templates:
Computer Configuration > Administrative Templates > Windows Components > Windows Remote Management (WinRM) > WinRM Service
- Allow remote server management through WinRM: Disabled
Verify WinRM status on workstations:
# Check WinRM service status across workstation fleet (run from management server)
$workstations = Get-ADComputer -SearchBase 'OU=Workstations,DC=domain,DC=com' -Filter *
foreach ($ws in $workstations) {
try {
$svc = Get-Service -ComputerName $ws.Name -Name WinRM -ErrorAction Stop
if ($svc.Status -eq 'Running') {
Write-Output "$($ws.Name) - WinRM RUNNING"
}
} catch {
Write-Output "$($ws.Name) - UNREACHABLE"
}
}
Exception: If you use Ansible, Intune Proactive Remediation, or custom WinRM-based scripts on workstations, keep WinRM enabled but enforce the HTTPS listener, firewall restrictions, and LocalAccountTokenFilterPolicy = 0.
Detect Lateral Movement via WinRM in Event Logs
WinRM lateral movement generates auditable events on both the source and target machines.
On the target machine (where WinRM is connecting to):
# Event ID 4624 (Successful logon) -- Logon Type 3 (network)
# Authentication Package: Kerberos or NTLM
# Source IP: the machine initiating the WinRM connection
# This fires for every WinRM connection
# Event ID 4688 (Process creation) -- Command Line Auditing must be enabled
# A WinRM session spawning wsmprovhost.exe is normal
# wsmprovhost.exe spawning cmd.exe, powershell.exe, or net.exe is suspicious
# Event ID 4103/4104 (PowerShell Script Block Logging)
# These capture commands run in WinRM sessions -- ship to SIEM
# See: PowerShell Script Block Logging guide
On the source machine (initiating the WinRM connection):
# Event ID 4624 with Logon Type 3 from the machine account or user
# to a remote destination is the source-side indicator
# Microsoft-Windows-WinRM/Operational log:
# Event ID 6 (WSMan Session initialized) -- every new WinRM session
# Event ID 91 (Creating WSMan Session) -- captures destination hostname/IP
Alert on:
// Sentinel/KQL: WinRM connections from workstations to workstations
SecurityEvent
| where EventID == 4624 and LogonType == 3
| where Computer !contains 'server' // filter out server-to-server (adjust for your naming)
| where AccountName !endswith '$' // filter machine account logins
| where IpAddress !in ('known-mgmt-IPs')
The bottom line
WinRM hardening in priority order: disable the HTTP listener (enforce HTTPS), set LocalAccountTokenFilterPolicy to 0 (prevents local admin lateral movement), restrict WinRM inbound via Windows Firewall to management server IPs only, disable WinRM on workstations via GPO. Enable Script Block Logging and PowerShell Module Logging to capture commands run through WinRM sessions -- these are your primary audit trail for WinRM-based post-exploitation.
Frequently asked questions
Does disabling HTTP WinRM and requiring HTTPS break Ansible?
No. Ansible's WinRM connection plugin supports HTTPS (winrm_scheme: https) and is the recommended configuration. You need to point Ansible at port 5986 and either use a trusted CA-signed certificate or configure Ansible to accept a self-signed certificate (cert_validation: ignore for lab environments). For production, enroll machine certificates from your internal CA and trust the CA in Ansible's certificate store. The Ansible WinRM documentation covers this -- it is a one-time configuration change per inventory or group_vars.
Can an attacker use WinRM if they only have a regular domain user credential?
By default, no. WinRM requires the connecting account to be a local administrator on the target machine. Domain users are not local admins on servers (in a properly managed environment), so they cannot establish a WinRM session. The risk is: if a domain user account is also a local admin on servers (common in flat environments or where developers have admin rights on their project servers), WinRM becomes a lateral movement path for that account. This is why local admin rights should be tightly controlled and LAPS should manage unique passwords for the local administrator account.
Should I enable WinRM on all servers or only specific ones?
Enable it where your management tooling requires it, which is typically all servers -- SCCM/Intune, monitoring agents, Ansible, Windows Admin Center, and many other tools require WinRM. The mitigation is not selective enablement but firewall restriction: WinRM should be reachable only from your management server IPs, not from other servers and not from workstations. This gives you management connectivity while preventing lateral movement via WinRM from compromised endpoints that are not in your management IP range.
What is the difference between WinRM and DCOM/WMI for remote administration?
WinRM and WMI (via DCOM on port 135 + dynamic RPC) are two separate remote administration protocols in Windows. PowerShell remoting uses WinRM exclusively. Some legacy tools (including old versions of Get-WmiObject) use DCOM/WMI directly. Modern PowerShell uses Get-CimInstance which defaults to WinRM (WSMAN protocol) but can fall back to DCOM for compatibility. For security hardening: restrict both WinRM ports (5985/5986) and DCOM/RPC (TCP 135 + ephemeral ports) to management sources. From a lateral movement perspective, both protocols are abused -- Impacket's wmiexec.py uses DCOM while evil-winrm uses WinRM.
How do I configure WinRM to use HTTPS instead of HTTP?
Create an HTTPS listener by installing a server certificate (from your internal CA or via Intune SCEP profile) on each target machine, then run: `New-WSManInstance -ResourceURI winrm/config/Listener -SelectorSet @{Address='*';Transport='HTTPS'} -ValueSet @{Hostname='server.domain.com';CertificateThumbprint='THUMBPRINT'}`. Configure the Group Policy setting Computer Configuration > Administrative Templates > Windows Components > Windows Remote Management (WinRM) > WinRM Service > Allow remote server management through WinRM to specify HTTPS only (port 5986). Disable the HTTP listener: `winrm delete winrm/config/Listener?Address=*+Transport=HTTP`. HTTPS WinRM prevents credential interception during PowerShell remoting sessions in environments where network traffic may be captured.
How do I restrict WinRM to specific IP addresses or network ranges?
WinRM access restriction can be configured at multiple layers. At the WinRM listener level: configure an IPv4Filter or IPv6Filter in the WinRM configuration to restrict which source IPs can connect. Run `winrm set winrm/config/Service '@{IPv4Filter="10.0.1.0/24;192.168.100.0/24"}'` to allow only management network ranges. At the Windows Firewall level: create an inbound rule allowing TCP 5985/5986 only from management source IPs, which provides enforcement even if the WinRM filter is misconfigured. At the WinRM session configuration level (per endpoint): use Set-PSSessionConfiguration with the AccessMode and SecurityDescriptorSddl parameters to control which users or groups can connect to specific endpoints. For JEA endpoints, the session configuration itself restricts the users who can connect, making the listener-level filtering a defense-in-depth control rather than the primary access control.
Sources & references
Free resources
Critical CVE Reference Card 2025–2026
25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, share it with your SOC team.
Ransomware Incident Response Playbook
Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.
Get threat intel before your inbox does.
50,000+ security professionals read Decryption Digest for early warnings on zero-days, ransomware, and nation-state campaigns. Free, daily, no spam.
Unsubscribe anytime. We never sell your data.

Founder & Cybersecurity Evangelist, Decryption Digest
Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals every morning.
Win a $2,495 Black Hat pass.
Full-access to Black Hat USA 2026 in Las Vegas. Subscribe free to enter.
