发布于10月9日10月9日 背景最近在一次授权内网渗透测试复盘里,客户提出一个很典型的问题:测试期间发现一台业务服务器上出现了异常登录和远程命令执行痕迹,但不确定是测试人员操作、运维误操作,还是已有入侵行为。这个问题很适合放在问答中心讨论,因为核心不是“怎么打进去”,而是如何基于日志把权限边界、操作链路和修复建议说清楚。场景大致如下:域环境:Windows AD,部分服务器加入域。被关注主机:Windows Server 2019,业务应用服务器。已知授权测试范围:允许漏洞验证、弱口令验证、最小化横向验证;禁止持久化、破坏性操作。异常现象:安全设备提示该服务器向多台内网主机发起 SMB、WinRM、RDP 连接。下面按实际排查思路展开,重点放在可复用的方法和证据链整理。问题定位第一步不要急着下结论。内网横向行为常见触发源包括:渗透测试人员使用了远程命令执行、凭据验证或共享枚举工具。运维脚本批量分发任务,例如 PowerShell Remoting、PsExec、计划任务。业务程序访问共享目录或数据库时产生正常连接。主机已经被入侵,攻击者在做凭据复用和横向扩散。需要先回答三个问题:谁登录了这台机器?登录后执行了什么?这台机器又连接了哪些目标?技术分析Windows 内网排查建议重点看以下日志:日志位置重点事件用途Security4624、4625、4634、4672、4688登录、失败登录、特权登录、进程创建System7045服务安装,常见于 PsExec 类工具Microsoft-Windows-PowerShell/Operational4103、4104PowerShell 命令和脚本块记录Microsoft-Windows-WinRM/Operational6、91、169WinRM 远程管理行为TerminalServices-LocalSessionManager21、22、24、25RDP 会话建立、断开、重连重点解释几个事件:4624:成功登录。关注 LogonType,例如 3 是网络登录,10 是远程交互式登录,2 是本地交互式登录。4672:分配了特殊权限,通常说明该账户具备管理员级别能力。4688:进程创建日志,需要提前开启命令行记录,否则信息有限。7045:新服务被安装,若服务名随机、路径指向 ADMIN$ 或临时目录,需要重点核查。4104:PowerShell Script Block 日志,能看到很多远程执行、下载、编码执行痕迹。操作步骤建议按时间线做,不要只看单条告警。确认安全设备告警时间窗口,例如 10:20 到 10:45。在源主机上查登录事件,确认当时有哪些账号进入。查特权登录和进程创建,判断是否有远程执行工具或脚本。在目标主机上查 4624、7045、WinRM、RDP 相关日志,验证是否真的发生横向访问。和授权测试记录、运维工单、堡垒机审计记录对齐。命令示例以下命令适合在授权排查场景使用,目的是提取证据,不建议直接在生产上大范围执行高负载查询。时间范围请按实际调整。# 查询最近 24 小时成功登录事件,重点看 LogonType、账号、来源地址 Get-WinEvent -FilterHashtable @{ LogName='Security'; Id=4624; StartTime=(Get-Date).AddHours(-24) } | Select-Object TimeCreated, @{n='Account';e={$_.Properties[5].Value}}, @{n='LogonType';e={$_.Properties[8].Value}}, @{n='SourceIP';e={$_.Properties[18].Value}} | Sort-Object TimeCreated # 查询特权登录事件 Get-WinEvent -FilterHashtable @{ LogName='Security'; Id=4672; StartTime=(Get-Date).AddHours(-24) } | Select-Object TimeCreated, @{n='Account';e={$_.Properties[1].Value}} # 查询新服务安装事件,常用于发现 PsExec/远程服务执行痕迹 Get-WinEvent -FilterHashtable @{ LogName='System'; Id=7045; StartTime=(Get-Date).AddDays(-3) } | Select-Object TimeCreated, @{n='ServiceName';e={$_.Properties[0].Value}}, @{n='ImagePath';e={$_.Properties[1].Value}}, @{n='Account';e={$_.Properties[4].Value}} # 查询 PowerShell Script Block 日志,关注 encoded、download、invoke、iex 等关键字 Get-WinEvent -LogName 'Microsoft-Windows-PowerShell/Operational' | Where-Object { $_.Id -eq 4104 -and $_.TimeCreated -gt (Get-Date).AddDays(-3) -and $_.Message -match 'encoded|download|invoke|iex|WebClient|FromBase64String' } | Select-Object TimeCreated, Id, Message 如果环境已经接入 Sysmon,排查会更清晰。重点关注:Event ID 1:进程创建。Event ID 3:网络连接。Event ID 7:镜像加载。Event ID 11:文件创建。Event ID 13:注册表值修改。# Sysmon:查询可疑远程连接行为 Get-WinEvent -FilterHashtable @{ LogName='Microsoft-Windows-Sysmon/Operational'; Id=3; StartTime=(Get-Date).AddHours(-24) } | Where-Object { $_.Message -match 'DestinationPort: 445|DestinationPort: 5985|DestinationPort: 3389' } | Select-Object TimeCreated, Message 常见判断点下面几个特征可以帮助区分测试行为、运维行为和异常入侵行为。如果出现 LogonType=3,来源 IP 是测试机,且时间与授权测试记录一致,通常可以归入测试链路。如果出现 7045 新服务安装,服务名随机、路径位于 C:\Windows\Temp 或 ADMIN$,需要确认是否为测试工具或运维分发工具。如果 PowerShell 日志中有 -enc、FromBase64String、IEX、外连下载行为,但测试记录里没有对应操作,应提高优先级。如果同一账号在短时间内对多台主机产生 4624 事件,且来源都是同一业务服务器,说明这台服务器可能被当作跳板。如果登录账号是域管理员、备份账号、运维共享账号,要重点核查凭据来源和使用范围。权限边界确认授权渗透里经常会遇到一个问题:测试人员为了验证风险,会做最小化横向验证。但验证要有边界,建议至少保留以下记录:测试机 IP、测试账号、测试时间窗口。验证的目标主机清单。使用的协议,例如 SMB、RDP、WinRM、WMI。执行的命令摘要,不记录敏感明文密码。验证结果,例如“仅验证登录成功,不执行命令”。如果缺少这些记录,后续蓝队排查很容易把测试流量和真实攻击混在一起,影响判断。风险与修复建议如果确认存在非预期横向行为,建议按优先级处理:立即禁用或重置疑似泄露账号密码,尤其是域管理员、服务器本地管理员、运维共享账号。检查本地管理员组成员,清理不必要的域用户和历史运维账号。限制 SMB、WinRM、RDP 横向访问,仅允许堡垒机、运维网段访问。开启并集中采集 4688 进程命令行、PowerShell 4104、WinRM 日志。对高权限账号启用分级管理,避免域管登录普通业务服务器。检查是否存在新增服务、计划任务、启动项、异常注册表 Run 项。对关键服务器启用 LAPS 或 Windows LAPS,避免本地管理员密码复用。可以参考以下基础加固项:# 开启进程创建命令行审计(需管理员权限) reg add "HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System\Audit" /v ProcessCreationIncludeCmdLine_Enabled /t REG_DWORD /d 1 /f # 开启 PowerShell Script Block Logging reg add "HKLM\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" /v EnableScriptBlockLogging /t REG_DWORD /d 1 /f # 查看本地管理员组成员 net localgroup administrators # 查看计划任务中最近变更或可疑任务 schtasks /query /fo LIST /v 总结这类问题的关键不是单看某个告警,而是把“登录事件、进程执行、远程连接、目标主机痕迹、授权记录”串成时间线。对问答中心里的求助帖来说,建议提问时至少提供脱敏后的时间范围、源 IP、目标 IP、事件 ID、账号类型和授权边界,这样社区成员才能给出更准确的判断。一句经验:内网排查先确认边界,再还原链路。没有授权记录的“测试行为”,在日志里和真实攻击没有本质区别。 服务器、云资产与权限边界梳理示意
10月9日10月9日 你这个场景建议先别急着“定性为横向”,先把边界画出来:谁是源头、访问了哪些主机、用了什么账号、协议是否成功。内网测试里最容易误判的是漏洞扫描器、运维跳板机、域控正常管理流量和真实横向混在一起。 可以按下面思路做日志定位。 1. 先从 Windows 登录事件定边界 重点看目标主机上的安全日志: 4624:登录成功 4625:登录失败 4648:使用显式凭据登录 4672:管理员特权登录 4688:进程创建,需要提前开启 7045:创建服务,常见于 PsExec 类行为 4697:服务安装 5140/5145:共享访问,尤其是 ADMIN$、C$、IPC$ 4768/4769/4776:域认证相关,在 DC 上看 横向行为常见组合: 4624 LogonType=3 + 5140 ADMIN$ + 7045:远程服务/PsExec 类 4624 LogonType=10:RDP 登录 4624 LogonType=3 + 远程 WMI 进程:WMIExec 类 4648 出现在普通终端上:说明有人显式使用了其他账号凭据 同一账号短时间登录多台机器,尤其来源 IP 固定:需要重点确认 可以先在可疑主机上用 PowerShell 拉近 24 小时登录事件: $start = (Get-Date).AddHours(-24) Get-WinEvent -FilterHashtable @{ LogName='Security' Id=4624,4625,4648,4672,5140,5145 StartTime=$start } | Select-Object TimeCreated, Id, @{n='User';e={$_.Properties[5].Value}}, @{n='LogonType';e={$_.Properties[8].Value}}, @{n='SrcIP';e={$_.Properties[18].Value}}, @{n='Workstation';e={$_.Properties[11].Value}} | Format-Table -AutoSize 注意不同 Windows 版本字段位置可能略有差异,最终还是以事件详情里的 Account Name、Source Network Address、Logon Type 为准。 2. 在域控上看账号扩散路径 如果是域环境,边界最好从 DC 的认证日志定。重点看: 某个账号是否短时间请求多个服务票据:4769 是否大量失败认证:4771、4776 是否异常访问 CIFS、HOST、TERMSRV 服务 筛选近 24 小时 4769: $start = (Get-Date).AddHours(-24) Get-WinEvent -FilterHashtable @{ LogName='Security' Id=4769 StartTime=$start } | ForEach-Object { [PSCustomObject]@{ Time = $_.TimeCreated Account = $_.Properties[0].Value Service = $_.Properties[2].Value ClientIP = $_.Properties[6].Value TicketEncType = $_.Properties[8].Value } } | Sort-Object Account,Time 如果看到普通用户账号频繁请求 cifs/hostname、host/hostname、termsrv/hostname,且目标主机跨度大,就要和授权测试人员确认是否为测试动作。若不是,很可能已经存在凭据被复用。 3. 区分扫描和真实横向 仅有连接不代表横向成功,建议按证据链判断: 现象倾向 大量 445/135/3389 连接,无成功登录事件更像扫描或探测 4624 Type 3 成功登录 + ADMIN$ 访问疑似 SMB 横向 7045 创建随机服务名高度疑似 PsExec 类执行 4688 中出现 cmd.exe /c、powershell -enc疑似远程命令执行 同一账号登录大量非职责范围主机凭据扩散风险 如果主机开启了 Sysmon,可以进一步看: Event ID 1:进程创建 Event ID 3:网络连接 Event ID 11:文件创建 Event ID 13:注册表修改 重点关注远程执行落地文件: Get-WinEvent -FilterHashtable @{ LogName='Microsoft-Windows-Sysmon/Operational' Id=1,3,11 StartTime=(Get-Date).AddHours(-24) } | Where-Object { $_.Message -match 'psexesvc|ADMIN\$|powershell|wmic|cmd.exe|rundll32|regsvr32' } | Select-Object TimeCreated,Id,Message 4. 给出边界结论时建议这样描述 不要只写“发现横向移动”,最好写成可验证结论: 在 2025-xx-xx xx:xx 至 xx:xx 期间,源主机 A 使用账号 domain\user1 对 B、C、D 三台主机产生成功网络登录,登录类型为 3;其中 B、C 存在 ADMIN$ 访问记录,B 上出现服务创建事件 7045。当前证据支持 A 到 B/C 的远程执行行为,D 仅有认证成功,未发现命令执行证据。 这样边界比较清楚,也方便业务方接受。 5. 修复建议要按风险分层 优先建议: 立即确认涉及账号是否为授权测试账号;如果不是,先禁用或重置密码。 清理本地管理员组,避免域用户、大范围运维组长期拥有本地管理员权限。 限制横向协议:普通办公网到服务器网段禁止直接访问 445/135/139/3389/5985/5986。 关闭不必要的 ADMIN$ 远程管理入口,至少按网段和跳板机做 ACL。 RDP 只允许跳板机访问,并开启 NLA 和 MFA。 启用 Windows 防火墙入站规则,按管理网段放行 SMB/WMI/WinRM。 开启进程命令行审计:4688 带命令行参数。 开启 4688 命令行审计可以这样做: reg add "HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System\Audit" ^ /v ProcessCreationIncludeCmdLine_Enabled /t REG_DWORD /d 1 /f auditpol /set /subcategory:"Process Creation" /success:enable Windows 防火墙按管理网段放行 SMB 示例: New-NetFirewallRule -DisplayName "Allow SMB from Mgmt Subnet" ` -Direction Inbound ` -Protocol TCP ` -LocalPort 445 ` -RemoteAddress 10.10.10.0/24 ` -Action Allow New-NetFirewallRule -DisplayName "Block SMB from Others" ` -Direction Inbound ` -Protocol TCP ` -LocalPort 445 ` -Action Block 6. 最后建议补一个时间线 把以下字段整理成表,基本就能把边界说明白: 时间 源 IP / 源主机名 目标主机 账号 事件 ID 登录类型 访问协议或服务 是否成功 是否存在命令执行证据 这个问题的关键不是单点日志,而是把“认证成功、共享访问、服务创建、进程执行、网络连接”串起来。只要能证明哪些主机只有探测,哪些主机已经成功执行命令,边界和整改优先级就比较清楚了。
10月10日10月10日 补充一个比较实用的做法:不要只按单台机器看事件,建议先做一张“源 IP → 目标主机 → 账号 → 登录类型 → 结果 → 时间”的表,横向边界基本就能画出来。尤其是你已经看到可疑横向行为时,重点是把“成功登录链路”和“凭据使用范围”先确认清楚。 如果环境里暂时没有 SIEM,可以先用 PowerShell 从目标主机批量拉近 24 小时的关键登录事件,做初步聚合: $hosts = Get-Content .\hosts.txt $start = (Get-Date).AddHours(-24) $events = foreach ($h in $hosts) { try { Get-WinEvent -ComputerName $h -FilterHashtable @{ LogName='Security' Id=4624,4625,4648,4672,5140,5145 StartTime=$start } | ForEach-Object { $xml = [xml]$_.ToXml() $data = @{} foreach ($d in $xml.Event.EventData.Data) { $data[$d.Name] = $d.'#text' } [PSCustomObject]@{ Host = $h Time = $_.TimeCreated EventId = $_.Id Account = "$($data['TargetDomainName'])\$($data['TargetUserName'])" LogonType = $data['LogonType'] SourceIp = $data['IpAddress'] Workstation = $data['WorkstationName'] ShareName = $data['ShareName'] Status = $data['Status'] Process = $data['ProcessName'] } } } catch { Write-Warning "Failed on $h : $_" } } $events | Sort-Object Time | Export-Csv .\lateral-check.csv -NoTypeInformation -Encoding UTF8 拿到 CSV 后,我一般会先看这几个聚合结果: # 同一源 IP 短时间访问了哪些主机 $events | Where-Object {$_.SourceIp -and $_.SourceIp -ne "-" -and $_.EventId -in 4624,4625} | Group-Object SourceIp | Sort-Object Count -Descending | Select-Object Count,Name # 同一账号登录了哪些主机 $events | Where-Object {$_.EventId -eq 4624 -and $_.LogonType -in 3,10} | Group-Object Account | Sort-Object Count -Descending | Select-Object Count,Name # ADMIN$ / C$ 访问情况 $events | Where-Object {$_.EventId -in 5140,5145 -and $_.ShareName -match "ADMIN\$|C\$|IPC\$"} | Sort-Object Time | Select-Object Time,Host,Account,SourceIp,ShareName 如果发现某个账号在多个工作站上出现 4624 LogonType=3,同时伴随 ADMIN$、IPC$ 访问,就要继续往下查“它到底有没有落地执行”。只看到登录不一定等于执行成功,最好结合下面几类日志: 服务安装:System 日志 7045,Security 日志 4697,看服务名、binPath 是否异常。 计划任务:Microsoft-Windows-TaskScheduler/Operational,重点看 106、140、141、200、201。 WMI:Microsoft-Windows-WMI-Activity/Operational,重点看 5857、5858、5860、5861。 PowerShell:PowerShell Operational 4103、4104,看是否有远程执行、下载、编码命令。 进程创建:4688 或 Sysmon Event ID 1,看父子进程,比如 services.exe 拉起 cmd、powershell、rundll32、regsvr32。 比如查最近的远程服务创建,可以这样看: Get-WinEvent -FilterHashtable @{ LogName='System' Id=7045 StartTime=(Get-Date).AddHours(-24) } | ForEach-Object { $msg = $_.Message [PSCustomObject]@{ Time = $_.TimeCreated Host = $env:COMPUTERNAME Message = $msg } } | Format-List 如果开了 Sysmon,横向边界会更清晰。重点关注: Event ID 1:进程创建。 Event ID 3:网络连接。 Event ID 11:文件创建,比如 ADMIN$ 落地文件。 Event ID 13:注册表修改。 Event ID 22:DNS 查询。 可以重点筛选这些典型父进程: Get-WinEvent -FilterHashtable @{ LogName='Microsoft-Windows-Sysmon/Operational' Id=1 StartTime=(Get-Date).AddHours(-24) } | Where-Object { $_.Message -match "ParentImage:.*\\services.exe" -or $_.Message -match "ParentImage:.*\\wmiprvse.exe" -or $_.Message -match "ParentImage:.*\\taskeng.exe" -or $_.Message -match "ParentImage:.*\\svchost.exe" } | Select-Object TimeCreated, Message 定位边界时还有一个点容易漏:DC 上的认证日志比单机日志更适合判断凭据扩散范围。如果是域账号,建议在 DC 上按账号反查 4768/4769/4776,确认它从哪些客户端发起认证、访问了哪些服务。 # 在 DC 上按可疑账号过滤 Kerberos 服务票据请求 Get-WinEvent -FilterHashtable @{ LogName='Security' Id=4769 StartTime=(Get-Date).AddHours(-24) } | Where-Object { $_.Message -match "Account Name:\s+suspect_user" } | Select-Object TimeCreated, Message 修复建议可以按“账号、主机、协议、日志”四块给,不建议只写一句“改密码”。 账号侧:确认被使用的账号是否为域管、本地管理员、服务账号。对可疑账号强制改密,清理长期不使用的本地管理员账号,优先启用 LAPS / Windows LAPS 管理本地管理员密码。 主机侧:对被成功登录的主机做进程、服务、计划任务、自启动、最近落地文件排查。不要只看最早报警主机,所有成功登录过的目标都要纳入范围。 协议侧:收敛 SMB/RDP/WMI/WinRM 的访问范围。普通终端之间尽量禁止 445 横向互访,只允许管理网段或跳板机访问。 权限侧:减少普通域账号在多台机器上的本地管理员权限,服务账号禁止交互式登录,域管账号不要登录普通终端。 审计侧:补齐 4688 进程命令行、PowerShell 4104、WMI Operational、对象访问 5140/5145、Sysmon 这几类日志,否则后续很难复盘执行动作。 组策略里建议至少打开进程命令行审计: 计算机配置 → 管理模板 → 系统 → 审核进程创建 → 在进程创建事件中加入命令行:已启用 对应审计策略可以这样下发: auditpol /set /subcategory:"Process Creation" /success:enable /failure:enable auditpol /set /subcategory:"Logon" /success:enable /failure:enable auditpol /set /subcategory:"File Share" /success:enable /failure:enable auditpol /set /subcategory:"Detailed File Share" /success:enable /failure:enable 最后建议报告里把结论写成可验证的边界,而不是直接写“已横向”。例如: 源主机:A,源 IP:x.x.x.x。 使用账号:DOMAIN\user1。 成功访问目标:B、C、D。 协议/方式:SMB ADMIN$ + 服务创建,或 RDP,或 WMI。 执行证据:7045 / 4688 / Sysmon 1 / PowerShell 4104。 未发现执行证据的主机:只出现认证或共享访问,建议列为待观察。 这样既能避免误判扫描器或跳板机流量,也方便后面给业务方落修复项。
创建帐户或登录后发表意见