Windows服务器上堆积的闲置账号从来不是小问题,它们像一扇扇长期不锁的后门,攻击者一旦掌握其中任何一个凭据,就能绕过正面防御直接进入内网。很多运维团队习惯把精力放在补丁更新和防火墙策略上,却忽略了账号本身的收敛,等到出事才发现某个三年前离职员工的账号还在被用来登录。清理闲置账号不是简单删几个用户,而是一套涉及识别、评估、禁用、删除和持续监控的流程。

闲置账号为什么是入侵入口

攻击者进入Windows服务器的路径通常不是硬碰硬破解管理员密码,而是先收集那些密码薄弱、长期未改、无人关注的账号。闲置账号往往具备几个危险特征:密码复杂度低、密码永不过期、登录审计缺失、权限残留过多。很多企业给临时外包人员、离职员工、测试项目创建过本地账号或域账号,项目结束后账号无人回收,这些账号就成了理想的爆破目标。更麻烦的是,部分闲置账号还保留着远程桌面登录权限或本地管理员组权限,一旦被拿下,攻击者可以直接提权或横向移动。

从合规角度看,等保、ISO 27001、SOC 2等标准都明确要求定期审查账号生命周期。账号只增不减的环境,审计时很难解释清楚“为什么五年前的测试账号还在”。所以清理闲置账号既是安全加固,也是合规刚需。

先定义什么是“闲置账号”

清理之前必须明确判定标准,否则容易误删正在使用的服务账号或系统内置账号。通常可以把闲置账号分为三类:

第一类是长期无登录行为的用户账号。比如超过90天没有成功登录过的域账号或本地账号。这个阈值可以根据企业实际情况调整,关键是要有明确的时间线。

第二类是已离职或已转岗人员的账号。这类账号可能仍有登录记录,但使用人已经不再需要访问该服务器。HR流程和IT流程脱节时,这类账号最容易漏掉。

第三类是用途不明或无人认领的服务账号。很多应用部署时会创建专用账号来运行服务,时间久了文档丢失,没人知道这个账号还在不在用、能不能删。

判定闲置不能只看“最后登录时间”,因为有些攻击者登录后不会触发常规的登录记录更新,或者某些服务账号的登录行为不规律。需要结合账号创建时间、密码最后修改时间、所属组、描述字段、关联的应用或任务计划来综合判断。

识别闲置账号的具体方法

在Windows环境中,识别闲置账号最直接的工具是PowerShell。对于本地账号,可以通过WMI或ADSI查询最后登录时间。下面这段脚本可以列出本地用户及其最后登录时间:

Get-LocalUser | ForEach-Object {
    $user = $_
    $lastLogon = $user.LastLogon
    [PSCustomObject]@{
        Name = $user.Name
        Enabled = $user.Enabled
        LastLogon = $lastLogon
        Description = $user.Description
    }
} | Sort-Object LastLogon

需要注意的是,本地用户的LastLogon属性在某些Windows版本上可能不准确,尤其是从未登录过的账号会显示为空。更可靠的方式是查询安全事件日志中的登录事件,但日志可能被覆盖或未开启审核策略。建议先开启“审核登录事件”和“审核账户管理”策略,确保后续有据可查。

对于域环境,可以用Active Directory模块查询域账号的最后登录时间。域账号的lastLogon属性分散在各域控制器上,需要遍历所有域控取最大值,或者使用lastLogonTimestamp作为参考。下面是一个查询90天以上未登录域账号的示例:

$days = 90
$cutoff = (Get-Date).AddDays(-$days)
Get-ADUser -Filter * -Properties lastLogonTimestamp, Description, Enabled |
Where-Object {
    $_.Enabled -eq $true -and
    $_.lastLogonTimestamp -ne $null -and
    [DateTime]::FromFileTime($_.lastLogonTimestamp) -lt $cutoff
} |
Select-Object Name, SamAccountName, DistinguishedName,
    @{Name='LastLogon';Expression={[DateTime]::FromFileTime($_.lastLogonTimestamp)}},
    Description

这个脚本只筛选了启用状态且最后登录时间早于90天前的账号。实际使用时建议把阈值放宽到180天甚至更长,先观察再逐步收紧,避免误伤低频使用的合法账号。

评估账号是否可以清理

识别出候选账号后,不能直接删除。每个账号都要经过一轮评估,确认它是否真的不再需要。评估时重点看几个方面:

账号属于哪个组。如果账号在Domain Admins、Enterprise Admins、本地Administrators等敏感组里,要格外谨慎,先确认是否有人力依赖这个账号执行管理任务。

账号是否有关联的服务或任务。检查Windows服务、计划任务、IIS应用程序池、SQL Server服务账户等,看是否引用了该账号。可以用下面的命令检查服务登录账户:

Get-WmiObject Win32_Service | Where-Object {
    $_.StartName -like '*用户名*'
} | Select-Object Name, StartName, State

账号是否被用于远程桌面或VPN登录。如果企业有远程访问日志,可以交叉比对。没有日志的话,至少检查该账号是否属于Remote Desktop Users组。

账号是否有特殊权限或委派。域账号可能配置了委派权限、约束委派或基于资源的约束委派,删除前需要确认这些配置是否还有效。

账号的创建者和描述字段。有时候账号描述里会写明用途和负责人,这是判断的重要线索。如果描述为空且无人认领,风险更高。

先禁用后删除,留出观察期

直接删除账号的风险在于:如果某个应用或脚本还在使用这个账号,删除后服务立刻中断,而且恢复起来比较麻烦。更稳妥的做法是先禁用账号,观察一段时间,确认没有异常后再删除。

禁用本地账号可以用:

Disable-LocalUser -Name "用户名"

禁用域账号可以用:

Disable-ADAccount -Identity "用户名"

观察期建议至少30天,期间监控安全日志和应用日志,看是否有登录失败事件、服务启动失败事件或应用报错。如果发现某个应用因为账号被禁用而异常,可以快速重新启用。观察期结束后,如果没有任何依赖迹象,再执行删除。

删除本地账号:

Remove-LocalUser -Name "用户名"

删除域账号:

Remove-ADUser -Identity "用户名" -Confirm:$false

删除前建议先导出账号信息,包括SID、所属组、权限配置等,方便日后审计或恢复。可以用下面的命令导出账号详情:

Get-ADUser -Identity "用户名" -Properties * |
Export-Csv -Path "C:\backup\用户名.csv" -NoTypeInformation

处理服务账号和系统内置账号

服务账号的清理要单独对待。很多服务账号的密码长期不变,而且往往拥有较高的本地权限。清理服务账号时,先确认它关联的服务是否还在运行,服务是否还需要。如果服务已经下线,账号可以直接禁用或删除。如果服务还在运行,需要先修改服务的登录账户,再处理旧账号。

系统内置账号如Administrator、Guest、DefaultAccount等,不建议删除,但可以禁用Guest和DefaultAccount。Administrator账号建议重命名并设置强密码,同时禁用不必要的登录方式。很多攻击者第一步就是尝试Administrator和Guest账号,重命名能显著降低自动化攻击的成功率。

建立账号生命周期管理机制

一次性清理只能解决存量问题,真正减少入侵入口要靠持续的账号生命周期管理。至少要做到以下几点:

入职和离职流程与账号创建删除联动。HR系统或工单系统里人员变动时,自动触发账号禁用或删除操作。即使没有自动化,也要规定离职账号必须在24小时内禁用。

定期审查账号。每季度或每半年跑一次闲置账号扫描脚本,输出报告给相关负责人确认。审查结果要留档,作为合规证据。

限制账号权限。遵循最小权限原则,普通用户账号不授予本地管理员权限,服务账号只授予运行服务所需的最小权限。权限越小,账号被滥用后的影响越小。

启用登录审核和告警。开启安全日志中的登录成功和失败事件记录,对异常登录行为设置告警,比如非工作时间登录、多次失败后成功登录、从异常IP登录等。

强制密码策略。确保所有账号都有密码过期策略,服务账号使用足够复杂的密码,并定期轮换。密码永不过期的账号要单独审批和记录。

清理过程中容易忽略的角落

除了常规的用户账号,Windows服务器上还有一些容易被忽略的账号类型。比如IIS应用程序池标识、SQL Server登录账号、任务计划中保存的凭据、服务主体名称关联的账号等。这些账号可能不属于常规的本地用户或域用户列表,但同样可能成为攻击入口。

IIS应用程序池如果使用自定义账号运行,需要检查该账号是否还有效。SQL Server的登录账号可能独立于Windows账号体系,需要单独审查。计划任务中如果保存了密码,账号被删除后任务会失败,所以删除前要检查计划任务的运行账户。

另外,本地安全策略中的“拒绝本地登录”“拒绝从网络访问此计算机”等策略里可能引用了特定账号或组,删除账号后这些策略会残留无效SID,虽然不影响安全,但审计时会显得混乱。建议定期清理策略中的无效SID。

清理后的验证和加固

删除或禁用账号后,要验证操作是否生效。检查账号是否还在组里、是否还能登录、相关服务是否正常。对于域账号,确认所有域控都已同步变更。对于本地账号,确认所有需要该账号的服务器都已处理。

清理完成后,建议做一次全面的权限审计,检查剩余账号的组成员关系,移除不必要的管理员权限。同时检查共享文件夹权限、注册表权限、文件系统权限中是否还残留已删除账号的SID,这些残留SID虽然不会直接导致入侵,但会让权限管理变得混乱,也说明之前的权限分配不够规范。

Windows服务器的安全加固是一个持续过程,闲置账号清理只是其中一环。把账号管理做扎实,能直接减少攻击面,让攻击者少很多可乘之机。与其等入侵发生后追查某个幽灵账号的登录记录,不如定期花点时间把账号列表理清楚。