05-账户安全排查 (Account Security Investigation)
账户是攻击者进入系统后的第一个落脚点。无论是新建隐藏账户、提权到管理员、还是通过 RDP 横向移动,都会在账户体系中留下痕迹。作为 Linux IR 背景的工程师,你会发现 Windows 的账户体系远比 /etc/passwd + /etc/shadow 复杂——SAM 数据库、SID 体系、域账户、登录类型(Logon Type)都是 Windows 特有的概念。
前置知识 :01-系统基础与注册表 | 03-事件日志分析
关联章节 :06-进程与网络分析 | 09-注册表持久化审计
Linux 对照 :04-账户安全排查
1. Windows 账户体系基础 1.1 与 Linux 账户体系的对比
特征
Linux
Windows
账户数据库
/etc/passwd + /etc/shadow
SAM (Security Account Manager)
账户标识
UID/GID (数字)
SID (S-1-5-21-…)
管理员
root (UID 0)
Administrator (SID 以 -500 结尾)
用户组
/etc/group
Local Groups / Domain Groups
域账户
LDAP (可选)
Active Directory (NTDS.dit)
密码哈希
/etc/shadow (SHA-512)
SAM/NTDS.dit (NTLM Hash)
远程登录
SSH
RDP / WinRM / PsExec / SMB
1.2 SAM 数据库 SAM 文件位于 C:\Windows\System32\config\SAM
系统运行时被锁定,无法直接复制
存储本地用户账户的密码哈希(NTLM)
离线提取方法:
1 2 3 4 5 6 7 8 9 10 reg save HKLM\SAM C:\IR\SAM_backup reg save HKLM\SYSTEM C:\IR\SYSTEM_backup vssadmin list shadows
1.3 SID (Security Identifier) 体系 Windows 使用 SID 而非数字 UID 来标识账户
SID 格式 :S-1-5-21-<域标识>-<RID>
常见 Well-Known SID :
SID
对应账户/组
S-1-5-18
LOCAL SYSTEM
S-1-5-19
LOCAL SERVICE
S-1-5-20
NETWORK SERVICE
S-1-5-21-…-500
Administrator
S-1-5-21-…-501
Guest
S-1-5-21-…-502
krbtgt (域)
S-1-5-21-…-512
Domain Admins
S-1-5-21-…-544
Administrators (内置组)
查看 SID 的方法 :
1 2 3 4 5 6 7 8 9 10 11 12 13 whoami /user wmic useraccount get name,sid Get-LocalUser | Select-Object Name, SID, Enabled, LastLogon$objSID = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-21-xxx-500" )$objUser = $objSID .Translate([System.Security.Principal.NTAccount ])$objUser .Value
2. 本地用户枚举 2.1 基础枚举命令 CMD 方式 :
1 2 3 4 5 6 7 8 9 10 11 :: 列出所有本地用户 net user:: 查看单个用户详细信息 net user Administrator:: 关注字段: :: Account active - 账户是否启用 :: Password last set - 密码上次修改时间 :: Last logon - 上次登录时间 :: Group memberships - 所属组
PowerShell 方式(推荐) :
1 2 3 4 5 6 7 8 9 10 11 12 13 Get-LocalUser | Select-Object Name, Enabled, LastLogon, PasswordLastSet, PasswordRequired, UserMayChangePassword, Description | Format-Table -AutoSize Get-LocalUser | Where-Object { $_ .Enabled -eq $true }Get-LocalUser | Where-Object { $_ .PasswordLastSet -gt (Get-Date ).AddDays(-7 ) } | Select-Object Name, Enabled, PasswordLastSet, Description Get-LocalUser | Where-Object { $_ .LastLogon -eq $null -and $_ .Enabled -eq $true }
WMI 方式 :
1 2 3 4 5 6 7 Get-WmiObject -Class Win32_UserAccount -Filter "LocalAccount=True" | Select-Object Name, SID, Disabled, Lockout, PasswordRequired, PasswordChangeable | Format-Table -AutoSize Get-CimInstance -ClassName Win32_UserAccount -Filter "LocalAccount=True"
2.2 隐藏账户检测 隐藏账户的几种方式 :
方式 1:账户名以 $ 结尾
net user 不会显示以 $ 结尾的账户名
这是最常见的隐藏账户手法
方式 2:修改注册表隐藏
修改 HKLM\SAM\SAM\Domains\Account\Users 下的注册表项
使账户在管理工具和 net user 中不可见
方式 3:克隆管理员账户
将普通用户的 SID 修改为与 Administrator 相同的 RID(500)
登录时获得管理员权限
检测隐藏账户的方法 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 Get-LocalUser | Select-Object Name, Enabled, SIDPsExec.exe -s -i powershell.exe Get-ChildItem "HKLM:\SAM\SAM\Domains\Account\Users\Names" | Select-Object PSChildName $netUsers = (net user | Select-Object -Skip 4 | Select-Object -SkipLast 2 ) -split '\s+' | Where-Object { $_ -ne '' } $regUsers = (Get-ChildItem "HKLM:\SAM\SAM\Domains\Account\Users\Names" ).PSChildNameCompare-Object $netUsers $regUsers Get-WmiObject -Class Win32_UserAccount -Filter "LocalAccount=True" | Group-Object { $_ .SID.Split('-' )[-1 ] } | Where-Object { $_ .Count -gt 1 } | Select-Object -ExpandProperty Group
注册表隐藏账户的深层检测 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 $usersKey = "HKLM:\SAM\SAM\Domains\Account\Users" $names = Get-ChildItem "$usersKey \Names" foreach ($name in $names ) { $username = $name .PSChildName $rid = (Get-ItemProperty $name .PSPath).'(Default)' $ridHex = '{0:X8}' -f $rid Write-Host "User: $username | RID: $rid (0x$ridHex )" }
2.3 事件日志中的账户创建记录 Event ID 4720 :用户账户已创建
Event ID 4722 :用户账户已启用
Event ID 4732 :成员已添加到安全启用的本地组
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 Get-WinEvent -FilterHashtable @ { LogName = 'Security' ID = 4720 } -MaxEvents 50 | ForEach-Object { $xml = [xml ]$_ .ToXml() [PSCustomObject ]@ { TimeCreated = $_ .TimeCreated TargetUserName = $xml .Event.EventData.Data | Where-Object { $_ .Name -eq 'TargetUserName' } | Select-Object -Expand '#text' SubjectUserName = $xml .Event.EventData.Data | Where-Object { $_ .Name -eq 'SubjectUserName' } | Select-Object -Expand '#text' } } | Format-Table -AutoSize Get-WinEvent -FilterHashtable @ { LogName = 'Security' ID = 4732 } -MaxEvents 50 | ForEach-Object { $xml = [xml ]$_ .ToXml() $groupName = ($xml .Event.EventData.Data | Where-Object { $_ .Name -eq 'TargetUserName' }).'#text' $memberName = ($xml .Event.EventData.Data | Where-Object { $_ .Name -eq 'MemberSid' }).'#text' if ($groupName -eq 'Administrators' ) { [PSCustomObject ]@ { TimeCreated = $_ .TimeCreated GroupName = $groupName MemberSid = $memberName } } }
3. 管理员组与特权组审计 3.1 本地管理员组枚举 1 2 3 4 5 6 7 8 :: CMD 方式 net localgroup Administrators:: 其他关键组也要检查 net localgroup "Remote Desktop Users"net localgroup "Remote Management Users"net localgroup "Backup Operators"net localgroup "Hyper-V Administrators"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Get-LocalGroupMember -Group "Administrators" Get-LocalGroup | ForEach-Object { $group = $_ .Name $members = Get-LocalGroupMember -Group $group -ErrorAction SilentlyContinue if ($members ) { foreach ($member in $members ) { [PSCustomObject ]@ { GroupName = $group MemberName = $member .Name ObjectClass = $member .ObjectClass PrincipalSource = $member .PrincipalSource } } } } | Format-Table -AutoSize
3.2 高危特权组清单
组名
风险说明
排查要点
Administrators
完全控制系统
应仅包含必要账户
Remote Desktop Users
允许 RDP 登录
检查是否有异常成员
Remote Management Users
允许 WinRM 远程管理
横向移动常用
Backup Operators
可读取任意文件
可用于导出 SAM/NTDS.dit
Hyper-V Administrators
虚拟化管理
可逃逸到宿主机
Print Operators
加载打印驱动
PrintNightmare 利用
Server Operators
服务器操作
可修改服务配置
Account Operators
账户管理
域环境中可创建账户
DnsAdmins
DNS 管理
可加载任意 DLL
3.3 检查特权令牌 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 whoami /priv secedit /export /cfg C:\IR\secpol.cfg
4. 域用户排查(概述) 4.1 域环境基本信息收集 1 2 3 4 5 6 7 8 9 10 11 12 13 systeminfo | findstr /i "domain" (Get-WmiObject Win32_ComputerSystem).Domain (Get-WmiObject Win32_ComputerSystem).PartOfDomain nltest /dclist: nltest /dsgetdc: nltest /domain_trusts
4.2 域用户基本枚举 1 2 3 4 5 :: CMD 方式 net user /domainnet group "Domain Admins" /domainnet group "Enterprise Admins" /domainnet group "Schema Admins" /domain
1 2 3 4 5 6 7 8 9 10 11 12 13 Import-Module ActiveDirectoryGet-ADUser -Filter * -Properties WhenCreated, LastLogonDate, Enabled | Where-Object { $_ .WhenCreated -gt (Get-Date ).AddDays(-30 ) } | Select-Object Name, SamAccountName, WhenCreated, LastLogonDate, Enabled | Sort-Object WhenCreated -Descending Get-ADGroupMember -Identity "Domain Admins" -Recursive | Get-ADUser -Properties LastLogonDate, Enabled | Select-Object Name, SamAccountName, LastLogonDate, Enabled
详细的域环境排查将在 Windows应急响应/11-Active-Directory-排查 中展开
5. RDP 会话分析 5.1 RDP 登录的事件日志体系 RDP 登录涉及多个事件日志源,需要交叉分析才能还原完整登录过程
Security 日志 :
Event ID
说明
关键字段
4624 (Type 10)
远程交互式登录成功
源 IP (IpAddress)、用户名
4625 (Type 10)
远程登录失败
源 IP、失败原因
4634
会话注销
登录 ID (LogonId)
4647
用户发起的注销
用户名
4778
会话重新连接
客户端名称、客户端地址
4779
会话断开
客户端名称、客户端地址
TerminalServices-RemoteConnectionManager/Operational :
Event ID
说明
1149
RDP 用户认证成功(包含源 IP 和用户名)
261
监听器接收了连接
TerminalServices-LocalSessionManager/Operational :
Event ID
说明
21
远程桌面会话登录成功
22
远程桌面 Shell 启动通知
23
远程桌面会话注销
24
远程桌面会话断开
25
远程桌面会话重新连接
5.2 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 43 44 45 46 47 Get-WinEvent -FilterHashtable @ { LogName = 'Security' ID = 4624 } | ForEach-Object { $xml = [xml ]$_ .ToXml() $logonType = ($xml .Event.EventData.Data | Where-Object { $_ .Name -eq 'LogonType' }).'#text' if ($logonType -eq '10' ) { [PSCustomObject ]@ { Time = $_ .TimeCreated User = ($xml .Event.EventData.Data | Where-Object { $_ .Name -eq 'TargetUserName' }).'#text' Domain = ($xml .Event.EventData.Data | Where-Object { $_ .Name -eq 'TargetDomainName' }).'#text' SourceIP = ($xml .Event.EventData.Data | Where-Object { $_ .Name -eq 'IpAddress' }).'#text' LogonID = ($xml .Event.EventData.Data | Where-Object { $_ .Name -eq 'TargetLogonId' }).'#text' } } } | Format-Table -AutoSize 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 Get-WinEvent -LogName "Microsoft-Windows-TerminalServices-LocalSessionManager/Operational" | Where-Object { $_ .Id -in @ (21 ,22 ,23 ,24 ,25 ) } | Select-Object TimeCreated, Id, @ {N='EventType' ; E={ switch ($_ .Id) { 21 { 'Session Logon' } 22 { 'Shell Start' } 23 { 'Session Logoff' } 24 { 'Session Disconnect' } 25 { 'Session Reconnect' } } }}, @ {N='User' ; E={ $_ .Properties[0 ].Value }}, @ {N='SessionID' ; E={ $_ .Properties[1 ].Value }}, @ {N='SourceIP' ; E={ $_ .Properties[2 ].Value }} | Format-Table -AutoSize
5.3 当前 RDP 会话查看 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 :: 查看当前活跃的 RDP 会话 qwinsta :: 或 query user :: 或 query session :: 输出示例: :: SESSIONNAME USERNAME ID STATE TYPE DEVICE :: services 0 Disc :: console Admin 1 Active :: rdp-tcp#0 attacker 2 Active :: rdp-tcp 65536 Listen :: 强制断开可疑会话 :: logoff <SessionID>
1 2 3 4 5 6 7 8 9 10 11 12 13 Get-CimInstance -ClassName Win32_LogonSession | Where-Object { $_ .LogonType -eq 10 } | ForEach-Object { $session = $_ $user = Get-CimAssociatedInstance -InputObject $session -ResultClassName Win32_Account [PSCustomObject ]@ { LogonId = $session .LogonId StartTime = $session .StartTime User = $user .Caption AuthenticationPackage = $session .AuthenticationPackage } } | Format-Table -AutoSize
5.4 RDP 缓存与 Bitmap 分析 RDP 客户端会在本地缓存远程桌面的 Bitmap 数据
缓存位置 :C:\Users\<user>\AppData\Local\Microsoft\Terminal Server Client\Cache\
文件名格式:bcache24.bmc, cache0000.bin 等
工具 :bmc-tools.py 可从缓存文件中提取 Bitmap 图片
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Get-ChildItem "C:\Users\*\AppData\Local\Microsoft\Terminal Server Client\Cache" -ErrorAction SilentlyContinueGet-ChildItem "HKCU:\Software\Microsoft\Terminal Server Client\Servers" -ErrorAction SilentlyContinue | ForEach-Object { [PSCustomObject ]@ { Server = $_ .PSChildName UsernameHint = (Get-ItemProperty $_ .PSPath).UsernameHint } } Get-ChildItem "C:\Users\*\Documents\*.rdp" -ErrorAction SilentlyContinue
6. 登录类型(Logon Type)深度解析 6.1 完整登录类型对照表 Event ID 4624/4625 中的 LogonType 字段标识了登录方式,是判断攻击路径的关键
Type
名称
说明
常见场景
IR 关注度
2
Interactive
本地控制台登录
物理登录、VM 控制台
★★★
3
Network
网络登录
SMB 共享、PsExec、WMI
★★★★★
4
Batch
批处理登录
计划任务执行
★★★
5
Service
服务登录
Windows 服务启动
★★★
7
Unlock
解锁工作站
屏幕解锁
★
8
NetworkCleartext
网络明文登录
IIS Basic Auth、PowerShell WinRM (HTTP)
★★★★
9
NewCredentials
新凭据登录
runas /netonly
★★★★
10
RemoteInteractive
远程交互式
RDP 登录
★★★★★
11
CachedInteractive
缓存凭据登录
域控不可达时的域账户登录
★★
12
CachedRemoteInteractive
缓存远程登录
RDP + 域缓存
★★
13
CachedUnlock
缓存解锁
域缓存解锁
★
6.2 各登录类型的攻击场景 Type 3 (Network) —— 横向移动最常见的登录类型:
PsExec 远程执行 → Type 3
net use \\target\C$ 映射共享 → Type 3
WMI 远程命令 → Type 3
Pass-the-Hash (PTH) → Type 3
关键特征 :Type 3 登录不会在目标系统上缓存凭据
Type 10 (RemoteInteractive) —— RDP 登录:
标准 RDP 连接 → Type 10
攻击者获取凭据后 RDP 到目标 → Type 10
注意 :如果使用 mstsc /restrictedAdmin(受限管理模式),登录类型会变成 Type 3
Type 9 (NewCredentials) —— runas /netonly:
本地进程使用当前凭据,网络访问使用新凭据
Mimikatz sekurlsa::pth (Pass-the-Hash) 会生成 Type 9
Cobalt Strike 的 steal_token 操作也会触发 Type 9
Type 4 (Batch) —— 计划任务:
攻击者通过 schtasks 创建持久化任务 → Type 4
与 Event ID 4698(计划任务创建)交叉分析
6.3 按登录类型查询事件日志 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 43 44 Get-WinEvent -FilterHashtable @ { LogName = 'Security' ID = 4624 } -MaxEvents 10000 | ForEach-Object { $xml = [xml ]$_ .ToXml() ($xml .Event.EventData.Data | Where-Object { $_ .Name -eq 'LogonType' }).'#text' } | Group-Object | Sort-Object Count -Descending | Select-Object @ {N='LogonType' ;E={$_ .Name}}, Count | Format-Table Get-WinEvent -FilterHashtable @ { LogName = 'Security' ID = 4624 } -MaxEvents 5000 | ForEach-Object { $xml = [xml ]$_ .ToXml() $logonType = ($xml .Event.EventData.Data | Where-Object { $_ .Name -eq 'LogonType' }).'#text' $user = ($xml .Event.EventData.Data | Where-Object { $_ .Name -eq 'TargetUserName' }).'#text' if ($logonType -eq '3' -and $user -notlike '*$' ) { [PSCustomObject ]@ { Time = $_ .TimeCreated User = $user SourceIP = ($xml .Event.EventData.Data | Where-Object { $_ .Name -eq 'IpAddress' }).'#text' LogonProcess = ($xml .Event.EventData.Data | Where-Object { $_ .Name -eq 'LogonProcessName' }).'#text' AuthPackage = ($xml .Event.EventData.Data | Where-Object { $_ .Name -eq 'AuthenticationPackageName' }).'#text' } } } | Format-Table -AutoSize Get-WinEvent -FilterHashtable @ { LogName = 'Security' ID = 4624 } -MaxEvents 5000 | ForEach-Object { $xml = [xml ]$_ .ToXml() $logonType = ($xml .Event.EventData.Data | Where-Object { $_ .Name -eq 'LogonType' }).'#text' if ($logonType -eq '9' ) { [PSCustomObject ]@ { Time = $_ .TimeCreated User = ($xml .Event.EventData.Data | Where-Object { $_ .Name -eq 'TargetUserName' }).'#text' Process = ($xml .Event.EventData.Data | Where-Object { $_ .Name -eq 'ProcessName' }).'#text' } } } | Format-Table -AutoSize
7. 凭据缓存与凭据窃取检测 7.1 Windows 凭据存储位置
存储位置
内容
攻击工具
LSASS 进程内存
NTLM Hash, Kerberos Ticket
Mimikatz sekurlsa::logonpasswords
SAM 数据库
本地用户 NTLM Hash
secretsdump, hashdump
LSA Secrets
服务账户密码、Auto-Logon 密码
Mimikatz lsadump::secrets
DPAPI
浏览器密码、WiFi 密码、凭据管理器
Mimikatz dpapi::
Credential Manager
保存的网络凭据
vaultcmd, cmdkey
Domain Cache
域缓存凭据 (DCC2)
secretsdump
NTDS.dit (域控)
所有域用户 Hash
secretsdump, ntdsutil
7.2 凭据窃取指标检测 LSASS 访问检测 :
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 Get-WinEvent -FilterHashtable @ { LogName = 'Microsoft-Windows-Sysmon/Operational' ID = 10 } -MaxEvents 1000 -ErrorAction SilentlyContinue | Where-Object { $_ .Properties[5 ].Value -like '*lsass.exe' } | ForEach-Object { [PSCustomObject ]@ { Time = $_ .TimeCreated SourceProcess = $_ .Properties[3 ].Value TargetProcess = $_ .Properties[5 ].Value GrantedAccess = $_ .Properties[7 ].Value } } | Format-Table -AutoSize Get-ChildItem -Path "C:\" , "C:\Users\*\Desktop" , "C:\Users\*\Downloads" , "C:\Windows\Temp" , "C:\Temp" -Filter "*.dmp" -Recurse -ErrorAction SilentlyContinue Get-WinEvent -FilterHashtable @ { LogName = 'Security' ID = 4688 } -MaxEvents 5000 | Where-Object { $_ .Properties[8 ].Value -like '*comsvcs*MiniDump*' -or $_ .Properties[8 ].Value -like '*procdump*lsass*' }
凭据管理器检查 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 cmdkey /list vaultcmd /listcreds:"Windows Credentials" /all vaultcmd /listcreds:"Web Credentials" /all $autoLogon = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -ErrorAction SilentlyContinueif ($autoLogon .DefaultPassword) { Write-Warning "[!] Auto-Logon 配置发现明文密码!" Write-Host "User: $ ($autoLogon .DefaultUserName)" Write-Host "Domain: $ ($autoLogon .DefaultDomainName)" Write-Host "Password: $ ($autoLogon .DefaultPassword)" }
7.3 Credential Guard 和 LSA Protection 状态检查 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 Get-CimInstance -ClassName Win32_DeviceGuard -Namespace "root\Microsoft\Windows\DeviceGuard" -ErrorAction SilentlyContinue | Select-Object SecurityServicesRunning, VirtualizationBasedSecurityStatus $lsaPPL = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name "RunAsPPL" -ErrorAction SilentlyContinueif ($lsaPPL .RunAsPPL -eq 1 ) { Write-Host "[+] LSA Protection (PPL) 已启用 - 可阻止大部分凭据窃取" -ForegroundColor Green } else { Write-Warning "[-] LSA Protection (PPL) 未启用 - LSASS 进程可被直接访问" } $wdigest = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest" -Name "UseLogonCredential" -ErrorAction SilentlyContinueif ($wdigest .UseLogonCredential -eq 1 ) { Write-Warning "[!] WDigest 明文密码缓存已开启 - 攻击者可能已修改此配置!" }
8. 一键用户安全审计脚本 8.1 综合审计脚本 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 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 $OutputDir = "C:\IR\AccountAudit_$ (Get-Date -Format 'yyyyMMdd_HHmmss')" New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null Write-Host "========================================" -ForegroundColor CyanWrite-Host " Windows 账户安全审计" -ForegroundColor CyanWrite-Host "========================================" -ForegroundColor CyanWrite-Host "`n[*] 1. 枚举本地用户..." -ForegroundColor Yellow$localUsers = Get-LocalUser | Select-Object Name, Enabled, SID, LastLogon, PasswordLastSet, PasswordRequired, Description $localUsers | Format-Table -AutoSize $localUsers | Export-Csv "$OutputDir \LocalUsers.csv" -NoTypeInformation -Encoding UTF8Write-Host "[*] 2. 检测隐藏账户($ 结尾)..." -ForegroundColor Yellow$hiddenUsers = $localUsers | Where-Object { $_ .Name -like '*$' -and $_ .Name -ne 'DefaultAccount$' }if ($hiddenUsers ) { Write-Host "[!] 发现隐藏账户:" -ForegroundColor Red $hiddenUsers | Format-Table -AutoSize } else { Write-Host "[+] 未发现 $ 结尾的隐藏账户" -ForegroundColor Green } Write-Host "[*] 3. 审计管理员组成员..." -ForegroundColor Yellow$adminMembers = Get-LocalGroupMember -Group "Administrators" -ErrorAction SilentlyContinue$adminMembers | Format-Table -AutoSize $adminMembers | Export-Csv "$OutputDir \AdminGroupMembers.csv" -NoTypeInformation -Encoding UTF8Write-Host "[*] 4. 审计高危组成员..." -ForegroundColor Yellow$highRiskGroups = @ ("Remote Desktop Users" , "Remote Management Users" , "Backup Operators" , "Hyper-V Administrators" ) foreach ($group in $highRiskGroups ) { $members = Get-LocalGroupMember -Group $group -ErrorAction SilentlyContinue if ($members ) { Write-Host " [!] $group 组成员:" -ForegroundColor Red $members | Format-Table -AutoSize } } Write-Host "[*] 5. 检查最近 30 天的账户创建事件 (4720)..." -ForegroundColor Yellowtry { $accountCreation = Get-WinEvent -FilterHashtable @ { LogName = 'Security' ; ID = 4720 StartTime = (Get-Date ).AddDays(-30 ) } -ErrorAction SilentlyContinue | ForEach-Object { $xml = [xml ]$_ .ToXml() [PSCustomObject ]@ { Time = $_ .TimeCreated NewUser = ($xml .Event.EventData.Data | Where-Object { $_ .Name -eq 'TargetUserName' }).'#text' CreatedBy = ($xml .Event.EventData.Data | Where-Object { $_ .Name -eq 'SubjectUserName' }).'#text' } } if ($accountCreation ) { $accountCreation | Format-Table -AutoSize $accountCreation | Export-Csv "$OutputDir \AccountCreation.csv" -NoTypeInformation -Encoding UTF8 } else { Write-Host " [+] 无最近账户创建事件" -ForegroundColor Green } } catch { Write-Host " [-] 无法读取 Security 日志" -ForegroundColor Red } Write-Host "[*] 6. 检查 RDP 登录事件..." -ForegroundColor Yellowtry { $rdpLogins = Get-WinEvent -LogName "Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational" -MaxEvents 100 -ErrorAction SilentlyContinue | 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 } } if ($rdpLogins ) { $rdpLogins | Format-Table -AutoSize $rdpLogins | Export-Csv "$OutputDir \RDP_Logins.csv" -NoTypeInformation -Encoding UTF8 } } catch { Write-Host " [-] 无 RDP 日志" -ForegroundColor Red } Write-Host "[*] 7. 检查 Auto-Logon 配置..." -ForegroundColor Yellow$autoLogon = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -ErrorAction SilentlyContinueif ($autoLogon .DefaultPassword) { Write-Host "[!!!] Auto-Logon 明文密码:User=$ ($autoLogon .DefaultUserName) Pass=$ ($autoLogon .DefaultPassword)" -ForegroundColor Red } else { Write-Host " [+] 未发现 Auto-Logon 明文密码" -ForegroundColor Green } Write-Host "[*] 8. 检查凭据保护配置..." -ForegroundColor Yellow$lsaPPL = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name "RunAsPPL" -ErrorAction SilentlyContinueWrite-Host " LSA Protection (PPL): $ (if($lsaPPL .RunAsPPL -eq 1){'已启用'}else{'未启用'})" $wdigest = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest" -Name "UseLogonCredential" -ErrorAction SilentlyContinueif ($wdigest .UseLogonCredential -eq 1 ) { Write-Host " [!] WDigest 明文缓存:已开启(高危)" -ForegroundColor Red } else { Write-Host " WDigest 明文缓存:已关闭" -ForegroundColor Green } Write-Host "`n========================================" -ForegroundColor CyanWrite-Host " 审计完成,结果保存至:$OutputDir " -ForegroundColor CyanWrite-Host "========================================" -ForegroundColor Cyan
9. 实战练习:发现隐藏管理员账户 9.1 场景描述 某 Windows Server 2019 疑似被入侵,管理员发现有异常远程登录记录
你的任务 :
枚举所有本地用户,找出隐藏账户
确认哪些账户具有管理员权限
追踪异常账户的创建时间和创建者
分析 RDP 登录记录,确定攻击来源 IP
9.2 排查步骤 Step 1:基础用户枚举
1 2 3 4 5 6 7 net user Get-LocalUser | Select-Object Name, Enabled, SID, LastLogon
Step 2:确认管理员组
1 2 Get-LocalGroupMember -Group "Administrators"
Step 3:追踪账户创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 Get-WinEvent -FilterHashtable @ { LogName='Security' ; ID=4720 } | ForEach-Object { $xml = [xml ]$_ .ToXml() $target = ($xml .Event.EventData.Data | Where-Object { $_ .Name -eq 'TargetUserName' }).'#text' if ($target -like '*support*' ) { [PSCustomObject ]@ { Time = $_ .TimeCreated NewUser = $target CreatedBy = ($xml .Event.EventData.Data | Where-Object { $_ .Name -eq 'SubjectUserName' }).'#text' } } }
Step 4:RDP 来源分析
1 2 3 4 5 6 7 8 9 10 11 12 13 Get-WinEvent -FilterHashtable @ { LogName='Security' ; ID=4624 } -MaxEvents 10000 | ForEach-Object { $xml = [xml ]$_ .ToXml() $user = ($xml .Event.EventData.Data | Where-Object { $_ .Name -eq 'TargetUserName' }).'#text' $type = ($xml .Event.EventData.Data | Where-Object { $_ .Name -eq 'LogonType' }).'#text' if ($user -eq 'support$' -and $type -eq '10' ) { [PSCustomObject ]@ { Time = $_ .TimeCreated SourceIP = ($xml .Event.EventData.Data | Where-Object { $_ .Name -eq 'IpAddress' }).'#text' } } } | Sort-Object Time | Format-Table -AutoSize
9.3 Linux 工程师注意事项
Linux 习惯
Windows 差异
cat /etc/passwd 看所有用户
net user 可能遗漏隐藏账户,用 Get-LocalUser
grep :0: /etc/passwd 找 root 等权账户
检查 SID 以 -500 结尾 + Administrators 组成员
last / lastlog 查看登录记录
Event ID 4624 + TerminalServices 日志
auth.log / secure 查看认证日志
Security Event Log (4624/4625/4634)
SSH key 认证
RDP + NLA (Network Level Authentication)
who / w 查看在线用户
qwinsta / query user
10. 快速参考卡片 10.1 账户排查命令速查
目标
命令
列出所有本地用户
Get-LocalUser
查看用户详情
net user <username>
查看管理员组
Get-LocalGroupMember -Group "Administrators"
查看当前登录会话
qwinsta / query user
查看用户 SID
wmic useraccount get name,sid
查看用户权限
whoami /priv
查看保存的凭据
cmdkey /list
检查 Auto-Logon
reg query "HKLM\...\Winlogon" /v DefaultPassword
10.2 关键事件 ID 速查
Event ID
日志源
说明
4720
Security
用户账户创建
4722
Security
账户启用
4724
Security
密码重置
4725
Security
账户禁用
4726
Security
账户删除
4732
Security
添加到本地组
4624
Security
登录成功
4625
Security
登录失败
1149
TerminalServices-RCM
RDP 认证成功
21
TerminalServices-LSM
RDP 会话登录
25
TerminalServices-LSM
RDP 会话重连