| name | performing-user-behavior-analytics |
| description | 执行用户和实体行为分析(UEBA),通过基于 SIEM 的行为基线和统计分析, 检测异常用户活动,包括不可能旅行、异常访问模式、权限滥用和内部威胁。 适用于 SOC 团队通过偏离既定行为规范来识别被攻陷账户或内部威胁。
|
| domain | cybersecurity |
| subdomain | soc-operations |
| tags | ["soc","ueba","user-behavior","insider-threat","anomaly-detection","splunk","baseline"] |
| version | 1.0 |
| author | mahipal |
| license | Apache-2.0 |
执行用户行为分析
适用场景
以下情况使用本技能:
- SOC 团队需要通过异常认证模式检测被攻陷账户
- 内部威胁项目需要超出基于规则检测的行为监控
- 不可能旅行或地理异常表明凭据已被入侵
- 特权账户监控需要基线偏差检测
不适用于作为纪律处分的唯一依据 —— UEBA 发现是需要调查的指标,而非恶意意图的证明。
前置条件
- 具有 30 天以上认证和访问日志历史的 SIEM,用于基线创建
- VPN、O365 和 Active Directory 认证日志规范化为 CIM
- 用于基于位置的异常检测的 GeoIP 数据库(MaxMind GeoLite2)
- 身份丰富数据(部门、角色、上级、典型工作时间)
- 具有 UBA 模块的 Splunk Enterprise Security 或等效的 UEBA 能力
工作流程
步骤 1:建立用户认证基线
从历史数据创建行为基线:
index=auth sourcetype IN ("o365:management:activity", "vpn_logs", "WinEventLog:Security")
earliest=-30d latest=-1d
| stats dc(src_ip) AS unique_ips,
dc(src_country) AS unique_countries,
dc(app) AS unique_apps,
count AS total_logins,
earliest(_time) AS first_login,
latest(_time) AS last_login,
values(src_country) AS countries,
avg(eval(strftime(_time, "%H"))) AS avg_login_hour,
stdev(eval(strftime(_time, "%H"))) AS stdev_login_hour
by user
| eval avg_daily_logins = round(total_logins / 30, 1)
| eval login_hour_range = round(avg_login_hour, 0)." +/- ".round(stdev_login_hour, 1)." 小时"
| table user, unique_ips, unique_countries, unique_apps, avg_daily_logins,
login_hour_range, countries
步骤 2:检测不可能旅行
识别在不可能的时间内从地理位置相距遥远的地点进行的登录:
index=auth sourcetype IN ("o365:management:activity", "vpn_logs")
action=success earliest=-24h
| iplocation src_ip
| sort user, _time
| streamstats current=f last(lat) AS prev_lat, last(lon) AS prev_lon,
last(_time) AS prev_time, last(City) AS prev_city,
last(Country) AS prev_country, last(src_ip) AS prev_ip
by user
| where isnotnull(prev_lat)
| eval distance_km = round(
6371 * acos(
cos(pi()/180 * lat) * cos(pi()/180 * prev_lat) *
cos(pi()/180 * (lon - prev_lon)) +
sin(pi()/180 * lat) * sin(pi()/180 * prev_lat)
), 0)
| eval time_diff_hours = round((_time - prev_time) / 3600, 2)
| eval speed_kmh = if(time_diff_hours > 0, round(distance_km / time_diff_hours, 0), 0)
| where speed_kmh > 900 AND distance_km > 500
| eval alert = "不可能旅行: ".prev_city.", ".prev_country." -> ".City.", ".Country
| table _time, user, prev_city, prev_country, City, Country, distance_km,
time_diff_hours, speed_kmh, alert
| sort - speed_kmh
步骤 3:检测异常登录时间
识别用户正常工作时间之外的登录:
index=auth action=success earliest=-7d
| eval hour = strftime(_time, "%H")
| eval day_of_week = strftime(_time, "%A")
| eval is_weekend = if(day_of_week IN ("Saturday", "Sunday"), 1, 0)
| eval is_off_hours = if(hour < 6 OR hour > 22, 1, 0)
| join user type=left [
search index=auth action=success earliest=-60d latest=-7d
| eval hour = strftime(_time, "%H")
| stats avg(hour) AS baseline_avg_hour, stdev(hour) AS baseline_stdev_hour,
perc95(hour) AS baseline_latest_hour by user
]
| where (is_off_hours=1 OR is_weekend=1) AND
(hour > baseline_latest_hour + 2 OR hour < baseline_avg_hour - baseline_stdev_hour * 2)
| stats count, values(hour) AS login_hours, values(day_of_week) AS login_days,
values(src_ip) AS source_ips
by user, baseline_avg_hour, baseline_latest_hour
| where count > 0
| sort - count
步骤 4:检测异常数据访问模式
监控异常文件或数据库访问量:
index=file_access OR index=sharepoint earliest=-24h
| stats sum(bytes) AS total_bytes, dc(file_path) AS unique_files,
count AS access_count by user
| join user type=left [
search index=file_access OR index=sharepoint earliest=-30d latest=-1d
| stats avg(eval(count)) AS baseline_avg_files,
stdev(eval(count)) AS baseline_stdev_files,
avg(eval(sum(bytes))) AS baseline_avg_bytes
by user
]
| eval bytes_gb = round(total_bytes / 1073741824, 2)
| eval z_score_files = round((unique_files - baseline_avg_files) / baseline_stdev_files, 2)
| where z_score_files > 3 OR bytes_gb > 5
| eval anomaly_level = case(
z_score_files > 5, "严重",
z_score_files > 3, "高",
bytes_gb > 10, "严重",
bytes_gb > 5, "高",
1=1, "中"
)
| sort - z_score_files
| table user, unique_files, bytes_gb, baseline_avg_files, z_score_files, anomaly_level
步骤 5:检测权限滥用模式
监控特权账户使用异常:
index=wineventlog sourcetype="WinEventLog:Security"
(EventCode=4672 OR EventCode=4624 OR EventCode=4648) earliest=-24h
| eval is_privileged = if(EventCode=4672, 1, 0)
| eval is_explicit_cred = if(EventCode=4648, 1, 0)
| stats sum(is_privileged) AS priv_events,
sum(is_explicit_cred) AS explicit_cred_events,
dc(ComputerName) AS unique_hosts,
values(ComputerName) AS hosts_accessed
by TargetUserName, src_ip
| join TargetUserName type=left [
search index=wineventlog EventCode IN (4672, 4624, 4648) earliest=-30d latest=-1d
| stats dc(ComputerName) AS baseline_hosts,
avg(eval(count)) AS baseline_daily_events by TargetUserName
]
| where unique_hosts > baseline_hosts * 2 OR priv_events > baseline_daily_events * 3
| eval risk_score = (unique_hosts / baseline_hosts * 30) + (priv_events / baseline_daily_events * 20)
| sort - risk_score
| table TargetUserName, src_ip, unique_hosts, baseline_hosts, priv_events,
baseline_daily_events, risk_score, hosts_accessed
步骤 6:生成风险评分并优先排序调查
将所有 UEBA 信号聚合为综合风险评分:
| inputlookup ueba_impossible_travel.csv
| append [| inputlookup ueba_off_hours_access.csv]
| append [| inputlookup ueba_data_access_anomaly.csv]
| append [| inputlookup ueba_privilege_abuse.csv]
| stats sum(risk_points) AS total_risk,
values(anomaly_type) AS anomaly_types,
dc(anomaly_type) AS anomaly_count
by user
| lookup identity_lookup_expanded identity AS user
OUTPUT department, managedBy, priority AS user_priority
| eval final_risk = total_risk * case(
user_priority="critical", 2.0,
user_priority="high", 1.5,
user_priority="medium", 1.0,
1=1, 0.8
)
| sort - final_risk
| head 20
| table user, department, managedBy, anomaly_types, anomaly_count, total_risk, final_risk
核心概念
| 术语 | 定义 |
|---|
| UEBA | 用户和实体行为分析(User and Entity Behavior Analytics)——针对既定基线检测异常的行为分析 |
| 不可能旅行 | 在使物理旅行不可能的时间框架内,从地理位置相距遥远的地点进行的登录事件 |
| 行为基线 | 从 30-90 天历史数据建立的用户正常活动模式的统计画像 |
| Z 分数 | 统计量,衡量观测值偏离均值的标准差数量——值 > 3 表示异常 |
| 风险评分 | 聚合多种行为异常并按资产重要性加权的综合数值评分 |
| 同伴组分析 | 将用户行为与同部门/角色的其他人进行比较以识别离群值 |
工具与系统
- Splunk UBA:与 Splunk ES 集成的专用用户行为分析模块,提供 ML 驱动的异常检测
- Microsoft Sentinel UEBA:Azure Sentinel 中的内置 UEBA 功能,具有实体页面和调查图
- Exabeam Advanced Analytics:独立 UEBA 平台,具有会话拼接和自动时间线创建
- Securonix:云原生 SIEM/UEBA,具有针对内部威胁检测的预建行为模型
常见场景
- 账户被攻陷:不可能旅行 + 非工作时间登录 + 异常应用访问 = 可能的凭据被攻陷
- 内部数据窃取:员工在离职前通知期内访问正常文件量的 10 倍
- 权限提升滥用:管理员账户从异常位置访问正常范围之外的系统
- 共享账户检测:服务账户同时从多个地理位置登录
- 休眠账户重新激活:90 天以上无活动的账户突然执行特权操作
输出格式
UEBA 异常报告 — 每周汇总
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
时间段: 2024-03-11 至 2024-03-17
基线用户数: 2,847
检测异常数: 23
高风险用户排名:
# 用户 部门 风险 异常
1. jsmith 财务 94.5 不可能旅行(纽约->莫斯科,2小时)、非工作时间访问、下载 15GB
2. admin_svc01 IT 运维 82.0 从 12 个新 IP 登录,访问 47 台主机(基线:8)
3. mwilson 人力资源 67.3 非工作时间文件访问(凌晨 2 点),下载量是正常的 3 倍
调查状态:
jsmith: 已上报 Tier 2 — 可能账户被攻陷(IR-2024-0445)
admin_svc01:审查中 — 可能是新的自动化部署(与 IT 运维确认中)
mwilson: 等待人力资源背景信息 — 员工在通知期内,已加强监控