跳转到帖子

从Windows事件日志定位内网横向移动:一次可落地的蓝队排查思路

精选回复

发布于

背景

内网横向移动的排查,很多时候不是靠单点告警就能闭环,而是要把身份、主机、登录类型、进程创建、远程服务等日志串起来看。尤其是在没有完整EDR覆盖的环境里,Windows安全日志仍然是最基础、最可靠的数据源之一。

本文以蓝队日常排查为视角,整理一套基于Windows事件日志的横向移动识别方法,重点关注以下场景:

  • 域账号被盗后,通过SMB、RDP、WinRM在多台主机登录;
  • 攻击者使用PsExec、sc.exe、wmic等方式远程执行;
  • 异常账号在非工作时间、非惯常主机上出现交互式或网络登录;
  • 短时间内同一账号访问大量主机,形成明显横向扩散特征。

技术分析

排查横向移动时,建议优先关注以下几类Windows事件ID。不同系统版本和审计策略会有差异,但这些事件基本是分析的主干。

事件ID 日志位置 意义 排查价值
4624 Security 登录成功 判断登录类型、来源IP、目标主机、账号
4625 Security 登录失败 发现密码喷洒、爆破、错误凭据横向尝试
4648 Security 使用显式凭据登录 常见于runas、远程连接、部分工具调用凭据
4672 Security 特权登录 识别管理员权限账号登录
4688 Security 进程创建 分析命令行、父子进程、远程执行痕迹
7045 System 服务被安装 PsExec、sc远程创建服务常见痕迹
4697 Security 服务被安装 需要开启相关审计,和7045互相印证
4776 Security,域控 NTLM认证 定位NTLM认证来源与失败原因
4768/4769 Security,域控 Kerberos认证/TGS请求 分析域内服务访问、异常票据请求

重点看4624的Logon Type

4624不是只看“登录成功”,关键在于登录类型。常见关注点如下:

  • Logon Type 2:本地交互式登录,常见于控制台登录;
  • Logon Type 3:网络登录,SMB访问、远程服务调用经常出现;
  • Logon Type 7:解锁屏幕;
  • Logon Type 10:远程交互式登录,典型RDP;
  • Logon Type 11:缓存域凭据登录,常见于离线域登录。

在横向移动里,最常见的是Type 3和Type 10。比如同一域账号在10分钟内对20台服务器产生Type 3登录,就值得重点调查。

操作步骤

1. 确认基础审计是否开启

建议在域策略中开启以下审计项,否则后续分析会缺少关键字段:

  • Audit Logon:Success、Failure;
  • Audit Account Logon:Success、Failure;
  • Audit Process Creation:Success;
  • Include command line in process creation events;
  • Audit System Events 中服务安装相关事件。

特别是4688进程创建日志,默认环境不一定记录命令行,需要额外开启“Include command line in process creation events”。没有命令行时,很多远程执行痕迹只能靠父子进程关系和时间线推断。

2. 从异常账号或异常主机切入

实际排查中,不建议一上来全域扫所有日志,容易噪声过大。可以先从以下线索切入:

  • VPN异常登录账号;
  • EDR或杀软报毒主机;
  • 域控上出现大量4625的源IP;
  • 管理员账号在非惯常终端登录;
  • 服务器上出现异常7045服务安装事件。

拿到一个账号或一台主机后,再扩展它在前后24小时内的登录和远程执行行为。

3. 建立时间线

横向移动不是孤立事件,通常会有如下顺序:

  1. 初始主机出现异常进程,例如powershell、cmd、rundll32、wmic;
  2. 域账号在该主机上产生4624 Type 2或Type 10;
  3. 随后该账号对多台目标产生4624 Type 3;
  4. 目标主机出现7045服务安装,或4688记录cmd/powershell执行;
  5. 域控上出现对应4769/4776认证记录。

如果只看其中某一个事件,可能很难判断。但把时间线串起来,横向路径会清晰很多。

代码示例

下面是一个PowerShell脚本示例,用于在单台Windows主机上导出最近24小时内的4624、4625、4672、4688、7045事件,并提取部分关键字段。适合应急时快速落地,不依赖额外组件。

$StartTime = (Get-Date).AddHours(-24)
$EventIdsSecurity = @(4624,4625,4672,4688)
$EventIdsSystem   = @(7045)

function Get-EventDataMap {
    param($Event)
    $xml = [xml]$Event.ToXml()
    $map = @{}
    foreach ($d in $xml.Event.EventData.Data) {
        if ($d.Name) {
            $map[$d.Name] = $d.'#text'
        }
    }
    return $map
}

Write-Host "[+] Query Security events..."
$secEvents = Get-WinEvent -FilterHashtable @{
    LogName   = 'Security'
    Id        = $EventIdsSecurity
    StartTime = $StartTime
} -ErrorAction SilentlyContinue

$secResult = foreach ($e in $secEvents) {
    $m = Get-EventDataMap $e
    [PSCustomObject]@{
        TimeCreated       = $e.TimeCreated
        EventId           = $e.Id
        Computer          = $e.MachineName
        TargetUserName    = $m['TargetUserName']
        TargetDomainName  = $m['TargetDomainName']
        LogonType         = $m['LogonType']
        IpAddress         = $m['IpAddress']
        WorkstationName   = $m['WorkstationName']
        ProcessName       = $m['ProcessName']
        CommandLine       = $m['CommandLine']
        ParentProcessName = $m['ParentProcessName']
    }
}

Write-Host "[+] Query System service installation events..."
$sysEvents = Get-WinEvent -FilterHashtable @{
    LogName   = 'System'
    Id        = $EventIdsSystem
    StartTime = $StartTime
} -ErrorAction SilentlyContinue

$sysResult = foreach ($e in $sysEvents) {
    $m = Get-EventDataMap $e
    [PSCustomObject]@{
        TimeCreated = $e.TimeCreated
        EventId     = $e.Id
        Computer    = $e.MachineName
        ServiceName = $m['ServiceName']
        ImagePath   = $m['ImagePath']
        AccountName = $m['AccountName']
    }
}

$secResult | Sort-Object TimeCreated | Export-Csv .\security_events_24h.csv -NoTypeInformation -Encoding UTF8
$sysResult | Sort-Object TimeCreated | Export-Csv .\service_install_24h.csv -NoTypeInformation -Encoding UTF8

Write-Host "[+] Done. Output: security_events_24h.csv, service_install_24h.csv"

导出后可以先做几个简单筛选:

  • 筛选4624且LogonType为3或10的记录;
  • 按TargetUserName统计登录过多少台主机;
  • 按IpAddress统计对多少目标发起过登录;
  • 查找7045中ImagePath是否包含ADMIN$、Temp、Users、ProgramData等路径;
  • 查找4688中CommandLine是否包含wmic、psexesvc、powershell -enc、cmd /c、net use、sc.exe等关键字。

典型痕迹判断

PsExec类远程执行

常见痕迹包括:

  • 目标主机出现4624 Type 3登录,来源为攻击者控制主机;
  • System日志出现7045,服务名可能为PSEXESVC,也可能被改名;
  • 服务ImagePath指向ADMIN$共享落地的可执行文件;
  • 随后出现cmd.exe、powershell.exe等进程创建事件。

不要只盯着服务名PSEXESVC,很多工具会随机服务名。更可靠的是“短时间内Type 3登录 + 服务安装 + 异常ImagePath + 命令执行”。

RDP横向

RDP场景通常关注:

  • 4624 Logon Type 10;
  • 来源IP是否为办公网、VPN地址或异常服务器;
  • 同一账号是否在多台服务器产生Type 10;
  • 是否伴随4778、4779远程桌面会话重连和断开事件;
  • 登录时间是否符合业务人员习惯。

如果一个普通运维账号凌晨在多台业务服务器上产生Type 10,而且来源不是堡垒机,基本就需要升级处置。

SMB访问与凭据滥用

SMB横向更多表现为4624 Type 3。单条Type 3不一定异常,因为文件共享、计划任务、管理工具都会产生网络登录。判断时建议结合:

  • 账号是否为高权限账号;
  • 来源主机是否具备管理职责;
  • 目标数量是否异常增多;
  • 是否紧跟7045、4688、5140共享访问事件;
  • 域控上是否有对应NTLM或Kerberos认证。

注意事项

  • 时间同步很关键:域控、服务器、终端时间偏差会直接影响时间线分析,建议统一NTP。
  • 日志保留周期要足够:安全日志默认大小通常不够,服务器建议至少保留7到30天,关键系统更长。
  • 不要只依赖单事件:4624 Type 3本身噪声较大,必须和服务安装、进程创建、账号画像一起看。
  • 关注机器账号:以$结尾的机器账号登录通常正常,但异常机器账号访问大量服务器时也要排查。
  • 区分堡垒机行为:如果所有管理操作都经堡垒机,日志中来源IP集中是正常的;绕过堡垒机的管理员登录反而更可疑。
  • 4688命令行存在敏感信息:开启命令行审计后可能记录密码、Token、业务参数,需要控制日志访问权限。

总结

内网横向移动排查的核心不是记几个事件ID,而是把账号、来源、目标、登录类型、远程执行和时间线串起来。实际落地时可以按这个顺序推进:

  1. 先找异常账号或异常主机;
  2. 查4624/4625确认登录来源和范围;
  3. 结合4672判断是否涉及特权账号;
  4. 看7045和4688确认是否存在远程执行;
  5. 回到域控用4768/4769/4776补认证链路;
  6. 最后形成账号、主机、时间、动作的完整闭环。

这套方法不依赖复杂平台,单靠Windows原生日志也能完成基础研判。关键是提前把审计策略和日志留存做好,否则真正应急时,很多关键证据已经被覆盖了。

网络流量与边界分析示意图
网络请求、日志与边界流量分析示意
补充一个比较实用的落地思路:不要只看单台机器的 4624,横向移动排查更适合按“登录源主机 - 目标主机 - 账号 - LogonId”串起来看。 重点关注这几类事件组合:
  • 4624:成功登录,重点看 LogonType 3/9/10
  • 4627:登录账号所属组,确认是否带管理员组权限
  • 4672:特殊权限登录,常见于管理员账号落地
  • 7045:新服务创建,常见于 PsExec、服务型横向
  • 4697:服务安装,部分系统策略下会有
  • 4688:进程创建,需要提前开启命令行审计
  • 5140/5145:共享访问,重点看 ADMIN$、C$、IPC$
一个比较典型的 PsExec/WMI/SMB 横向链路大概是:
源机器:出现对目标主机 ADMIN$ / IPC$ 的访问
目标机器:4624 LogonType=3,认证包 NTLM 或 Kerberos
目标机器:4672 特权登录
目标机器:7045 创建服务
目标机器:4688 出现 cmd.exe / powershell.exe / rundll32.exe / wmic.exe 等进程
如果环境里有 PowerShell,可以先在疑似目标主机上拉最近一天的远程登录和服务创建记录:
Get-WinEvent -FilterHashtable @{
    LogName='Security'
    Id=4624,4672,5140,5145
    StartTime=(Get-Date).AddDays(-1)
} | Select-Object TimeCreated,Id,@{
    Name='TargetUser';Expression={$_.Properties[5].Value}
},@{
    Name='LogonType';Expression={$_.Properties[8].Value}
},@{
    Name='SourceIp';Expression={$_.Properties[18].Value}
},@{
    Name='Workstation';Expression={$_.Properties[11].Value}
} | Format-Table -AutoSize

Get-WinEvent -FilterHashtable @{
    LogName='System'
    Id=7045
    StartTime=(Get-Date).AddDays(-1)
} | Select-Object TimeCreated,ProviderName,Id,Message
如果开了 4688 命令行审计,可以再看目标主机上的可疑进程:
Get-WinEvent -FilterHashtable @{
    LogName='Security'
    Id=4688
    StartTime=(Get-Date).AddDays(-1)
} | Where-Object {
    $_.Message -match 'cmd.exe|powershell.exe|wmic.exe|rundll32.exe|regsvr32.exe|certutil.exe|bitsadmin.exe|psexesvc'
} | Select-Object TimeCreated,Message
这里有几个排查细节挺关键:
  • LogonType=3 不一定就是攻击,文件共享、远程管理都会产生,需要结合 SourceIp、账号、时间窗口和后续 7045/4688 判断。
  • 4672 单独出现意义有限,但如果和 4624 同一个 LogonId,且来源不是常见运维机,就值得重点看。
  • 7045 的服务名不一定叫 PSEXESVC,很多工具会随机服务名,所以更要看 Service File Name 是否指向 ADMIN$、Windows\Temp、ProgramData 等路径。
  • RDP 横向 重点看 4624 LogonType=10,同时关联 TerminalServices-LocalSessionManager 下的 21、24、25 事件。
  • WMI 横向 可能没有明显服务创建,建议同时看 WMI-Activity/Operational 的 5857、5858、5861,以及目标机上的 4688。
建议在域环境里做一个基线:哪些账号允许跨主机管理、哪些机器是跳板机/运维机。后续排查时,优先筛选“普通办公机发起到多台服务器的 4624 Type 3/10”、“同一账号短时间登录多台主机”、“非常规时间段出现 ADMIN$ 访问”这类行为,命中率会比单纯搜事件 ID 高很多。

创建帐户或登录后发表意见

最近浏览 0

  • 没有会员查看此页面。