goubx/sentinel-impossible-travel-detection
GitHub: goubx/sentinel-impossible-travel-detection
该项目是一个 Microsoft Sentinel 安全检测与事件响应实验,利用 KQL 分析 Azure AD 登录日志来检测不可能的旅行登录活动,并按 NIST SP 800-61 框架完成事件分类与处置。
Stars: 0 | Forks: 0
# 在 Microsoft Sentinel 中检测不可能的旅行登录
这是一个基于 Microsoft Sentinel 构建的检测工程和事件响应实验室。本项目创建了一个计划分析规则,用于标记在短时间窗口内从过多地理区域登录的帐户(不可能的旅行),然后对每个被标记的帐户进行分类,并按照 NIST SP 800-61 生命周期对事件进行处理直至关闭。
| | |
|---|---|
| **SIEM** | Microsoft Sentinel |
| **遥测数据源** | Azure AD 登录 (SigninLogs) |
| **查询语言** | KQL |
| **IR 框架** | NIST SP 800-61 |
| **战术** | 初始访问 |
| **MITRE 技术** | T1078 有效账户, T1078.004 云账户 |
| **结果** | 在对标记的帐户进行分类后,得出 1 个真阳性(帐户已禁用),4 个良性阳性 |
## 目录
- [概述](#overview)
- [检测工作原理](#how-the-detection-works)
- [第 1 部分:分析规则](#part-1-the-analytics-rule)
- [第 2 部分:触发警报](#part-2-triggering-the-alert)
- [第 3 部分:处理事件 (NIST SP 800-61)](#part-3-working-the-incident-nist-sp-800-61)
- [MITRE ATT&CK 映射](#mitre-attck-mapping)
- [经验教训](#lessons-learned)
- [文件](#files)
## 概述
许多组织都有禁止从未批准的区域登录、共享帐户或使用非企业 VPN 的策略。不可能的旅行检测会标记其登录位置相距过远,以至于在间隔时间内物理上不可能到达的用户,这可能表明凭据被盗、帐户被共享或使用了 VPN。
这种检测的难点在于它天生就容易产生噪音。许多命中是完全可以接受的,例如某人从两个相邻的城市登录。因此,真正的技能不仅仅是触发警报,而是对每个被标记的帐户进行分类,并决定哪些是良性的,哪些是真正的威胁。本实验室构建了检测规则,并随后执行了这一分类过程。
## 检测工作原理
当用户通过其 Azure 帐户进行身份验证时,会向 `SigninLogs` 表写入一条记录,该记录会转发到 Microsoft Sentinel 背后的 Log Analytics 工作区。计划分析规则会计算每个用户在特定时间窗口内登录的不同位置数量,并标记任何超过允许区域数量的用户。
## 第 1 部分:分析规则
此检测会标记在 7 天时间窗口内从超过两个不同地理位置登录的任何用户。
```
let TimePeriodThreshold = timespan(7d);
let NumberOfDifferentLocationsAllowed = 2;
SigninLogs
| where TimeGenerated > ago(TimePeriodThreshold)
| summarize Count = count() by UserPrincipalName, UserId, City = tostring(parse_json(LocationDetails).city), State = tostring(parse_json(LocationDetails).state), Country = tostring(parse_json(LocationDetails).countryOrRegion)
| project UserPrincipalName, UserId, City, State, Country
| summarize PotentialImpossibleTravelInstances = count() by UserPrincipalName, UserId
| where PotentialImpossibleTravelInstances > NumberOfDifferentLocationsAllowed
```
**规则配置:**
| 设置 | 值 |
|---------|-------|
| 状态 | 已启用 |
| 运行频率 | 每 4 小时 |
| 检测窗口 | 7 天(在查询中定义) |
| 位置阈值 | 超过 2 个不同地区 |
| 事件创建 | 自动 |
| 警报分组 | 每 24 小时生成单个事件 |
| 警报后停止查询 | 是 |
**实体映射:**
| 实体 | 标识符 | 值 |
|--------|-----------|-------|
| 账户 | AadUserId | UserId |
| 账户 | DisplayName | UserPrincipalName |
**规则上的 MITRE 映射:** T1078 有效账户,包括 T1078.004 云账户。
## 第 2 部分:触发警报
从虚拟机内部登录 Azure 门户会在 `SigninLogs` 表中生成登录事件。结合整个环境中现有的登录历史记录,该规则获得了足够的位置数据进行评估,并标记了登录跨度超过两个地区的帐户。
## 第 3 部分:处理事件 (NIST SP 800-61)
### 准备阶段
在调查之前已部署了工具和程序:使用 Microsoft Sentinel 进行检测和事件管理,以 Azure AD 登录数据作为来源,并可在需要时使用 Entra ID 进行帐户封堵。
### 检测与分析
该规则标记了 33 个存在潜在不可能旅行的帐户。前五个帐户被作为代表性样本进行分类,对每个帐户进行了单独调查,以确定警报是良性的还是真正的威胁。
针对每个帐户的调查使用了以下查询,以提取特定用户的完整登录地理位置:
```
let TargetUserPrincipalName = "";
let TimePeriodThreshold = timespan(7d);
SigninLogs
| where TimeGenerated > ago(TimePeriodThreshold)
| where UserPrincipalName == TargetUserPrincipalName
| project TimeGenerated, UserPrincipalName, UserId, City = tostring(parse_json(LocationDetails).city), State = tostring(parse_json(LocationDetails).state), Country = tostring(parse_json(LocationDetails).countryOrRegion)
| order by TimeGenerated desc
```
**分类结果:**
| 帐户 | 登录模式 | 结论 |
|---------|-----------------|---------|
| 帐户 1 | 多次登录发生在约 3 小时火车车程内,同一国家 | 良性阳性 |
| 帐户 2 | 圣何塞和旧金山,相距约一小时 | 良性阳性 |
| 帐户 3 | 都在同一个州,最多约一小时的行程 | 良性阳性 |
| 帐户 4 | 两个不同的州,但城市之间仅相距约 25 分钟 | 良性阳性 |
| 帐户 5 | 同一天内多次从不同国家(美国、英国、泰国)登录 | 真阳性 |
前四个帐户是现实的人类活动。相邻城市、短途驾车、人类确实可以实现的一日游。帐户 5 则不同:一天之内在美国、英国和泰国登录,这对于一个人来说在物理上是不可能的。这是一个帐户被盗或共享的强烈信号。
### 遏制、根除和恢复
- 帐户 1 到 4 保持原样。该行为是预期内的,不构成威胁,因此禁用它们只会造成不必要的干扰。
- 帐户 5 被确定为真阳性。该帐户已在 Entra ID 中被禁用,并联系了管理层。
- 这里没有恶意软件类型的威胁需要清除。下一步是确定该帐户是否遭到入侵,因此正在进行更深入的调查,切入到 `AzureActivity` 日志中,查看该帐户使用其 Azure 对象 ID 还执行了哪些操作。
### 事件后活动
- 建议实施地理围栏或条件访问策略,以阻止来自批准区域之外的登录,从而从源头上防止此类活动。这在实验室环境中无法配置,但在生产环境中是正确的控制措施。
- 调查结果和各帐户的结论已随事件一起记录。
### 关闭
事件得到了处理并关闭,被归类为**真阳性**,这是由帐户 5 确认的不可能旅行所导致的。其他四个帐户被记录为良性阳性:检测正确触发了,但底层的活动是正常的。这种分离正是“不可能旅行”规则的核心意义所在,它筛选出供人类判断的候选对象,而不是单方面确认威胁。
## MITRE ATT&CK 映射
| 战术 | 技术 | ID | 证据 |
|--------|-----------|----|----|
| 初始访问 | 有效账户 | T1078 | 从地理上不可能的位置使用有效凭据登录 |
| 初始访问 | 有效账户:云账户 | T1078.004 | 一天内从多个国家进行 Azure AD 云登录 |
## 经验教训
**此检测能捕获什么,及其局限性:**
- 不可能旅行能筛选出登录地理位置对不上的帐户,这可能意味着凭据被盗、帐户被共享或使用了 VPN。它的优势在于广度,缺点是噪音大。这里的五个帐户中有四个是良性的,因此该规则只有与严格的分类相结合时才有用。
- 判断决策至关重要:区分两个相邻的城市(良性)和一天内的三个国家(真正的威胁)是分析师的工作,而不是规则的职责。
**什么能预防或减少这种情况:**
- 阻止从批准区域之外登录的条件访问或地理围栏策略,可以在不可能旅行活动演变成事件之前将其阻止。
- 即使登录确实来自意外的位置,强制实施 MFA 也能降低凭据被盗造成的影响。
**什么能让检测更敏锐:**
- 将两次登录之间的时间和距离作为考量因素,以便规则本身可以抑制明显的良性情况(相邻城市),并优先处理真正不可能的情况,从而减轻分类工作量。
## 文件
- `README.md` - 本说明文档
- `analytics-rule.kql` - Sentinel 规则背后的检测查询
- `investigation.kql` - 用于对每个标记帐户进行分类的单用户查询
由 Mohamed Yagoub 撰写的威胁狩猎和 SOC 调查持续系列的一部分。
标签:KQL, Microsoft Sentinel, 安全运营, 扫描框架