Detects lateral movement in enterprise networks by analyzing auth logs, network traffic, SMB/RDP sessions using Zeek, Velociraptor, SIEM rules. Builds Splunk/Elastic queries for PsExec, pass-the-hash, RDP pivots.
npx claudepluginhub killvxk/cybersecurity-skills-zhThis skill uses the workspace's default tool permissions.
- 监控企业网络中的入侵后横向移动(lateral movement)模式(哈希传递(pass-the-hash)、RDP 跳转、PSExec)
Detects lateral movement techniques like pass-the-hash, RDP hopping, PSExec in enterprise networks by analyzing auth logs, flows, SMB/RDP via Zeek, Velociraptor, SIEM rules.
Detects lateral movement techniques like pass-the-hash, RDP hopping, and PsExec in enterprise networks by analyzing auth logs, flows, SMB, and RDP with Zeek, Velociraptor, and SIEM rules.
Detects lateral movement techniques like Pass-the-Hash, PsExec, WMI execution, RDP transfers, and SMB propagation using SIEM SPL queries on Windows event logs, Sysmon, and network flows. Maps to MITRE ATT&CK TA0008.
Share bugs, ideas, or general feedback.
不适用场景:替代终端检测与响应(EDR)工具;仅监控南北向流量而忽略内部流量;在没有正常内部通信模式基线的情况下使用。
# 需收集的 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
# 横向移动检测的 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)
# 横向移动检测的 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
# 检测 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
# 狩猎 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
# 横向移动响应的 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
# 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 异常检测 |
背景:SOC 在凌晨 2:00 收到文件服务器(10.10.20.15)上创建 PsExec 服务的告警。该告警触发了横向移动调查。组织部署了 Zeek 网络监控和 Windows 事件日志转发至 Splunk。
方法:
常见陷阱:
## 横向移动调查报告
**案例 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 分钟间隔