RDP暴力破解与未授权访问
前置说明
RDP(Remote Desktop Protocol,远程桌面协议)是 Windows 环境中最常被攻击的远程访问服务
相当于 Linux 世界的 SSH,是攻击者获取初始访问的首选目标
本页覆盖:暴力破解检测、未授权访问取证、RDP 位图缓存取证、防护加固
关联页面:03-事件日志分析 | 04-取证制品分析 | 10-SSH暴力破解与未授权访问
一、RDP 攻击面概述
1.1 RDP 基本架构
默认端口:TCP 3389(很多管理员会改端口,但 Shodan/Censys 可轻松扫出)
协议层次:
RDP → TPKT → X.224 → MCS → 加密层(TLS/CredSSP/RDP Security)
Windows 默认组件:
TermService(Terminal Services)服务
svchost.exe -k NetworkService 或 svchost.exe -k termsvcs
确认 RDP 服务状态:
1 2 3 4 5 6 7 8 9 10 11 12 13
| Get-Service -Name TermService | Select-Object Status, StartType
Get-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server' -Name fDenyTSConnections
Get-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name PortNumber
Get-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name UserAuthentication
|
1.2 NLA(Network Level Authentication)对攻击的影响
NLA 启用时(推荐配置):
认证在 RDP 会话建立之前完成(CredSSP 协议)
暴力破解产生 Event ID 4625 失败日志,但 不会 产生 TerminalServices 1149 事件
攻击者无法看到登录界面就被拒绝
资源消耗小,服务器不会因暴力破解导致 GUI 资源耗尽
NLA 禁用时(危险配置):
攻击者先建立 RDP 会话,然后在 Windows 登录界面输入凭据
每次尝试都建立完整 RDP 会话,产生 TerminalServices 1149 事件
服务器资源消耗大,可能导致拒绝服务
攻击者可以看到操作系统版本等信息
关键区别对照:
1 2
| NLA 启用: Client → CredSSP Auth → [成功才建立会话] NLA 禁用: Client → RDP Session → [登录界面认证]
|
检测 NLA 状态:
1 2 3 4 5 6 7 8
| (Get-ItemProperty 'HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp').UserAuthentication
(Get-WmiObject -Class Win32_TSGeneralSetting -Namespace root\cimv2\terminalservices).UserAuthenticationRequired
|
1.3 常见 RDP 攻击场景
场景一:互联网暴力破解
RDP 直接暴露在公网(最常见也最危险)
攻击者使用 Hydra/Crowbar/NLBrute 等工具
通常在数小时到数天内完成,取决于密码复杂度
场景二:内网横向移动
攻击者已获取某台主机权限,使用窃取的凭据 RDP 到其他主机
使用 Pass-the-Hash 或 Restricted Admin 模式
详见 15-横向移动检测
场景三:RDP 劫持(Session Hijack)
利用 tscon.exe 劫持断开的 RDP 会话
需要 SYSTEM 权限:tscon <SessionID> /dest:console
无需知道目标用户密码
场景四:BlueKeep/CVE-2019-0708 类漏洞利用
预认证远程代码执行
不需要任何凭据
影响 Windows 7/2008 R2 及更早版本
二、RDP 相关事件日志详解
2.1 Security Log — 登录事件
Event ID 4624(成功登录)— Logon Type 10
RDP 成功登录的核心标识是 Logon Type 10(RemoteInteractive)
关键字段:
1 2 3 4 5 6 7 8 9
| EventID: 4624 LogonType: 10 (RemoteInteractive) TargetUserName: 登录的用户名 TargetDomainName: 域名或计算机名 IpAddress: 源 IP 地址(关键!) IpPort: 源端口 LogonProcessName: User32 AuthenticationPackageName: Negotiate WorkstationName: 源主机名(可能为空)
|
查询命令:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| Get-WinEvent -FilterHashtable @{ LogName='Security' Id=4624 } | Where-Object { $_.Properties[8].Value -eq 10 } | ForEach-Object { [PSCustomObject]@{ Time = $_.TimeCreated User = $_.Properties[5].Value Domain = $_.Properties[6].Value SourceIP = $_.Properties[18].Value SourcePort = $_.Properties[19].Value LogonID = $_.Properties[7].Value } } | Format-Table -AutoSize
|
注意: RDP 重连(断开后重新连接)可能产生 Logon Type 7(Unlock)而非 Type 10
Event ID 4625(登录失败)— 暴力破解检测核心
RDP 暴力破解最直接的证据
关键字段:
1 2 3 4 5 6 7
| EventID: 4625 LogonType: 10 (RemoteInteractive) 或 3 (Network,NLA场景) TargetUserName: 尝试的用户名 Status: 失败状态码 SubStatus: 失败子状态码 IpAddress: 攻击者 IP FailureReason: 失败原因描述
|
Status/SubStatus 常见组合:
1 2 3 4 5 6 7 8 9 10
| 0xC000006D / 0xC000006A → 密码错误(最常见的暴力破解特征) 0xC000006D / 0xC0000064 → 用户名不存在 0xC000006E / 0xC000006A → 账户限制 + 密码错误 0xC0000234 / 0x00000000 → 账户被锁定 0xC0000072 / 0x00000000 → 账户被禁用 0xC000006F / 0x00000000 → 登录时间限制外 0xC0000070 / 0x00000000 → 工作站限制 0xC0000193 / 0x00000000 → 账户过期 0xC0000071 / 0x00000000 → 密码过期 0xC000015B / 0x00000000 → 未授予登录类型权限
|
暴力破解检测查询:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Get-WinEvent -FilterHashtable @{ LogName='Security' Id=4625 } -MaxEvents 50000 | ForEach-Object { [PSCustomObject]@{ Time = $_.TimeCreated User = $_.Properties[5].Value SourceIP = $_.Properties[19].Value Status = '0x{0:X8}' -f [int]$_.Properties[7].Value SubStatus= '0x{0:X8}' -f [int]$_.Properties[9].Value } } | Group-Object SourceIP | Sort-Object Count -Descending | Select-Object Count, Name, @{N='Users';E={($_.Group.User | Sort-Object -Unique) -join ','}} | Format-Table -AutoSize
|
暴力破解判断标准(经验值):
同一源 IP 在 1 小时内 > 50 次 4625 → 高度疑似暴力破解
同一源 IP 尝试多个不同用户名 → 字典攻击/密码喷洒
同一用户名来自多个 IP → 分布式暴力破解
Event ID 4648(显式凭据登录)
当使用 mstsc /v:target 并手动输入不同于当前会话的凭据时产生
说明有人在使用 非当前登录用户 的凭据进行 RDP 连接
可用于检测凭据盗用后的横向移动
1 2 3 4 5 6 7 8
| Get-WinEvent -FilterHashtable @{LogName='Security';Id=4648} | Where-Object { $_.Properties[8].Value -like '*termsrv*' -or $_.Properties[11].Value -ne '-' } | Select-Object TimeCreated, @{N='SubjectUser';E={$_.Properties[1].Value}}, @{N='TargetUser';E={$_.Properties[5].Value}}, @{N='TargetServer';E={$_.Properties[8].Value}}, @{N='TargetIP';E={$_.Properties[12].Value}} | Format-Table -AutoSize
|
2.2 TerminalServices 日志(RDP 专用)
Event ID 1149 — RDP 连接认证成功
日志通道:Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational
仅在 NLA 禁用时记录每次连接尝试,NLA 启用时仅记录成功连接
关键字段:
1 2
| User: 域\用户名 Source Network Address: 源 IP
|
查询命令:
1 2 3 4 5 6 7 8 9 10 11
| Get-WinEvent -LogName 'Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational' | Where-Object { $_.Id -eq 1149 } | ForEach-Object { $xml = [xml]$_.ToXml() [PSCustomObject]@{ Time = $_.TimeCreated User = $xml.Event.UserData.EventXML.Param1 Domain = $xml.Event.UserData.EventXML.Param2 SourceIP = $xml.Event.UserData.EventXML.Param3 } } | Format-Table -AutoSize
|
Event ID 21 — RDP 登录成功(会话创建)
日志通道:Microsoft-Windows-TerminalServices-LocalSessionManager/Operational
表示 RDP 会话已成功创建
关键字段:User、Session ID、Source Network Address
1 2 3 4 5 6 7 8 9 10
| Get-WinEvent -LogName 'Microsoft-Windows-TerminalServices-LocalSessionManager/Operational' | Where-Object { $_.Id -eq 21 } | ForEach-Object { [PSCustomObject]@{ Time = $_.TimeCreated User = $_.Properties[0].Value SessionID = $_.Properties[1].Value SourceIP = $_.Properties[2].Value } } | Format-Table -AutoSize
|
Event ID 22 — RDP Shell 启动(桌面就绪)
表示 RDP 用户的桌面(explorer.exe shell)已经启动
时间比 Event 21 稍晚,确认用户已到达桌面
Event ID 23 — RDP 用户注销
用户正常注销(而非断开连接)
Event ID 24 — RDP 会话断开
用户断开 RDP 连接(关闭窗口/网络中断),但会话可能仍然活跃
注意: 断开 ≠ 注销,断开的会话可以被重连或劫持
Event ID 25 — RDP 重连成功
用户重新连接到之前断开的会话
如果非原始用户重连,可能是会话劫持
TerminalServices 事件时间线汇总
1 2 3 4 5 6 7 8 9 10 11
| 正常 RDP 会话生命周期: 1149 (RemoteConnectionManager) → 认证成功 21 (LocalSessionManager) → 会话创建 22 (LocalSessionManager) → Shell 启动 ...用户操作... 24 (LocalSessionManager) → 会话断开 或 23 (LocalSessionManager) → 用户注销
会话重连: 25 (LocalSessionManager) → 重新连接
|
完整时间线查询:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| $rdpEvents = @()
$rdpEvents += Get-WinEvent -LogName 'Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational' -MaxEvents 500 | Where-Object { $_.Id -eq 1149 } | Select-Object TimeCreated, Id, @{N='Detail';E={"[认证成功] User=$($_.Properties[0].Value) IP=$($_.Properties[2].Value)"}}
$rdpEvents += Get-WinEvent -LogName 'Microsoft-Windows-TerminalServices-LocalSessionManager/Operational' -MaxEvents 500 | Where-Object { $_.Id -in 21,22,23,24,25 } | Select-Object TimeCreated, Id, @{N='Detail';E={ $action = switch($_.Id) { 21 {"会话创建"} 22 {"Shell启动"} 23 {"注销"} 24 {"断开"} 25 {"重连"} } "[$action] User=$($_.Properties[0].Value) Session=$($_.Properties[1].Value) IP=$($_.Properties[2].Value)" }}
$rdpEvents | Sort-Object TimeCreated -Descending | Select-Object -First 100 | Format-Table -AutoSize
|
2.3 安全日志中其他 RDP 相关事件
| Event ID |
描述 |
IR 用途 |
| 4624 Type 10 |
RDP 成功登录 |
确认 RDP 登入 |
| 4625 Type 10/3 |
RDP 登录失败 |
暴力破解检测 |
| 4634/4647 |
注销 |
会话结束时间 |
| 4648 |
显式凭据登录 |
凭据盗用检测 |
| 4778 |
会话重连 |
包含源IP和主机名 |
| 4779 |
会话断开 |
包含源IP和主机名 |
4778/4779 特别重要 — 包含客户端名称(ClientName)和客户端地址(ClientAddress),即使 4624 中 IP 字段为空也可能在这里找到源信息
1 2 3 4 5 6 7 8 9 10 11 12 13
| Get-WinEvent -FilterHashtable @{LogName='Security';Id=4778,4779} -MaxEvents 200 | ForEach-Object { [PSCustomObject]@{ Time = $_.TimeCreated EventID = $_.Id Action = if($_.Id -eq 4778){'重连'}else{'断开'} User = $_.Properties[0].Value SessionName= $_.Properties[1].Value ClientName = $_.Properties[4].Value ClientIP = $_.Properties[5].Value } } | Format-Table -AutoSize
|
三、RDP Bitmap Cache 取证
3.1 什么是 RDP Bitmap Cache
RDP 协议会在客户端缓存远程桌面的图像碎片(bitmap tiles),用于减少网络传输
关键: 缓存存储在 客户端 而非服务器端
这意味着如果攻击者从某台机器 RDP 到目标,攻击者的机器上会留下目标桌面的图像碎片
缓存位置:
1 2 3 4 5 6 7
| %USERPROFILE%\AppData\Local\Microsoft\Terminal Server Client\Cache\ ├── bcache22.bmc ├── bcache24.bmc └── Cache0000.bin Cache0001.bin Cache0002.bin ...
|
3.2 提取和分析 Bitmap Cache
工具一:bmc-tools(ANSSI 开发,推荐)
1 2 3 4 5
| :: 提取 bitmap cache 为独立图片 python bmc-tools.py -s "C:\Users\attacker\AppData\Local\Microsoft\Terminal Server Client\Cache" -d C:\output\bitmap_cache
:: 生成拼接后的大图(collage 模式) python bmc-tools.py -s "C:\Users\attacker\AppData\Local\Microsoft\Terminal Server Client\Cache" -d C:\output -b
|
工具二:RdpCacheStitcher(GUI 拼接工具)
将 bmc-tools 提取的碎片导入
手动/半自动拼接还原完整屏幕截图
可以还原攻击者在远程桌面上看到的内容
取证价值:
可以看到攻击者通过 RDP 访问了什么内容
可能包含:打开的文件、命令行窗口、浏览器页面、敏感数据
即使攻击者清理了日志,bitmap cache 往往被遗忘
3.3 RDP 连接历史(注册表)
客户端连接历史(攻击者机器上):
1 2 3 4 5 6 7 8 9 10 11 12
| Get-ChildItem 'HKCU:\Software\Microsoft\Terminal Server Client\Servers' | ForEach-Object { [PSCustomObject]@{ Server = $_.PSChildName Username = (Get-ItemProperty $_.PSPath).UsernameHint } } | Format-Table -AutoSize
Get-ItemProperty 'HKCU:\Software\Microsoft\Terminal Server Client\Default' | Select-Object MRU*
|
服务器端(被连接的机器上):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
Get-WmiObject Win32_UserProfile | ForEach-Object { $sid = $_.SID $path = $_.LocalPath try { $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteSubKey('Users') $userKey = $reg.OpenSubKey("$sid\Software\Microsoft\Terminal Server Client\Servers") if ($userKey) { $userKey.GetSubKeyNames() | ForEach-Object { Write-Output "User: $path → Connected to: $_" } } } catch {} }
|
四、RDP 暴力破解完整案例分析
4.1 场景还原
背景: 某企业 Windows Server 2019 服务器,RDP 端口 3389 直接暴露在公网
发现: 管理员发现服务器运行异常缓慢,CPU 持续 100%
初步判断: 疑似被入侵
4.2 第一步:检查登录失败事件
1 2 3 4 5 6 7 8 9 10 11 12 13
| $startTime = (Get-Date).AddHours(-24) Get-WinEvent -FilterHashtable @{ LogName='Security' Id=4625 StartTime=$startTime } | Group-Object @{E={$_.Properties[19].Value}} | Sort-Object Count -Descending | Select-Object -First 20 Count, @{N='SourceIP';E={$_.Name}}, @{N='FirstAttempt';E={($_.Group | Sort-Object TimeCreated | Select-Object -First 1).TimeCreated}}, @{N='LastAttempt';E={($_.Group | Sort-Object TimeCreated -Descending | Select-Object -First 1).TimeCreated}}, @{N='Users';E={($_.Group | ForEach-Object {$_.Properties[5].Value} | Sort-Object -Unique | Select-Object -First 5) -join ','}} | Format-Table -AutoSize
|
预期输出示例:
1 2 3 4 5
| Count SourceIP FirstAttempt LastAttempt Users ----- -------- ------------ ----------- ----- 15847 185.xxx.xxx.12 2026-03-31 02:15:33 2026-04-01 18:22:41 Administrator,admin,test,user 8234 91.xxx.xxx.45 2026-03-31 08:44:12 2026-04-01 16:33:22 administrator,admin,guest 3421 103.xxx.xxx.78 2026-04-01 00:12:55 2026-04-01 14:55:33 Administrator,sa,root
|
分析: 明显的暴力破解特征 — 大量失败、多用户名尝试、持续时间长
4.3 第二步:确认是否有成功登录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| $bruteForceIPs = @('185.xxx.xxx.12', '91.xxx.xxx.45', '103.xxx.xxx.78')
Get-WinEvent -FilterHashtable @{ LogName='Security' Id=4624 } -MaxEvents 50000 | Where-Object { $_.Properties[8].Value -eq 10 -and $_.Properties[18].Value -in $bruteForceIPs } | ForEach-Object { [PSCustomObject]@{ Time = $_.TimeCreated User = $_.Properties[5].Value SourceIP = $_.Properties[18].Value LogonID = $_.Properties[7].Value } } | Format-Table -AutoSize
|
如果发现成功登录,说明攻击者已经突破!必须立即进入后续排查
4.4 第三步:追踪攻击者登录后的行为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| $attackerLogonId = '0x1234ABCD'
Get-WinEvent -FilterHashtable @{LogName='Security';Id=4688} -MaxEvents 100000 | Where-Object { $_.Properties[1].Value -eq $attackerLogonId } | ForEach-Object { [PSCustomObject]@{ Time = $_.TimeCreated Process = $_.Properties[5].Value CmdLine = $_.Properties[8].Value Parent = $_.Properties[13].Value } } | Format-Table -AutoSize
Get-WinEvent -FilterHashtable @{LogName='Security';Id=4672} -MaxEvents 10000 | Where-Object { $_.Properties[1].Value -eq $attackerLogonId } | Select-Object TimeCreated, @{N='User';E={$_.Properties[0].Value}} | Format-Table -AutoSize
|
4.5 第四步:检查 TerminalServices 日志交叉验证
1 2 3 4 5 6 7 8 9 10 11 12 13
| Get-WinEvent -LogName 'Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational' | Where-Object { $_.Id -eq 1149 } | ForEach-Object { $xml = [xml]$_.ToXml() [PSCustomObject]@{ Time = $_.TimeCreated User = $xml.Event.UserData.EventXML.Param1 Domain = $xml.Event.UserData.EventXML.Param2 SourceIP = $xml.Event.UserData.EventXML.Param3 } } | Where-Object { $_.SourceIP -in $bruteForceIPs } | Format-Table -AutoSize
|
4.6 第五步:后渗透行为检测
攻击者 RDP 登录成功后常见操作:
1 2 3 4 5 6
| 1. whoami / net user / net localgroup administrators → 信息收集 2. net user hacker P@ssw0rd /add → 创建后门账户 3. net localgroup administrators hacker /add → 提权 4. reg add ... fDenyTSConnections /d 0 → 确保 RDP 持续可用 5. netsh advfirewall set allprofiles state off → 关闭防火墙 6. 下载并执行挖矿/勒索软件 → 最终目的
|
检查后门账户创建:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| Get-WinEvent -FilterHashtable @{LogName='Security';Id=4720} | ForEach-Object { [PSCustomObject]@{ Time = $_.TimeCreated Creator = $_.Properties[4].Value NewAccount = $_.Properties[0].Value } } | Format-Table -AutoSize
Get-WinEvent -FilterHashtable @{LogName='Security';Id=4732} | ForEach-Object { [PSCustomObject]@{ Time = $_.TimeCreated AddedUser = $_.Properties[0].Value GroupName = $_.Properties[2].Value AddedBy = $_.Properties[6].Value } } | Where-Object { $_.GroupName -like '*admin*' } | Format-Table -AutoSize
|
五、RDP 暴力破解防护
5.1 Windows 原生防护
账户锁定策略(Group Policy)
1 2 3 4 5
| 计算机配置 → Windows 设置 → 安全设置 → 账户策略 → 账户锁定策略
账户锁定阈值: 5 次无效登录 账户锁定时间: 30 分钟 重置账户锁定计数器: 30 分钟后
|
PowerShell 配置:
1 2 3 4 5
| net accounts
net accounts /lockoutthreshold:5 /lockoutduration:30 /lockoutwindow:30
|
Windows 防火墙规则限制 RDP 源 IP
1 2 3 4 5
| New-NetFirewallRule -DisplayName "RDP-Allow-Trusted" -Direction Inbound -Protocol TCP -LocalPort 3389 -RemoteAddress 10.0.0.0/8,192.168.1.0/24 -Action Allow
New-NetFirewallRule -DisplayName "RDP-Block-All" -Direction Inbound -Protocol TCP -LocalPort 3389 -Action Block
|
5.2 第三方 Fail2Ban 等效方案
与 Linux 上的 fail2ban 类似,Windows 上有以下方案:
wail2ban(开源,PowerShell 实现)
原理:监控 Security Log 中的 4625 事件,自动创建防火墙规则封禁 IP
GitHub: https://github.com/glasnt/wail2ban
配置要点:
1 2 3 4
| $CHECK_WINDOW = 120 $CHECK_COUNT = 5 $MAX_BANDURATION = 172800
|
RdpGuard(商业软件)
功能类似 fail2ban,但有 GUI 管理界面
支持 RDP、FTP、SMTP 等多种协议
支持白名单和自动解封
IPBan(开源替代)
https://github.com/DigitalRuby/IPBan
跨平台(Windows/Linux),功能最完善的开源方案
安装:
对比 Linux fail2ban:
| 特性 |
Linux fail2ban |
wail2ban |
IPBan |
RdpGuard |
| 开源 |
是 |
是 |
是 |
否 |
| 日志监控 |
文本文件 |
Event Log |
Event Log |
Event Log |
| 封禁方式 |
iptables |
Windows Firewall |
Windows Firewall |
Windows Firewall |
| 配置难度 |
中 |
低 |
低 |
最低 |
| 企业支持 |
社区 |
社区 |
社区 |
商业 |
5.3 纵深防御建议
第一层:网络层
不要将 RDP 直接暴露在公网(最重要的一条)
使用 VPN 或 RD Gateway 作为入口
配置网络级 ACL 限制源 IP
第二层:认证层
启用 NLA(Network Level Authentication)
强制复杂密码策略
启用账户锁定策略
使用多因素认证(MFA)— Azure MFA / DUO 等
第三层:审计层
确保 Security Log 大小足够(建议 ≥ 1GB)
启用审计策略:登录/注销、进程创建、对象访问
将日志转发到 SIEM
第四层:监控层
配置 RDP 登录失败告警
监控非工作时间的 RDP 登录
监控来自异常地理位置的 RDP 连接
第五层:加固层
1 2 3 4 5 6 7 8 9 10
|
Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name PortNumber -Value 33890
reg add "HKLM\System\CurrentControlSet\Control\Lsa" /v DisableRestrictedAdmin /t REG_DWORD /d 0 /f
|
六、RDP 会话劫持检测
6.1 tscon 会话劫持原理
攻击者拥有 SYSTEM 权限后,可以劫持任意已断开的 RDP 会话
不需要知道目标用户的密码
1 2 3 4 5 6 7 8
| :: 攻击方式 :: 1. 列出所有会话 query user
:: 2. 以 SYSTEM 权限执行(例如通过 PsExec 或服务) tscon <TargetSessionID> /dest:console :: 或 tscon <TargetSessionID> /dest:rdp-tcp#<AttackerSessionNumber>
|
6.2 检测方法
检测 tscon.exe 的执行:
1 2 3 4 5 6 7 8 9 10 11
| Get-WinEvent -FilterHashtable @{LogName='Security';Id=4688} -MaxEvents 100000 | Where-Object { $_.Properties[5].Value -like '*tscon*' } | ForEach-Object { [PSCustomObject]@{ Time = $_.TimeCreated Process = $_.Properties[5].Value CmdLine = $_.Properties[8].Value User = $_.Properties[1].Value } } | Format-Table -AutoSize
|
检测创建劫持服务(常见攻击方式):
1 2 3 4 5 6 7 8
|
Get-WinEvent -FilterHashtable @{LogName='System';Id=7045} | Where-Object { $_.Properties[1].Value -like '*tscon*' } | Select-Object TimeCreated, @{N='ServiceName';E={$_.Properties[0].Value}}, @{N='ImagePath';E={$_.Properties[1].Value}} | Format-Table -AutoSize
|
检测异常会话切换:
正常情况下 tscon.exe 很少被使用
任何 tscon.exe 的执行都应该触发告警
七、自动化排查脚本
7.1 一键 RDP 安全审计脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| Write-Host "===== RDP 安全审计 =====" -ForegroundColor Cyan
Write-Host "`n[1] RDP 配置状态" -ForegroundColor Yellow $rdpEnabled = (Get-ItemProperty 'HKLM:\System\CurrentControlSet\Control\Terminal Server').fDenyTSConnections $nlaEnabled = (Get-ItemProperty 'HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp').UserAuthentication $rdpPort = (Get-ItemProperty 'HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp').PortNumber Write-Host " RDP 启用: $(if($rdpEnabled -eq 0){'是 [!]'}else{'否'})" Write-Host " NLA 启用: $(if($nlaEnabled -eq 1){'是 [OK]'}else{'否 [!]'})" Write-Host " RDP 端口: $rdpPort"
Write-Host "`n[2] 当前 RDP 会话" -ForegroundColor Yellow query user 2>$null
Write-Host "`n[3] 最近24h RDP登录失败 Top 10" -ForegroundColor Yellow try { Get-WinEvent -FilterHashtable @{LogName='Security';Id=4625;StartTime=(Get-Date).AddHours(-24)} -ErrorAction SilentlyContinue | ForEach-Object { $_.Properties[19].Value } | Where-Object { $_ -and $_ -ne '-' } | Group-Object | Sort-Object Count -Descending | Select-Object -First 10 Count, Name | Format-Table -AutoSize } catch { Write-Host " 无登录失败记录或日志不可用" }
Write-Host "`n[4] 最近 RDP 成功登录 Top 20" -ForegroundColor Yellow try { Get-WinEvent -FilterHashtable @{LogName='Security';Id=4624} -MaxEvents 50000 -ErrorAction SilentlyContinue | Where-Object { $_.Properties[8].Value -eq 10 } | Select-Object -First 20 TimeCreated, @{N='User';E={$_.Properties[5].Value}}, @{N='SourceIP';E={$_.Properties[18].Value}} | Format-Table -AutoSize } catch { Write-Host " 无法读取安全日志" }
Write-Host "`n[5] 账户锁定策略" -ForegroundColor Yellow net accounts 2>$null | Select-String "Lockout"
Write-Host "`n===== 审计完成 =====" -ForegroundColor Cyan
|
八、与 Linux SSH 暴力破解对比
| 维度 |
Windows RDP |
Linux SSH |
| 默认端口 |
3389 |
22 |
| 日志位置 |
Security.evtx + TerminalServices |
/var/log/auth.log |
| 失败事件 |
Event ID 4625 |
“Failed password” |
| 成功事件 |
Event ID 4624 Type 10 |
“Accepted password/publickey” |
| 防暴力破解 |
wail2ban/IPBan/RdpGuard |
fail2ban |
| 认证方式 |
NTLM/Kerberos/CredSSP |
密码/密钥/证书 |
| 会话缓存 |
Bitmap Cache(取证金矿) |
~/.bash_history |
| 会话劫持 |
tscon.exe |
screen/tmux attach |
| NLA 等效 |
NLA |
无直接等效 |
详见 10-SSH暴力破解与未授权访问 了解 Linux 侧的对应内容
九、关键检查清单(Checklist)
事件收集:
[ ] Security Log — 4624 Type 10, 4625, 4648, 4778, 4779
[ ] TerminalServices-RemoteConnectionManager — 1149
[ ] TerminalServices-LocalSessionManager — 21, 22, 23, 24, 25
[ ] System Log — 7045(服务安装,检测 tscon 劫持)
暴力破解确认:
[ ] 统计 4625 按源 IP 分组的数量和时间分布
[ ] 检查是否有成功登录(4624 Type 10)来自暴力破解 IP
[ ] 确认攻击时间窗口
后渗透排查:
[ ] 新建用户账户(4720)
[ ] 组成员变更(4732)
[ ] 进程执行记录(4688)
[ ] RDP Bitmap Cache 分析
[ ] 注册表 RDP 连接历史
防护确认:
[ ] NLA 是否启用
[ ] 账户锁定策略是否配置
[ ] 防火墙规则是否限制 RDP 源 IP
[ ] RDP 是否暴露在公网