# Detecting Lateral Movement In Network

> 通过分析身份验证日志、网络流量、SMB 流量和 RDP 会话，使用 Zeek、Velociraptor 和 SIEM 关联规则，识别企业网络中的横向移动技术，检测攻击者在系统间的移动行为。

- Skill: `killvxk/detecting-lateral-movement-in-network` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add killvxk/detecting-lateral-movement-in-network`
- Raw SKILL.md: https://api.skillmd.com/api/skills/killvxk/detecting-lateral-movement-in-network/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: Apache-2.0
- Author: killvxk (https://skillmd.com/u/killvxk)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/killvxk/detecting-lateral-movement-in-network

---

# 检测网络中的横向移动

## 适用场景

- 监控企业网络中的入侵后横向移动（lateral movement）模式（哈希传递（pass-the-hash）、RDP 跳转、PSExec）
- 为 MITRE ATT&CK 横向移动技术（T1021、T1570）构建 SIEM 检测规则和告警
- 通过分析身份验证模式和内部主机间的网络连接，调查疑似入侵事件
- 狩猎异常的东西向流量（east-west traffic）模式，识别攻击者在网络中的横穿行为
- 验证网络分段和访问控制是否有效限制横向移动路径

**不适用场景**：替代终端检测与响应（EDR）工具；仅监控南北向流量而忽略内部流量；在没有正常内部通信模式基线的情况下使用。

## 前置条件

- 在内部关键节点部署了网络安全监控（Zeek、Suricata 或网络 TAP）
- SIEM 平台（Splunk、Elastic、Microsoft Sentinel）收集 Windows 安全事件日志、DNS 和流量数据
- 配置了 Windows 事件日志转发，收集安全事件（4624、4625、4648、4672、4768、4769）
- 建立了正常内部身份验证和连接模式的基线
- 了解 MITRE ATT&CK 横向移动战术（TA0008）

## 工作流程

### 步骤 1：配置横向移动检测的日志收集

```bash
# 需收集的 Windows 事件日志（通过 WEF 或代理）：
# 安全日志：
#   4624 - 成功登录（类型 3=网络，类型 10=远程交互）
#   4625 - 登录失败
#   4648 - 使用显式凭据登录（RunAs、PsExec）
#   4672 - 分配了特殊权限（管理员登录）
#   4768 - Kerberos TGT 请求
#   4769 - Kerberos 服务票证请求
#   4776 - NTLM 身份验证（凭据验证）
# 系统日志：
#   7045 - 安装了新服务（PsExec 指标）
#   7036 - 服务启动/停止

# 配置 Windows 事件转发（WEF）订阅
# 在收集服务器上（PowerShell）：
# wecutil cs lateral-movement-subscription.xml

# 用于 Windows 事件日志传输的 Filebeat 配置
cat > /etc/filebeat/modules.d/security.yml << 'EOF'
- module: system
  auth:
    enabled: true
    var.paths: ["/var/log/auth.log"]
  syslog:
    enabled: true

- module: zeek
  connection:
    enabled: true
    var.paths: ["/opt/zeek/logs/current/conn.log"]
  dns:
    enabled: true
    var.paths: ["/opt/zeek/logs/current/dns.log"]
  smb_mapping:
    enabled: true
    var.paths: ["/opt/zeek/logs/current/smb_mapping.log"]
  dce_rpc:
    enabled: true
    var.paths: ["/opt/zeek/logs/current/dce_rpc.log"]
EOF

# Zeek 横向移动检测配置
# 启用 SMB、DCE-RPC 和 Kerberos 日志
cat >> /opt/zeek/share/zeek/site/local.zeek << 'EOF'
@load policy/protocols/smb
@load policy/protocols/conn/known-hosts
@load policy/protocols/conn/known-services
@load frameworks/intel/seen
EOF

sudo zeekctl deploy
```

### 步骤 2：为常见横向移动技术构建检测规则

```yaml
# 横向移动检测的 Splunk SPL 查询

# 1. 检测 PsExec 使用（在远程主机上创建新服务）
# index=wineventlog EventCode=7045 ServiceName="PSEXESVC" OR ServiceName="*psexec*"
# | stats count by ComputerName, ServiceName, ImagePath
# | where count > 0

# 2. 检测哈希传递（NTLM 类型 3 登录）
# index=wineventlog EventCode=4624 LogonType=3 AuthenticationPackageName="NTLM"
# | where TargetUserName!="ANONYMOUS LOGON" AND TargetUserName!="$"
# | stats count dc(ComputerName) as unique_hosts by TargetUserName, IpAddress
# | where unique_hosts > 3

# 3. 检测 RDP 横向移动（内网 IP 的类型 10 登录）
# index=wineventlog EventCode=4624 LogonType=10
# | where cidrmatch("10.0.0.0/8", IpAddress) OR cidrmatch("192.168.0.0/16", IpAddress)
# | stats count dc(ComputerName) as rdp_hosts by TargetUserName, IpAddress
# | where rdp_hosts > 2

# Elastic SIEM 检测规则（KQL）
# event.code: "4624" and winlog.event_data.LogonType: "3"
#   and winlog.event_data.AuthenticationPackageName: "NTLM"
#   and not winlog.event_data.TargetUserName: *$
#   and source.ip: (10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16)
```

```bash
# 横向移动检测的 Sigma 规则
# 安装 sigma-cli 并转换为目标 SIEM 格式
pip3 install sigma-cli

cat > lateral_movement_pth.yml << 'EOF'
title: Pass-the-Hash Lateral Movement Detection
id: f8d98d6c-7a07-4d74-b064-dd4a3c244528
status: experimental
description: Detects network logon with NTLM authentication to multiple hosts
logsource:
    product: windows
    service: security
detection:
    selection:
        EventID: 4624
        LogonType: 3
        AuthenticationPackageName: NTLM
    filter:
        TargetUserName|endswith: '$'
    condition: selection and not filter
    timeframe: 15m
    count:
        field: ComputerName
        min: 3
        group-by: TargetUserName
level: high
tags:
    - attack.lateral_movement
    - attack.t1550.002
EOF

# 将 Sigma 规则转换为 Splunk SPL
sigma convert -t splunk lateral_movement_pth.yml

# 转换为 Elastic 查询
sigma convert -t elasticsearch lateral_movement_pth.yml
```

### 步骤 3：使用 Zeek 进行网络层检测

```bash
# 检测 SMB 横向移动（访问 admin$ 和 c$ 共享）
cat /opt/zeek/logs/current/smb_mapping.log | \
  zeek-cut ts id.orig_h id.resp_h path | \
  grep -iE "(admin\$|c\$|ipc\$)" | \
  sort -t$'\t' -k2 | uniq -c | sort -rn

# 检测在端口 445 上连接大量内部主机的主机（SMB 扩散）
cat /opt/zeek/logs/current/conn.log | \
  zeek-cut ts id.orig_h id.resp_h id.resp_p | \
  awk '$4 == 445' | \
  awk '{print $2}' | sort | uniq -c | sort -rn | head -10

# 检测 WMI 横向移动（DCE-RPC 到 IWbemServices）
cat /opt/zeek/logs/current/dce_rpc.log | \
  zeek-cut ts id.orig_h id.resp_h operation | \
  grep -i "wbem\|wmi" | sort | uniq -c | sort -rn

# 检测内部主机间的 RDP 连接
cat /opt/zeek/logs/current/conn.log | \
  zeek-cut ts id.orig_h id.resp_h id.resp_p duration | \
  awk '$4 == 3389 && $5 > 60' | \
  sort -t$'\t' -k2 | head -20

# 检测 Kerberos 票证授予异常
cat /opt/zeek/logs/current/kerberos.log | \
  zeek-cut ts id.orig_h id.resp_h client service success error_msg | \
  grep -v "true" | head -20

# 用于横向移动检测的自定义 Zeek 脚本
sudo tee /opt/zeek/share/zeek/site/custom-detections/lateral-movement.zeek << 'ZEEKEOF'
@load base/frameworks/notice
@load base/frameworks/sumstats

module LateralMovement;

export {
    redef enum Notice::Type += {
        SMB_Lateral_Spread,
        RDP_Lateral_Chain
    };
    const smb_host_threshold: count = 5 &redef;
    const smb_time_window: interval = 15min &redef;
}

event zeek_init()
{
    local r1 = SumStats::Reducer(
        $stream="lateral.smb",
        $apply=set(SumStats::UNIQUE)
    );

    SumStats::create([
        $name="detect-smb-lateral",
        $epoch=smb_time_window,
        $reducers=set(r1),
        $threshold_val(key: SumStats::Key, result: SumStats::Result) = {
            return result["lateral.smb"]$unique + 0.0;
        },
        $threshold=smb_host_threshold + 0.0,
        $threshold_crossed(key: SumStats::Key, result: SumStats::Result) = {
            NOTICE([
                $note=SMB_Lateral_Spread,
                $msg=fmt("Host %s connected to %d SMB hosts in %s",
                         key$str, result["lateral.smb"]$unique, smb_time_window),
                $identifier=key$str
            ]);
        }
    ]);
}

event connection_state_remove(c: connection)
{
    if ( c$id$resp_p == 445/tcp && c$id$resp_h in Site::local_nets )
    {
        SumStats::observe("lateral.smb",
            [$str=cat(c$id$orig_h)],
            [$str=cat(c$id$resp_h)]
        );
    }
}
ZEEKEOF

sudo zeekctl deploy
```

### 步骤 4：威胁狩猎横向移动指标

```bash
# 狩猎 Windows 日志中的身份验证异常
# Splunk 查询：从异常源主机进行身份验证的用户
# index=wineventlog EventCode=4624 LogonType=3
# | stats values(IpAddress) as source_ips dc(IpAddress) as source_count by TargetUserName
# | where source_count > 5
# | sort -source_count

# 狩猎以交互方式使用的服务账户
# index=wineventlog EventCode=4624 (LogonType=2 OR LogonType=10)
# | where match(TargetUserName, "^svc-.*")
# | table _time ComputerName TargetUserName IpAddress LogonType

# 横向移动模式的网络流分析
# 查找突然与大量内部主机通信的主机
cat /opt/zeek/logs/current/conn.log | \
  zeek-cut ts id.orig_h id.resp_h | \
  awk '{
    key = $2
    targets[key][$3] = 1
  }
  END {
    for (src in targets) {
      count = 0
      for (dst in targets[src]) count++
      if (count > 20) print src, count
    }
  }' | sort -k2 -rn

# 检测凭据转储痕迹（大量 LSASS 读取）
# 查找突然横穿的主机的连接
cat /opt/zeek/logs/current/conn.log | \
  zeek-cut ts id.orig_h id.resp_h id.resp_p orig_bytes | \
  awk '$4 == 445 && $5 > 10000000' | sort -t$'\t' -k5 -rn

# 时间线分析：绘制攻击路径
# index=wineventlog (EventCode=4624 OR EventCode=7045)
# | eval stage=case(
#     EventCode=4624 AND LogonType=3, "Network Logon",
#     EventCode=4624 AND LogonType=10, "RDP Logon",
#     EventCode=7045, "Service Creation"
#   )
# | timechart span=5m count by stage
```

### 步骤 5：自动响应与遏制

```bash
# 横向移动响应的 SOAR 剧本（伪代码）
# 当横向移动告警触发时：

# 1. 用上下文信息丰富告警
# - 查询 AD 获取用户组成员资格和角色
# - 检查源 IP 是否为已知管理员工作站
# - 查找受影响主机的近期漏洞扫描结果

# 2. 自动遏制操作
# 选项 A：通过交换机端口关闭隔离主机
# ssh admin@switch "conf t; interface Gi1/0/5; shutdown"

# 选项 B：通过 VLAN 变更隔离（影响较小）
# ssh admin@switch "conf t; interface Gi1/0/5; switchport access vlan 999"

# 选项 C：在防火墙层面封锁
sudo iptables -I FORWARD -s 10.10.5.23 -j DROP

# 3. 禁用被入侵账户
# PowerShell: Disable-ADAccount -Identity compromised_user

# 4. 强制重置密码
# PowerShell: Set-ADAccountPassword -Identity compromised_user -Reset

# 5. 完全遏制前收集取证证据
# velociraptor artifact collect Windows.KapeFiles.Targets --target BasicCollection
```

### 步骤 6：构建检测仪表板

```bash
# Elastic Kibana 横向移动监控仪表板查询

# 面板 1：身份验证热图（源与目标）
# 聚合：源 IP（行）和目标 IP（列）的 Terms 聚合
# 指标：event.code:4624 的计数

# 面板 2：内部主机间的 SMB 连接
# 过滤：destination.port:445 and source.ip:10.0.0.0/8
# 聚合：按唯一目标数排序的前 20 个源 IP

# 面板 3：RDP 会话时间线
# 过滤：destination.port:3389 and event.code:4624 and winlog.event_data.LogonType:10
# 可视化：按 source.ip 的时间线

# 面板 4：新服务安装
# 过滤：event.code:7045
# 聚合：winlog.event_data.ServiceName 的 Terms 聚合

# 面板 5：登录失败峰值检测
# 过滤：event.code:4625
# 聚合：带异常检测的日期直方图

# 导出 Kibana 仪表板
# curl -X GET "elastic-siem:5601/api/saved_objects/_export" \
#   -H "kbn-xsrf: true" \
#   -d '{"type":"dashboard","objects":[{"id":"lateral-movement-dashboard","type":"dashboard"}]}' \
#   > lateral_movement_dashboard.ndjson
```

## 核心概念

| 术语 | 定义 |
|------|------------|
| **横向移动（Lateral Movement）** | MITRE ATT&CK 战术（TA0008），描述攻击者在网络中从一个被入侵系统移动到另一个系统的技术 |
| **哈希传递（Pass-the-Hash，T1550.002）** | 使用捕获的 NTLM 密码哈希向远程系统进行身份验证，无需知道明文密码 |
| **PsExec（T1569.002）** | 远程服务执行工具，在目标系统上创建临时服务，可通过事件 ID 7045 检测 |
| **东西向流量（East-West Traffic）** | 内部系统间的网络通信（相对于内外部网络间的南北向流量） |
| **身份验证异常** | 偏离基线身份验证模式的行为，例如用户登录到以前从未访问过的系统 |
| **Kerberoasting（T1558.003）** | 请求服务账户的 Kerberos 服务票证并离线破解，可通过事件 ID 4769 异常检测 |

## 工具与系统

- **Zeek**：网络安全监控器，生成 SMB、Kerberos、DCE-RPC 和连接日志，用于横向移动分析
- **Splunk/Elastic SIEM**：日志聚合平台，用于关联企业内的身份验证事件、网络流量和服务创建
- **Sigma**：厂商无关的检测规则格式，用于编写可跨 SIEM 平台移植的横向移动检测规则
- **Velociraptor**：终端取证工具，用于从横向移动链中涉及的主机收集证据
- **BloodHound**：活动目录攻击路径分析工具，在攻击者利用前识别潜在的横向移动路径

## 常见场景

### 场景：检测勒索软件操作员的横向移动

**背景**：SOC 在凌晨 2:00 收到文件服务器（10.10.20.15）上创建 PsExec 服务的告警。该告警触发了横向移动调查。组织部署了 Zeek 网络监控和 Windows 事件日志转发至 Splunk。

**方法**：
1. 在 Splunk 中查询 10.10.20.15 上的事件 ID 7045（服务创建），确认 PsExec 执行并识别源 IP（10.10.5.23）
2. 追踪 10.10.5.23 的身份验证历史：查找事件 ID 4624 类型 3 登录，发现该主机在过去一小时内使用 NTLM 向 8 台服务器进行了身份验证（哈希传递模式）
3. 检查 10.10.5.23 的 Zeek conn.log：识别出到 12 台内部主机的 SMB 连接（端口 445）以及到外部 IP 的大量文件传输
4. 构建攻击时间线：凌晨 1:15 通过网络钓鱼完成初始入侵，1:25 转储凭据，1:30-2:00 横向移动到 8 台服务器
5. 通过追踪身份验证链识别所有被入侵主机：10.10.5.23 -> 10.10.20.15 -> 10.10.20.16 -> 10.10.20.17
6. 将所有识别出的主机隔离到 VLAN 999、禁用被入侵账户、封锁外部 C2 IP
7. 报告完整的攻击链，包括时间线、受影响主机和检测盲点

**常见陷阱**：
- 只调查单一告警，而不追踪所有主机上完整的横向移动链
- 在宣布遏制完成前，不检查每台被入侵主机上的持久化机制
- 仅依赖 Windows 事件日志，不关联网络流数据，导致遗漏通过不产生 Windows 事件的工具进行的横向移动
- 未建立正常内部身份验证模式的基线，导致无法进行异常检测

## 输出格式

```
## 横向移动调查报告

**案例 ID**：IR-2024-0312
**初始告警**：10.10.20.15 上的 PsExec，时间 02:00 UTC
**调查周期**：2024-03-15 01:00 至 03:00 UTC

### 攻击时间线

| 时间（UTC） | 来源 | 目标 | 技术 | 证据 |
|------------|--------|-------------|-----------|----------|
| 01:15 | 外部 | 10.10.5.23 | 初始访问（网络钓鱼） | 邮件日志 + HTTP 下载 |
| 01:25 | 10.10.5.23 | 本地 | 凭据转储 | LSASS 访问（Sysmon EID 10） |
| 01:32 | 10.10.5.23 | 10.10.20.15 | 哈希传递（SMB） | EID 4624 类型 3 NTLM |
| 01:38 | 10.10.5.23 | 10.10.20.16 | PsExec | EID 7045 + Zeek SMB |
| 01:45 | 10.10.20.16 | 10.10.20.17 | RDP | EID 4624 类型 10 |
| 02:00 | 10.10.20.17 | 10.10.20.15 | PsExec（触发告警） | EID 7045 |
| 02:10 | 10.10.5.23 | 203.0.113.50 | 数据渗出 | Zeek conn.log 2.3 GB |

### 受影响系统
- 10.10.5.23（workstation-045）- 初始入侵
- 10.10.20.15（file-server-01）- 数据被访问
- 10.10.20.16（app-server-02）- 横穿节点
- 10.10.20.17（db-server-01）- 最终目标

### 检测盲点
1. 初始网络钓鱼邮件未被邮件网关拦截
2. 凭据转储未被检测（无 LSASS 监控）
3. 首次横向移动到告警之间存在 30 分钟间隔
```

