跳转到帖子

授权内网测试中 WinRM 凭据有效却拒绝访问,如何定位权限边界与日志留痕?

精选回复

发布于

背景与问题

在一次已授权的 Windows 内网渗透测试中,测试账号能够正常登录域、访问部分 SMB 共享,但通过 WinRM 连接目标主机时出现 Access is denied、Kerberos authentication failed 或 HTTP 401。此类现象不应直接归因于“密码错误”,更常见的是网络监听、认证协议、远程管理授权、本地 UAC 过滤或 PowerShell 会话配置中的某一层拒绝了请求。

本文讨论的是已取得明确授权的验证场景。建议使用专门的测试账号和测试主机,并提前约定目标地址、测试时段及日志保留范围。

问题定位思路

WinRM 链路可以拆成五层。排查时按顺序验证,避免在身份权限问题上反复修改防火墙。

层级检查内容典型现象
网络TCP 5985 或 5986 是否可达连接超时、拒绝连接
监听器WinRM 服务及 Listener 是否存在端口未监听、WSMan 初始化失败
认证Kerberos、NTLM、证书或 Basic 配置401、凭据被拒绝、SPN 错误
授权管理员组、Remote Management Users、会话 ACL凭据有效但 Access is denied
令牌本地账号 UAC 远程过滤、JEA 限制可以认证但管理命令权限不足

一、先确认网络与监听器

从测试机仅进行连通性和 WSMan 协议探测。端口可达不代表账号已获授权,但可以先排除路由、主机防火墙和服务未启动的问题。

# 在测试机执行
Test-NetConnection 10.20.30.15 -Port 5985
Test-WSMan -ComputerName 10.20.30.15

# 使用 HTTPS 时检查 5986
Test-NetConnection 10.20.30.15 -Port 5986
Test-WSMan -ComputerName 10.20.30.15 -UseSSL

如果 TCP 测试失败,应由目标系统管理员在目标主机检查服务、监听地址和防火墙规则,而不是直接关闭防火墙。

# 在目标主机以管理员身份执行
Get-Service WinRM
winrm enumerate winrm/config/listener
Get-NetTCPConnection -State Listen -LocalPort 5985,5986 -ErrorAction SilentlyContinue
Get-NetFirewallRule -DisplayGroup 'Windows Remote Management' |
  Select-Object DisplayName,Enabled,Profile,Direction,Action

还要注意防火墙规则的 Profile 和 RemoteAddress。目标主机从 Domain 网络切换为 Public 网络后,已有规则可能不再生效;若规则只允许管理网段,来自其他测试网段的请求也会被正确阻断。

二、区分认证失败和授权失败

域环境优先使用主机名连接,以便 Kerberos 根据 HTTP 服务主体名称完成认证。直接使用 IP 地址通常无法正常匹配 Kerberos SPN,客户端可能回退到 NTLM,随后受域策略限制。

# 推荐:使用可解析的主机名
$cred = Get-Credential 'LAB\audit-winrm'
Test-WSMan -ComputerName srv-app-01.lab.example
Invoke-Command -ComputerName srv-app-01.lab.example `
  -Credential $cred -Authentication Kerberos `
  -ScriptBlock { whoami; hostname }

# 客户端检查名称解析和 Kerberos 票据
Resolve-DnsName srv-app-01.lab.example
klist

# 由域管理员检查 HTTP SPN,重点关注重复注册
setspn -Q HTTP/srv-app-01
setspn -Q HTTP/srv-app-01.lab.example

如果事件日志显示未知用户名、错误密码或 Kerberos 票据问题,应先处理认证。如果日志表明账号已成功登录,但远程会话仍被拒绝,则继续检查授权组和会话端点 ACL。

三、检查远程管理授权边界

默认情况下,本地 Administrators 成员通常可以建立完整管理会话。非管理员账号可加入 Remote Management Users,但这并不等于自动获得所有 PowerShell 命令、WMI 命名空间和受保护资源的权限。

# 在目标主机检查本地组成员
Get-LocalGroupMember -Group 'Administrators'
Get-LocalGroupMember -Group 'Remote Management Users'

# 域账号的有效组信息应在对应登录上下文中确认
whoami /user
whoami /groups

# 查看 PowerShell 会话端点
Get-PSSessionConfiguration |
  Select-Object Name,Permission

若账号刚被加入域组,现有 Kerberos 票据和登录令牌不会立即刷新。可以注销后重新登录,或在测试机清理该账号的票据后重新建立会话。不要通过反复扩大管理员组成员来掩盖令牌未刷新的问题。

如果组织使用 JEA,会话连接成功后仍可能只能运行白名单命令。这是预期的权限边界。可通过以下命令确认当前端点,而不应尝试绕过端点限制。

# 查看已注册端点及会话能力
Get-PSSessionConfiguration

# 连接指定的受限端点
Enter-PSSession -ComputerName srv-app-01.lab.example `
  -ConfigurationName 'Maintenance' `
  -Credential $cred

四、本地账号与 UAC 远程令牌过滤

使用目标主机本地管理员账号时,认证成功但部分远程管理操作被拒绝,常与 UAC 远程限制有关。注册表项 LocalAccountTokenFilterPolicy 会改变本地管理员远程令牌的过滤行为,但不建议为了测试直接将其设置为 1,因为这会扩大本地账号通过网络进行高权限管理的能力。

# 只读检查,不主动修改
$path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System'
Get-ItemProperty -Path $path -Name LocalAccountTokenFilterPolicy `
  -ErrorAction SilentlyContinue

# 检查本地管理员账号状态
Get-LocalUser | Select-Object Name,Enabled,LastLogon

更稳妥的做法是使用受控域账号、Windows LAPS 管理的本地管理员凭据,或为维护任务配置 JEA。若业务确实要求修改令牌过滤策略,应记录变更单、限定来源地址,并在验证后恢复。

五、核对客户端与服务端认证配置

TrustedHosts 不是常规域环境的首选方案。它主要用于无法使用 Kerberos 的工作组、IP 地址或跨域无信任场景,而且只影响客户端信任范围,不负责加密凭据,也不会赋予服务端权限。

# 客户端只读检查
Get-Item WSMan:\localhost\Client\TrustedHosts
Get-ChildItem WSMan:\localhost\Client\Auth

# 服务端只读检查
Get-ChildItem WSMan:\localhost\Service\Auth
winrm get winrm/config/service
winrm get winrm/config/client

不要使用通配符 TrustedHosts,也不要在 HTTP 上为图省事启用 Basic。确需跨工作组管理时,优先配置 HTTPS Listener,并将 TrustedHosts 精确限制为指定主机。

六、从日志确认拒绝发生在哪一层

WinRM 故障应同时看 PowerShell、WinRM 和 Windows 安全日志。以下命令适合在目标主机本地或由管理员执行,避免在未授权主机上远程批量采集。

$start = (Get-Date).AddMinutes(-30)

# WinRM 操作日志
Get-WinEvent -FilterHashtable @{
  LogName='Microsoft-Windows-WinRM/Operational'
  StartTime=$start
} | Select-Object TimeCreated,Id,LevelDisplayName,Message

# PowerShell 远程会话相关日志
Get-WinEvent -FilterHashtable @{
  LogName='Microsoft-Windows-PowerShell/Operational'
  StartTime=$start
} | Select-Object TimeCreated,Id,Message

# 登录成功、登录失败及显式凭据使用
Get-WinEvent -FilterHashtable @{
  LogName='Security'
  Id=4624,4625,4648
  StartTime=$start
} | Select-Object TimeCreated,Id,Message

重点关注以下信息:

  • 4625 中的 Status、SubStatus、LogonType、Source Network Address 和 Authentication Package。
  • 4624 的 LogonType。远程网络登录通常可见类型 3,但具体记录受调用方式和审计策略影响。
  • 4648 表示使用了显式凭据,适合关联测试机、目标账号和时间线。
  • WinRM Operational 日志可帮助判断请求是否到达服务端,以及失败是否发生在认证或插件处理阶段。
  • PowerShell Operational 中的 4103、4104 是否存在,取决于模块日志和脚本块日志策略。

建议以统一时区记录测试时间,并保留测试源 IP、目标主机、账号、执行命令及预期结果。只凭客户端报错很难准确判断权限边界。

可复用的最小化排查步骤

# 1. 网络
Test-NetConnection srv-app-01.lab.example -Port 5985

# 2. 协议
Test-WSMan srv-app-01.lab.example

# 3. DNS 与 Kerberos
Resolve-DnsName srv-app-01.lab.example
klist

# 4. 使用明确认证方式执行无副作用命令
$cred = Get-Credential 'LAB\audit-winrm'
Invoke-Command -ComputerName srv-app-01.lab.example `
  -Credential $cred -Authentication Kerberos `
  -ScriptBlock { whoami; hostname; Get-Date }

# 5. 由目标管理员核对组、端点和最近 15 分钟日志
Get-LocalGroupMember 'Remote Management Users'
Get-PSSessionConfiguration
Get-WinEvent -FilterHashtable @{
  LogName='Microsoft-Windows-WinRM/Operational'
  StartTime=(Get-Date).AddMinutes(-15)
}

风险与修复建议

  • 限制来源:使用主机防火墙将 5985、5986 的 RemoteAddress 限制为跳板机或管理网段。
  • 优先 Kerberos:域内通过完整主机名连接,及时修复 DNS 和重复 SPN,避免无必要的 NTLM 回退。
  • 最小权限:普通运维任务使用 Remote Management Users 配合 JEA,不要长期授予本地管理员权限。
  • 保护本地账号:部署 Windows LAPS,禁用共享本地管理员密码,不因测试长期关闭 UAC 远程过滤。
  • 加密传输:工作组或跨信任边界场景优先使用 HTTPS Listener,证书应匹配主机名并由受信任链签发。
  • 保留审计:集中采集 WinRM、PowerShell 和安全日志,开启适当的进程创建、模块日志及脚本块日志策略,并设置合理留存周期。
  • 避免危险放宽:不要设置 TrustedHosts 为通配符,不要全局关闭防火墙,也不要在完成验证后遗留临时管理员组成员。

总结

WinRM 的“凭据正确但拒绝访问”通常不是单点故障。有效的排查顺序是先验证网络和 Listener,再区分认证与授权,随后检查会话端点、本地 UAC 令牌过滤及日志证据。对授权渗透测试而言,结论不应只写“无法连接”,而应明确指出拒绝发生在哪一层、当前控制是否符合预期,以及是否存在过度放宽配置。这样既能验证权限边界,也能给修复和复测留下可执行依据。

服务器与云环境安全示意图
服务器、云资产与权限边界梳理示意
网络流量与边界分析示意图
网络请求、日志与边界流量分析示意

先把“凭据有效”和“允许建立 WinRM 会话”分开看。WinRM 返回 Access is denied 时,通常已经通过身份验证,失败点更可能在端点 ACL、本地组权限、UAC 远程令牌过滤或域策略。建议保留原始错误中的错误码、认证方式和目标名称,不要只看中文提示。

1. 先确认连接链路和身份是否符合预期

Test-NetConnection server01 -Port 5985
Test-WSMan server01

$cred = Get-Credential 'CONTOSO\tester'
Invoke-Command -ComputerName server01 -Credential $cred `
  -Authentication Kerberos `
  -ScriptBlock { whoami /all } -ErrorVariable winrmErr

$winrmErr | Format-List * -Force

域环境优先使用主机名和 Kerberos。若用 IP、别名或跨域连接,可能退回 NTLM;这时“同一套凭据在 SMB/RDP 可用”不能证明 WinRM 授权路径相同。可在客户端检查 Kerberos 票据:

klist purge
klist get HTTP/server01.contoso.local
klist

2. 在目标机核对 WinRM 端点的授权边界

Get-PSSessionConfiguration |
  Select-Object Name, Permission, Enabled, PSVersion |
  Format-List

Get-PSSessionConfiguration -Name Microsoft.PowerShell |
  Format-List *

winrm enumerate winrm/config/listener
winrm get winrm/config/service/auth

重点看目标端点的 Permission,以及账号是否属于被授权的本地组。默认端点通常要求本地 Administrators;如果配置过 JEA、自定义会话端点或修改过 SDDL,账号即使密码正确也会被拒绝。不要直接执行 Enable-PSRemoting -Force 覆盖现有配置,先导出当前状态:

Get-PSSessionConfiguration |
  Format-List * |
  Out-File C:\Windows\Temp\pssession-config-before.txt

winrm get winrm/config > C:\Windows\Temp\winrm-config-before.txt

3. 核对实际组成员关系,而不是只看 AD 页面

whoami /user
whoami /groups
Get-LocalGroupMember -Group Administrators
Get-LocalGroupMember -Group 'Remote Management Users' -ErrorAction SilentlyContinue

如果使用域组授予权限,要留意组嵌套、刚调整成员关系但 Kerberos 票据尚未刷新,以及目标机无法联系域控导致授权信息不完整。重新登录或清理票据后再测,比反复改密码更有意义。

4. 本地账户要单独排查 UAC 远程令牌过滤

非内置本地管理员通过网络登录时,可能拿到被过滤的令牌,从而表现为凭据有效但管理端点拒绝。先读取策略,不建议为排障直接关闭过滤:

Get-ItemProperty `
  'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System' `
  -Name LocalAccountTokenFilterPolicy -ErrorAction SilentlyContinue

如果域账号可用、本地管理员账号失败,这一项优先级很高。生产环境更稳妥的处理是使用受控域账号、JEA 端点或显式端点 ACL,而不是把 LocalAccountTokenFilterPolicy 长期设为 1。

5. 用服务端事件确认失败发生在哪一层

$start = (Get-Date).AddMinutes(-15)

Get-WinEvent -FilterHashtable @{
  LogName   = 'Microsoft-Windows-WinRM/Operational'
  StartTime = $start
} | Select-Object TimeCreated, Id, LevelDisplayName, Message

Get-WinEvent -FilterHashtable @{
  LogName   = 'Windows PowerShell'
  StartTime = $start
} | Select-Object TimeCreated, Id, Message

Get-WinEvent -FilterHashtable @{
  LogName   = 'Security'
  Id        = 4624,4625,4672,4688
  StartTime = $start
} | Select-Object TimeCreated, Id, Message
  • 4625:重点记录状态码、子状态码、登录类型和 Authentication Package;这更偏身份验证失败。
  • 4624 已出现但随后 WinRM 拒绝:更偏端点 ACL、组权限或令牌过滤。
  • 4672:可辅助判断是否拿到管理员特权令牌。
  • WinRM Operational:通常能看到插件初始化、Shell 创建或授权阶段的失败。

如果 WinRM Operational 未启用,可在测试窗口内开启,并记录变更时间:

wevtutil sl Microsoft-Windows-WinRM/Operational /e:true
wevtutil gli Microsoft-Windows-WinRM/Operational

6. 留痕建议

每次测试至少保存:客户端命令及完整错误、UTC 时间、源/目标 IP、目标主机名、用户名格式、认证方式、端口、事件日志导出和测试前后的配置摘要。事件日志可直接导出,避免复制文本时丢失字段:

$stamp = Get-Date -Format yyyyMMdd-HHmmss
wevtutil epl Microsoft-Windows-WinRM/Operational `
  "C:\Windows\Temp\WinRM-$stamp.evtx"

wevtutil epl Security `
  "C:\Windows\Temp\Security-$stamp.evtx" `
  "/q:*[System[TimeCreated[timediff(@SystemTime) <= 1800000]]]"

排查顺序建议是:先固定主机名与认证方式,再确认服务端是否产生 4624/4625,随后检查端点权限和实际令牌,最后才考虑修改策略。这样能较快区分“认证失败”“端点未授权”和“管理员令牌被过滤”,也避免为了让测试通过而扩大 WinRM 权限面。

创建帐户或登录后发表意见

最近浏览 0

  • 没有会员查看此页面。