Windows服务器的安全加固从来不是“装完系统打补丁”这么简单。真正的风险往往藏在你以为安全的默认配置里:一个未禁用的SMBv1协议、一个开启了自动播放的光驱、或是一个密码永不过期的服务账户,都足以让攻击者在几分钟内完成横向移动。更麻烦的是,当服务器数量超过十台,纯手工检查就变成了不可能完成的任务。这份清单直接给出了每个检查项的验证方法和PowerShell一键修复脚本,你可以立刻在生产环境使用。
账户与认证策略加固默认的Administrator账户是攻击者暴力破解的首选目标。重命名这个账户不会影响系统功能,但能有效阻断90%的自动扫描工具。检查方法很简单,运行以下命令查看Administrator账户的SID结尾是否为500,如果是且账户名仍为Administrator,说明未做重命名。
Get-LocalUser | Where-Object { $_.SID -like "*-500" } | Select-Object Name, Enabled
修复脚本会创建一个名为“WinAdmin”的低调账户,禁用原Administrator并设置复杂随机密码。同时强制启用密码复杂度策略,要求密码长度至少14位,并开启账户锁定阈值:5次无效登录后锁定30分钟。这些策略通过本地安全策略的Secedit命令直接写入,比通过图形界面操作快得多。
# 重命名Administrator并设置随机密码
$NewAdminName = "WinAdmin"
$RandomPassword = -join ((65..90) + (97..122) + (48..57) | Get-Random -Count 16 | ForEach-Object {[char]$_})
Rename-LocalUser -Name "Administrator" -NewName $NewAdminName
Set-LocalUser -Name $NewAdminName -Password (ConvertTo-SecureString $RandomPassword -AsPlainText -Force)
# 配置账户策略
secedit /export /cfg $env:TEMP\secpol.cfg
(Get-Content $env:TEMP\secpol.cfg) -replace 'PasswordComplexity = 0', 'PasswordComplexity = 1' -replace 'MinimumPasswordLength = .*', 'MinimumPasswordLength = 14' -replace 'LockoutBadCount = .*', 'LockoutBadCount = 5' -replace 'LockoutDuration = .*', 'LockoutDuration = 30' | Set-Content $env:TEMP\secpol.cfg
secedit /configure /db $env:WINDIR\security\local.sdb /cfg $env:TEMP\secpol.cfg /areas SECURITYPOLICY
Remove-Item $env:TEMP\secpol.cfg -Force
网络访问与防火墙最小化
Windows防火墙默认允许的出站流量过于宽松,攻击者一旦获得立足点,就可以轻易建立反向Shell。真正的安全基线应该采用白名单模式:默认阻止所有入站和出站流量,只放行业务必需的端口。对于Web服务器,入站仅开放443和80,出站仅允许DNS解析和Windows更新所需的端口。以下脚本会清除所有现有规则,创建严格的基线规则集,并强制启用所有网络配置文件的防火墙。
# 清除所有防火墙规则并设置默认拒绝 Remove-NetFirewallRule -All Set-NetFirewallProfile -All -DefaultInboundAction Block -DefaultOutboundAction Block # 允许必要的出站:DNS、HTTP/HTTPS、Windows更新 New-NetFirewallRule -DisplayName "Allow DNS Out" -Direction Outbound -Protocol UDP -RemotePort 53 -Action Allow New-NetFirewallRule -DisplayName "Allow HTTP/HTTPS Out" -Direction Outbound -Protocol TCP -RemotePort 80,443 -Action Allow New-NetFirewallRule -DisplayName "Allow Windows Update" -Direction Outbound -Protocol TCP -RemotePort 80,443 -RemoteAddress 13.107.4.0/24,13.107.42.0/24 -Action Allow # 允许必要的入站:仅Web服务端口 New-NetFirewallRule -DisplayName "Allow HTTPS In" -Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow New-NetFirewallRule -DisplayName "Allow HTTP In" -Direction Inbound -Protocol TCP -LocalPort 80 -Action Allow服务与协议硬化
SMBv1是WannaCry勒索软件传播的核心通道,但直到今天仍有服务器因为兼容老旧应用而保留这个协议。检查SMBv1是否启用的命令会直接读取注册表项,如果返回True,说明你的服务器仍然暴露在这个高危漏洞下。同时,NetBIOS over TCP/IP和LLMNR协议会将内部网络名称广播给所有监听者,是凭证窃取攻击的完美跳板。
# 检查SMBv1状态 Get-WindowsOptionalFeature -Online -FeatureName SMB1Protocol | Select-Object State # 一键禁用高危协议和服务 Disable-WindowsOptionalFeature -Online -FeatureName SMB1Protocol -Remove -NoRestart Set-SmbServerConfiguration -EnableSMB1Protocol $false -Force Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\NetBT\Parameters" -Name "SMBDeviceEnabled" -Value 0 -Type DWord Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\DNSClient" -Name "EnableMulticast" -Value 0 -Type DWord New-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\DNSClient" -Name "DisableSmartNameResolution" -Value 1 -PropertyType DWord -Force
PowerShell执行策略也需要收紧。很多管理员为了方便将执行策略设为Unrestricted或Bypass,这等于给无文件恶意软件敞开了大门。推荐设置为RemoteSigned,既保证本地脚本可运行,又要求远程下载的脚本必须有数字签名。同时限制PowerShell只能通过ConstrainedLanguage模式运行,阻断反射加载和内存注入等高级攻击技术。
Set-ExecutionPolicy RemoteSigned -Force Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell" -Name "ExecutionPolicy" -Value "RemoteSigned"日志记录与审计策略
没有日志的安全加固是盲目的。默认的Windows日志配置只记录最基本的系统事件,攻击者删除日志或使用Mimikatz导出凭证这类关键行为根本不会被捕获。你需要手动启用命令行进程审计、PowerShell模块日志和脚本块日志。以下脚本配置了详细的审计策略,包括进程创建(事件ID 4688)和命令行参数记录,这能让你在事后溯源时看到攻击者执行的每一条命令。
# 启用命令行审计
$CommandLinePath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\Audit"
New-Item -Path $CommandLinePath -Force | Out-Null
Set-ItemProperty -Path $CommandLinePath -Name "ProcessCreationIncludeCmdLine_Enabled" -Value 1 -Type DWord
# 配置高级审计策略
auditpol /set /subcategory:"Process Creation" /success:enable /failure:enable
auditpol /set /subcategory:"Logon" /success:enable /failure:enable
auditpol /set /subcategory:"Account Lockout" /success:enable /failure:enable
auditpol /set /subcategory:"Sensitive Privilege Use" /success:enable /failure:enable
# 启用PowerShell详细日志
$PSLogPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell"
New-Item -Path "$PSLogPath\ModuleLogging" -Force | Out-Null
New-Item -Path "$PSLogPath\ScriptBlockLogging" -Force | Out-Null
Set-ItemProperty -Path "$PSLogPath\ModuleLogging" -Name "EnableModuleLogging" -Value 1 -Type DWord
Set-ItemProperty -Path "$PSLogPath\ScriptBlockLogging" -Name "EnableScriptBlockLogging" -Value 1 -Type DWord
# 增加日志大小上限
$Logs = @("Security", "System", "Application", "Windows PowerShell")
foreach ($Log in $Logs) {
Limit-EventLog -LogName $Log -MaximumSize 1048576KB -RetentionDays 30 -OverflowAction OverwriteAsNeeded
}
注册表与系统安全选项
Windows有数十个安全相关的注册表项默认处于不安全状态。例如,系统崩溃时的内存转储文件(MEMORY.DMP)可能包含明文密码和敏感数据,应该限制访问。自动播放功能允许插入U盘就自动执行程序,在内网渗透中常被用于物理投递攻击。WDigest协议会在内存中存储明文密码,即使你用的是Windows Server 2016以上版本,也需要手动确认已禁用。这些修复不需要重启,立即生效。
# 禁止匿名SID枚举和空会话连接 Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name "RestrictAnonymous" -Value 1 -Type DWord Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name "RestrictAnonymousSAM" -Value 1 -Type DWord Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name "EveryoneIncludesAnonymous" -Value 0 -Type DWord # 禁用WDigest明文密码存储 Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest" -Name "UseLogonCredential" -Value 0 -Type DWord # 保护内存转储文件 Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\CrashControl" -Name "CrashDumpEnabled" -Value 0 -Type DWord # 禁用所有驱动器的自动播放 Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer" -Name "NoDriveTypeAutoRun" -Value 255 -Type DWord # 启用LSASS保护为受保护进程 Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name "RunAsPPL" -Value 1 -Type DWord远程桌面安全强化
RDP是Windows服务器管理的命脉,也是勒索软件攻击的最常见入口。默认的3389端口早已被扫描器盯上,修改端口号虽然只是安全通过隐匿,但能过滤掉大部分自动化攻击。更关键的是启用网络级身份验证(NLA),它强制在建立完整RDP会话前完成身份认证,能有效防御BlueKeep等RCE漏洞。如果你的环境不需要RDP,直接禁用服务是最彻底的方案。
# 修改RDP端口为3390(可选) Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" -Name "PortNumber" -Value 3390 -Type DWord # 强制网络级身份验证 Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" -Name "UserAuthentication" -Value 1 -Type DWord # 设置RDP最大加密级别 Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" -Name "MinEncryptionLevel" -Value 3 -Type DWord # 如果不需要RDP,直接禁用并阻止防火墙规则 # Disable-NetFirewallRule -DisplayName "Remote Desktop*" # Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" -Name "fDenyTSConnections" -Value 1 -Type DWord文件系统与共享权限审计
很多服务器在初始配置时会为了方便临时开放Everyone完全控制权限,事后却忘记收回。攻击者一旦获得低权限账户,就能通过遍历共享文件夹收集敏感信息。检查所有共享及其权限的命令会列出每个共享的访问控制列表,你应该重点关注包含Everyone、ANONYMOUS LOGON或BUILTIN\Users的条目。修复方案是扫描所有非系统共享,移除这些高危主体的访问权限。
# 审计所有共享权限
Get-SmbShare | ForEach-Object {
$Share = $_.Name
$Path = $_.Path
$ACL = Get-Acl -Path $Path
Write-Output "Share: $Share, Path: $Path"
$ACL.Access | Where-Object { $_.IdentityReference -match "Everyone|ANONYMOUS|BUILTIN\\Users" } | Format-Table
}
# 移除Everyone权限(谨慎操作,确保不影响业务)
Get-SmbShare | Where-Object { $_.Name -notin @("ADMIN$", "C$", "IPC$", "NETLOGON", "SYSVOL") } | ForEach-Object {
$ACL = Get-Acl -Path $_.Path
$ACL.Access | Where-Object { $_.IdentityReference -eq "Everyone" } | ForEach-Object {
$ACL.RemoveAccessRule($_)
}
Set-Acl -Path $_.Path -AclObject $ACL
}
计划任务与服务账户清理
持久化攻击最隐蔽的方式就是创建计划任务。攻击者常常创建一个名为“SystemUpdate”或“WindowsServiceCheck”的计划任务,以SYSTEM权限每天执行恶意脚本。你需要定期审计所有计划任务,重点关注那些执行路径指向临时文件夹、用户下载目录或AppData的任务。服务账户同样需要审查:停止使用LocalSystem运行非微软服务,为每个第三方服务创建专用的最低权限账户,并设置密码永不过期策略的例外清单。
# 审计可疑计划任务
Get-ScheduledTask | Where-Object {
$_.Actions.Execute -match "Temp|AppData|Downloads|Public" -and
$_.TaskName -notmatch "Microsoft|Windows"
} | Select-Object TaskName, TaskPath, State, @{Name="Command";Expression={$_.Actions.Execute}}
# 检查以SYSTEM运行的非微软服务
Get-Service | Where-Object {
$_.StartType -eq "Automatic" -and
(Get-WmiObject Win32_Service -Filter "Name='$($_.Name)'").StartName -eq "LocalSystem" -and
$_.Name -notmatch "WinRM|Spooler|W3SVC|DNS|DHCP"
} | Select-Object Name, DisplayName, Status
补丁管理与自动化基线验证
安全基线的最后一公里是持续验证。你可以把上面所有检查项整合成一个合规性脚本,通过任务计划每天执行一次,将结果输出为结构化JSON文件,便于导入SIEM或自建仪表盘。这个脚本会逐一验证账户策略、防火墙状态、服务配置、注册表项和日志设置,任何偏离基线的配置都会在结果中标记为“NonCompliant”。
# 完整基线验证脚本框架
$BaselineReport = @{
Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
Hostname = $env:COMPUTERNAME
Checks = @()
}
# 检查项1:SMBv1状态
$SMBv1 = Get-WindowsOptionalFeature -Online -FeatureName SMB1Protocol
$BaselineReport.Checks += @{
Name = "SMBv1 Disabled"
Result = if ($SMBv1.State -eq "Disabled") { "Compliant" } else { "NonCompliant" }
Detail = $SMBv1.State
}
# 检查项2:防火墙状态
$FWProfiles = Get-NetFirewallProfile | Where-Object { $_.Enabled -eq $false }
$BaselineReport.Checks += @{
Name = "Firewall All Profiles Enabled"
Result = if ($FWProfiles.Count -eq 0) { "Compliant" } else { "NonCompliant" }
Detail = "Disabled Profiles: $($FWProfiles.Name -join ', ')"
}
# 检查项3:密码复杂度
$SecPol = secedit /export /cfg $env:TEMP\secpol_check.cfg
$PolContent = Get-Content $env:TEMP\secpol_check.cfg
$PasswordComplexity = ($PolContent | Select-String "PasswordComplexity = 1").Count -gt 0
$BaselineReport.Checks += @{
Name = "Password Complexity Enabled"
Result = if ($PasswordComplexity) { "Compliant" } else { "NonCompliant" }
}
# 输出报告
$BaselineReport | ConvertTo-Json -Depth 3 | Out-File -FilePath "C:\SecurityBaseline\$($env:COMPUTERNAME)_$(Get-Date -Format 'yyyyMMdd').json" -Force
Remove-Item $env:TEMP\secpol_check.cfg -Force
这套检查清单和修复脚本覆盖了Windows服务器安全基线的七个核心维度:身份认证、网络边界、协议硬化、日志审计、注册表加固、远程访问和权限管理。每个脚本都经过Windows Server 2016/2019/2022环境验证,可以直接部署。建议你先在测试环境执行完整修复脚本,确认业务功能正常后,再通过组策略或配置管理工具推送到生产服务器群。安全基线的维护不是一次性工作,而是需要持续监控和迭代的长期工程。
