PowerShell远程会话(WinRM)的默认加密机制在域环境下通常依赖Kerberos,而在工作组环境中则容易降级为仅使用CredSSP或Basic认证,这存在凭据泄露的风险。更核心的问题在于,默认的WinRM侦听器配置可能仅使用自签名证书进行简单的传输层加密,或者根本没有启用HTTPS,导致数据在网络上以极易被解密的格式传输。要真正锁定远程会话,必须从双阶段加密入手:一是传输层的信道加密,二是会话层的消息级加密。传输层加密强制WinRM使用HTTPS,这需要绑定一个受信任的服务器身份验证证书。消息级加密则通过配置会话选项,强制所有通信使用特定的加密算法套件,防止协议降级攻击。
强制启用HTTPS传输层加密WinRM默认侦听5985(HTTP)和5986(HTTPS)端口。许多管理员为了方便,仅开放5985端口,这会让所有远程操作以近乎明文的形式传输。要彻底解决此问题,必须禁用HTTP侦听器,并强制WinRM仅通过HTTPS通信。首先,需要一张服务器身份验证证书。在企业内部,这通常由AD证书服务颁发;在独立服务器上,可以使用OpenSSL生成自签名证书,但更推荐使用Windows内置的New-SelfSignedCertificate cmdlet。执行以下命令创建证书,注意将DNS名称替换为服务器的实际完全限定域名:
New-SelfSignedCertificate -DnsName "server01.internal.lab" -CertStoreLocation "Cert:\LocalMachine\My" -KeyLength 2048 -KeyAlgorithm RSA -TextExtension "2.5.29.37={text}1.3.6.1.5.5.7.3.1"
证书创建后,需要将其指纹绑定到HTTPS侦听器。使用以下命令创建新的WinRM HTTPS侦听器,并指定端口为5986:
$thumbprint = (Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object { $_.Subject -match "server01" }).Thumbprint
New-Item -Path WSMan:\LocalHost\Listener -Transport HTTPS -Address * -CertificateThumbprint $thumbprint -Port 5986 -Force
此操作会在WSMan驱动器中创建一个永久性的HTTPS侦听器。为确保安全策略的严格执行,应立即删除所有HTTP侦听器,并配置防火墙仅允许5986端口的入站流量。删除HTTP侦听器的命令如下:
Get-ChildItem -Path WSMan:\LocalHost\Listener | Where-Object { $_.Transport -eq "HTTP" } | Remove-Item -Recurse -Force
完成上述步骤后,任何尝试通过HTTP协议或默认5985端口发起的远程连接都会被直接拒绝。客户端连接时必须显式指定使用HTTPS和5986端口,例如:
Enter-PSSession -ComputerName server01.internal.lab -UseSSL -Port 5986 -Credential (Get-Credential)
这种强制SSL/TLS的配置确保了网络嗅探工具无法直接读取会话内容,因为所有数据包都在传输层被加密。
配置会话层消息加密与算法锁定传输层加密解决了网络窃听问题,但会话层的消息加密决定了数据在端点之间的保护强度。PowerShell会话的加密协商过程由WinRM管理,它支持多种加密算法。默认情况下,客户端和服务器会协商一个双方都支持的算法,这可能包含较弱的旧式算法。为了达到硬核安全标准,必须通过组策略或本地策略锁定加密算法套件,禁用RC4等弱算法,并强制使用AES-256或更高强度的加密。
在客户端或服务器上,通过组策略编辑器(gpedit.msc)定位到“计算机配置” -> “管理模板” -> “Windows组件” -> “Windows远程管理(WinRM)” -> “WinRM服务”。启用“允许通过WinRM进行远程Shell访问”策略后,进一步配置“指定信道绑定的令牌类型”和“允许的基本身份验证”等设置。但更细粒度的算法控制位于“计算机配置” -> “管理模板” -> “Windows组件” -> “Windows远程管理(WinRM)” -> “WinRM客户端”下的“禁止协商式身份验证”和“允许CredSSP身份验证”。
真正的算法锁定需要修改WinRM的WSMan配置。可以通过命令行直接指定允许的加密算法集。查看当前配置,使用:
winrm get winrm/config/service
要强制WinRM服务端仅使用AES-256-CBC进行加密,并禁用所有其他算法,可以执行以下命令:
winrm set winrm/config/service @{MaxConcurrentOperations="100";AllowUnencrypted="false";Auth="{Basic=false,Kerberos=true,Negotiate=true,Certificate=true,CredSSP=false}";DefaultPorts="{HTTPS=5986}"}
其中AllowUnencrypted参数必须设置为false,这是防止会话降级为明文的关键。虽然WinRM没有直接提供选择AES-256的单一开关,但它遵循Schannel和协商协议的算法优先级。通过修改Windows的Schannel注册表项,可以强制系统优先使用高强度的密码套件。定位到注册表路径:
HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers
在该路径下,可以为AES 256/256创建子项,并设置Enabled值为0xffffffff,同时禁用RC4、DES等子项。这种系统级的密码套件管理会直接影响WinRM的加密协商结果,确保会话消息使用最高强度的对称加密算法。
利用PowerShell会话选项实现双向证书认证仅依赖用户名和密码,即使信道加密,仍然面临凭据盗窃和重放攻击的风险。更高级的加密方案是使用客户端证书进行双向认证。这要求服务器不仅拥有证书,客户端也必须出示受服务器信任的证书。这种模式下,会话的密钥交换基于公钥基础设施,安全性远超单纯的口令认证。
首先,需要为客户端也颁发用户身份验证证书。在AD环境中,这可以通过证书模板自动注册实现;在非域环境中,需要手动创建并导出证书。假设已获得客户端证书(PFX格式),在发起PowerShell远程会话时,需要创建一个包含证书信息的会话选项对象:
$cert = Get-ChildItem -Path Cert:\CurrentUser\My | Where-Object { $_.EnhancedKeyUsageList -match "客户端验证" }
$sessionOption = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck
$securePassword = ConvertTo-SecureString "YourPassword" -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential("Administrator", $securePassword)
然后,使用证书和凭据共同建立会话。但更纯粹的方式是完全舍弃密码,仅使用证书进行身份验证。这需要在WinRM服务端启用证书认证,并将客户端证书的公钥映射到本地用户。在服务器上,执行以下命令启用证书认证:
Set-Item -Path WSMan:\LocalHost\Service\Auth\Certificate -Value $true
接下来,必须建立客户端证书到Windows用户账户的映射。将客户端证书的指纹或主题与本地用户关联,可以通过WinRM的CertMapping功能实现:
New-Item -Path WSMan:\LocalHost\ClientCertificate -Subject "client01.internal.lab" -URI * -Issuer (Get-ChildItem Cert:\LocalMachine\Root\ClientRootCA指纹) -Credential (Get-Credential)
完成映射后,客户端连接时只需指定证书,无需提供密码:
Enter-PSSession -ComputerName server01.internal.lab -UseSSL -Port 5986 -CertificateThumbprint $cert.Thumbprint
这种双向TLS握手配合客户端证书认证,不仅加密了信道,还彻底消除了口令传输和存储的风险,是目前Windows原生环境下最强的远程会话加密方案之一。
JEA端点与受限管理模式下的加密强化Just Enough Administration (JEA) 是PowerShell安全纵深防御的重要组成部分。JEA端点不仅限制用户可以执行的cmdlet,还在内部强制使用了虚拟账户或组托管服务账户(gMSA)。从加密角度看,JEA会话在初始化时自动进行加密,且不允许用户提升权限或绕过加密通道。创建JEA端点时,会话配置文件可以显式指定可见的提供程序和模块,同时强制所有连接到该端点的会话使用HTTPS。
创建JEA会话配置文件的命令如下:
New-PSSessionConfigurationFile -Path "C:\ProgramData\JEA\SecureEndpoint.pssc" -SessionType RestrictedRemoteServer -LanguageMode NoLanguage -VisibleCmdlets @{ Name="Get-Service"; Parameters=@{ Name="Name"; ValidateSet="Spooler","WinRM" }} -RequiredGroups @{ And="Administrators"; Or="Remote Operators" }
注册此端点时,直接绑定到HTTPS侦听器并禁用所有其他传输方式:
Register-PSSessionConfiguration -Name "SecureSupport" -Path "C:\ProgramData\JEA\SecureEndpoint.pssc" -Force -ShowSecurityDescriptorUI
在注册过程中,通过安全描述符严格控制谁可以连接。JEA端点运行时,用户的操作在高度受限的沙箱中执行,其进程令牌是临时的虚拟账户,无法访问网络资源或修改系统加密设置。即使攻击者获取了JEA会话,由于语言模式被锁定为NoLanguage,无法执行任意脚本,也无法通过PowerShell降级加密策略。这种机制将加密从单纯的传输保护扩展到了执行环境的完整性保护。
监控与审计加密会话状态加密配置部署后,持续的监控是验证安全策略有效性的必要手段。可以通过查询WinRM日志和PowerShell事件日志来确认所有会话是否确实使用了加密。在事件查看器中,导航到“应用程序和服务日志” -> “Microsoft” -> “Windows” -> “Windows Remote Management” -> “Operational”。事件ID 80和81记录连接请求和认证方式。检查这些事件的详细信息,可以确认客户端是否使用了HTTPS以及协商的认证协议。
此外,使用PowerShell本身可以实时查看当前活动会话的加密状态。执行以下命令获取所有运行中的远程会话详情:
Get-PSSession | Select-Object ComputerName, State, Availability, Id, @{Name="Transport"; Expression={ $_.ComputerType }}
对于更深入的WinRM配置审计,可以导出完整的WSMan配置快照:
winrm enumerate winrm/config/listener
该命令会列出所有侦听器的传输协议、端口和证书指纹。定期将此输出与安全基线进行比较,确保没有意外的HTTP侦听器被重新启用。如果检测到任何非加密会话,应立即触发警报并强制断开连接,使用Remove-PSSession命令终止可疑会话。
通过强制HTTPS传输、锁定AES-256会话算法、部署双向证书认证以及实施JEA受限端点,Windows系统的PowerShell远程会话加密强度可以达到抵御现代网络嗅探和中间人攻击的水平。这种多层次的加密策略不需要依赖第三方工具,完全基于Windows内置的安全组件,是构建自动化运维通道时必须达到的安全基线。
