?0x01? ??設置5次失敗后鎖定賬戶30分鐘
secpol.msc
# 導航到: 安全設置 > 賬戶策略 > 賬戶鎖定策略
0x02? ? ?復制保存到? BlockFailedRDP.ps1
<#
.DESCRIPTION
此腳本分析Windows安全日志中的RDP登錄失敗事件(ID 4625),
統計每個IP的失敗次數,對達到閾值的IP自動創建防火墻阻止規則。.VERSION
1.2
#># 設置正確的編碼環境(UTF-8)
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$OutputEncoding = [System.Text.Encoding]::UTF8# 配置參數
$config = @{LogName = "Security"EventID = 4625TimeRangeDays = 1BlockThreshold = 5MaxEvents = 5000Whitelist = @("192.168.1.100", "10.0.0.1", "127.0.0.1") # 信任IP列表RulePrefix = "AutoBlockRDP" # 防火墻規則前綴LogFile = "D:\SecurityScripts\Logs\RDP_Protection.log" # 日志文件路徑
}# 創建日志目錄
if (-not (Test-Path (Split-Path $config.LogFile -Parent))) {New-Item -ItemType Directory -Path (Split-Path $config.LogFile -Parent) -Force | Out-Null
}# 記錄日志函數
function Write-Log {param([string]$Message,[ValidateSet("INFO","WARNING","ERROR")][string]$Level = "INFO")$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"$logEntry = "[$timestamp][$Level] $Message"Add-Content -Path $config.LogFile -Value $logEntry -Encoding UTF8if ($Level -eq "ERROR") { Write-Error $Message }elseif ($Level -eq "WARNING") { Write-Warning $Message }else { Write-Output $Message }
}# 主程序
try {# 1. 收集日志數據$startTime = (Get-Date).AddDays(-$config.TimeRangeDays)$endTime = Get-DateWrite-Log " "Write-Log "開始分析RDP登錄失敗日志 ($startTime 至 $endTime)"$filter = @{LogName = $config.LogNameID = $config.EventIDStartTime = $startTimeEndTime = $endTime}$events = Get-WinEvent -FilterHashtable $filter -MaxEvents $config.MaxEvents -Oldest -ErrorAction Stop# 2. 統計IP失敗次數$ipFailCount = @{}$totalEvents = 0foreach ($event in $events) {$totalEvents++if ($event.Message -match "(?<IP>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(?::\d{1,5})?") {$ip = $matches.IPif ($config.Whitelist -notcontains $ip) {$ipFailCount[$ip] = ($ipFailCount[$ip] + 1)}}}Write-Log "共分析 $totalEvents 條日志記錄,發現 $($ipFailCount.Count) 個唯一IP地址"Write-Log "======================================================================"Write-Log " "# 3. 處理惡意IP$blockedIPs = 0$skippedIPs = 0foreach ($ip in $ipFailCount.Keys) {$failCount = $ipFailCount[$ip]if ($failCount -ge $config.BlockThreshold) {$ruleName = "$($config.RulePrefix)_$ip"# 檢查是否已存在規則if (-not (Get-NetFirewallRule -DisplayName $ruleName -ErrorAction SilentlyContinue)) {try {New-NetFirewallRule -DisplayName $ruleName `-Direction Inbound `-Action Block `-RemoteAddress $ip `-Description "自動阻止于 $(Get-Date -Format 'yyyy-MM-dd'), 失敗次數: $failCount" `-ErrorAction StopWrite-Log "已創建防火墻規則阻止IP: $ip (失敗次數: $failCount)"$blockedIPs++}catch {Write-Log "創建防火墻規則失敗 ($ip): $_" -Level "ERROR"}}else {Write-Log "IP $ip 已在阻止列表中 (失敗次數: $failCount)"$skippedIPs++}}else {Write-Log "IP $ip 未達阻止閾值 (失敗次數: $failCount)"}}# 4. 生成報告Write-Log " "$report = @"===== RDP防護報告 =====
分析時間范圍: $($startTime.ToString('yyyy-MM-dd HH:mm')) 至 $($endTime.ToString('yyyy-MM-dd HH:mm'))
分析日志條目: $totalEvents
檢測到的唯一IP: $($ipFailCount.Count)
達到閾值的IP: $($ipFailCount.Values.Where({$_ -ge $config.BlockThreshold}).Count)
新增阻止的IP: $blockedIPs
已有規則的IP: $skippedIPs
"@Write-Log $report# 5. 清理舊規則(可選)# Get-NetFirewallRule | Where { $_.DisplayName -like "$($config.RulePrefix)*" -and $_.CreationTime -lt (Get-Date).AddDays(-30) } | Remove-NetFirewallRule}
catch {Write-Log "腳本執行出錯: $_" -Level "ERROR"exit 1
}exit 0
0x03? ? 使用PowerShell執行腳本:
.\BlockFailedRDP.ps1
0x04? ? 設置定時任務?
# 創建任務觸發器(每15分鐘運行一次)
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) `-RepetitionInterval (New-TimeSpan -Minutes 15) `-RepetitionDuration ([TimeSpan]::MaxValue)# 創建任務動作
$action = New-ScheduledTaskAction `-Execute "powershell.exe" `-Argument "-ExecutionPolicy Bypass -File `"D:\SecurityScripts\BlockFailedRDP.ps1`""# 注冊計劃任務
Register-ScheduledTask `-TaskName "RDP防護" `-Trigger $trigger `-Action $action `-RunLevel Highest `-User "SYSTEM" # 使用SYSTEM賬戶運行,如果報錯,改成當前使用的賬戶# 查看任務是否添加成功
PS C:\Windows\system32> Get-ScheduledTask -TaskName "RDP防護"TaskPath TaskName State
-------- -------- -----
\ RDP防護 Ready
0x05? ??如果提示系統禁止運行腳本:
# 以管理員身份打開PowerShell
Set-ExecutionPolicy RemoteSigned -Scope Process -Force# 測試運行(不會實際修改防火墻)
cd C:\SecurityScripts
.\BlockFailedRDP.ps1 -WhatIf
? ? 如果遇到中文亂碼,使用PowerShell命令轉換編碼,或者用vscode轉碼。
# 將文件轉換為UTF-8 with BOM編碼
$content = Get-Content -Path "D:\SecurityScripts\BlockFailedRDP.ps1" -Raw
Set-Content -Path "D:\SecurityScripts\BlockFailedRDP.ps1" -Value $content -Encoding UTF8
? ? 其他幾種檢查方法:
# 1. 檢查腳本錯誤
$Error[0] | Format-List * -Force# 2. 測試事件日志訪問
Get-WinEvent -LogName Security -MaxEvents 1 -ErrorAction Stop# 3. 檢查防火墻模塊
Get-Module -Name NetSecurity -ListAvailable# 4. 查看最近的4625事件
Get-WinEvent -FilterHashtable @{LogName='Security'; ID=4625} -MaxEvents 5 | Select-Object TimeCreated, Message# 備份規則:定期導出防火墻配置
Export-NetFirewallRule -Path "C:\FirewallBackup\firewall-rules.xml"# 查看所有腳本創建的規則
Get-NetFirewallRule | Where-Object {$_.DisplayName -like "Block IP *"
} | Format-Table DisplayName, Enabled, Direction, Action# 啟用RDP網絡級認證(NLA),設置為1
(Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" -Name "UserAuthentication").UserAuthenticationSet-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" -Name "UserAuthentication" -Value 1# 修改默認RDP端口,修改注冊表
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" -Name "PortNumber" -Value 3390
# 重啟生效
Restart-Service TermService -Force# 限制RDP訪問IP, 創建防火墻規則只允許特定IP訪問
New-NetFirewallRule -DisplayName "允許特定IP訪問RDP" `-Direction Inbound `-Protocol TCP `-LocalPort 3389,3390 `-RemoteAddress 192.168.1.0/24,123.45.67.89 `-Action Allow
0x99? ? 幾種安全措施,根據實際情況選擇:
安全措施 | 作用 | 實施方法 |
---|---|---|
修改端口 | 減少掃描攻擊 | 注冊表 + 防火墻 |
NLA | 防止未授權連接 | 遠程桌面設置 |
IP 白名單 | 限制訪問來源 | 防火墻/安全組 |
MFA | 防止暴力破解 | 微軟 Authenticator |
VPN/RD Gateway | 加密通信 | 企業級部署 |
通過以上方法,可大幅降低 RDP 被攻擊的風險。對于企業用戶,建議結合?RD Gateway(需要Win服務器) + MFA(需微軟賬戶) + IP 白名單?提供最高級別的保護。
如果還是報錯(允許腳本本地運行):
????????
PS D:\SecurityScripts> Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned -ForcePS D:\SecurityScripts> Get-ExecutionPolicy -ListScope ExecutionPolicy----- ---------------
MachinePolicy UndefinedUserPolicy UndefinedProcess UndefinedCurrentUser RemoteSignedLocalMachine Undefined
????????
也可以給腳本進行數字簽名(自簽也可以)
呦,發現github有現成的了?
https://gist.github.com/example/secure-rdp-script?