该教程项目旨在帮助安全分析师系统学习在 Microsoft Sentinel Log Analytics 工作区中使用 KQL 进行安全日志分析与威胁狩猎的核心技能。
# 探索 Kusto Query Language (KQL)
## 简介
本实验旨在创建一个详细的指南,以帮助大家理解 Kusto Query Language (KQL) 与 MS Sentinel 集成的强大功能。本课程将向学习者介绍如何使用 Microsoft Sentinel KQL 分析安全日志。作为安全分析师和工程师,我们将安全日志视为宝藏,因为它们可以帮助我们发现基础设施内隐藏的活动。Microsoft Sentinel 是一款云原生安全信息与事件管理 (SIEM) 产品,利用摄取的日志让您更深入地了解环境。另一方面,如果您充满好奇心且喜欢亲自动手,Kusto Query Language (KQL) 将帮助您主动揭示这些日志中隐藏的秘密。
想象一下,您能够:
* 准确追踪恶意用户活动,并在发生之前识别潜在的违规行为
* 通过关联事件并弄清楚攻击者的每一步行动,解开复杂的安全事件
* 自动执行重复性任务,从而专注于更严重的威胁和调查
本指南重点介绍 KQL,它赋予我们安全分析师/工程师成为安全侦探的能力,通过主动狩猎威胁来确保您组织的数字基础设施免受攻击者的侵害。因此,我深入研究 KQL 的工作原理,以发现安全日志分析的强大力量。

图 1
在本指南结束时,读者将掌握使用 Kusto Query Language (KQL) 在 MS Sentinel Log Analytics 工作区中进行安全分析所需的基础知识和技能。
* 更好地理解 Microsoft Sentinel 作为安全信息与事件管理 (SIEM) 解决方案的核心概念和功能。
* 轻松理解在 Microsoft Sentinel 中使用 Kusto Query Language (KQL) 进行日常安全操作的优势。
* 了解 KQL 如何与 MS Sentinel Log Analytics 工作区中存储的数据进行交互,以及其在查询和分析中的用途。
# Microsoft Sentinel 概述
让我们先了解一下 Microsoft Sentinel,因为在深入研究 Kusto Query Language 之前,更好地了解它至关重要。
云计算领域在不断发展,网络犯罪分子总是潜伏在暗处,伺机让安全团队措手不及。正确配置了 MS Sentinel 的组织始终保持警惕,保护自己免受恶意攻击者的侵害,并不知疲倦地确保其数字基础设施免受所有网络威胁。
# Microsoft Sentinel 工作流程

图 2:Microsoft Sentinel 工作流程
```
flowchart LR
A[Data Source] --> B[Collect]
B --> C[Detect]
C --> D[Investigate]
D --> E[Respond]
B --- B1[Collect security data across your enterprise]
C --- C1[Detect previously undetected threats and reduce false positives using analytics and unparalleled threat intelligence.]
D --- D1[Investigate threats with Artificial Intelligence and Machine Learning to hunt for suspicious activities at scale.]
E --- E1[Respond to incidents rapidly with built-in orchestration and automation of common tasks.]
A --- A1[Collect security and event logs at cloud scale across all users, devices, applications, and infrastructure, both on-premises and in multiple clouds.]
```
# Microsoft Sentinel 详解
MS Sentinel 是一个云原生安全信息与事件管理 (SIEM) 解决方案,使安全管理员能够在整个企业环境中更好地检测、调查和响应安全威胁。Sentinel 构建于 Azure 之上,为安全监控、日志收集、威胁检测、响应和调查提供了一个集中式平台。它不仅是 SIEM 解决方案,还是安全编排、自动化和响应 (SOAR) 解决方案,这大大增强了它的功能。
MS Sentinel 可以与 Microsoft 及第三方服务无缝集成,为云端或本地的威胁情报和安全运营创建一个全面的安全生态系统。
## 与 Microsoft 服务的集成
MS Sentinel 提供了预构建的连接器,可轻松与各种 Microsoft 安全服务进行集成,从而消除了复杂的配置需求。以下是与其他 Microsoft 服务的一些关键集成。
* Microsoft Entra ID:Sentinel 与 Entra ID 集成,用于身份保护、身份和访问管理以及威胁检测。您将能够监控用户活动、筛选审计日志、识别可疑的登录尝试,并在配置后强制执行条件访问策略。
* Microsoft Defender:当 Sentinel 与 Microsoft Defender 套件集成时,它将其威胁检测能力扩展到了多个 Azure 资源,如虚拟机、数据库和容器。这种集成允许 Sentinel 使用 Defender 的高级威胁防护功能来进行更全面的安全分析。例如,收集端点安全日志以检测并隔离感染恶意软件的设备,甚至启动自动化响应。
* Azure Logic Apps:Sentinel 可以利用 Azure Logic Apps 来自动化响应和补救工作流。这使得在检测到威胁时,能够协调跨不同服务的复杂响应。
* Azure Monitor:将 Azure Monitor 与 Sentinel 集成,可以摄取来自各种 Microsoft 服务的指标和日志,从而生成全面的安全洞察和分析。
Microsoft Sentinel 还可以使用基于代理的日志收集工具,来收集托管在本地或云端的各个服务器的日志,为您提供更广阔的安全视野。
## 与第三方服务的集成
Microsoft 拥有一个内置数据连接器库,专门用于第三方安全产品,通过处理数据格式和通信协议来简化日志摄取,从而实现无缝摄取。以下是一些
第三方产品的示例,包括但不限于 Palo Alto Networks、CrowdStrike、Fortinet、MacAfee、Splunk、AWS 等。
* Syslog 集成:Syslog 是广泛使用的日志传输标准。Sentinel 可以从支持 Syslog 格式的各种设备、服务器和应用程序中摄取安全数据,在集成各种安全日志时提供了极大的灵活性。
* REST API 集成:对于内置连接器未涵盖的安全解决方案,Sentinel 提供了备用的 REST API。此选项可能需要专家编写自定义脚本或应用程序,与服务 API 进行交互以将数据传输到 Microsoft Sentinel。
## 注意事项
值得一提的是,Microsoft Sentinel 利用 Azure Log Analytics 工作区来存储数据日志。这些日志可能包括来自 Microsoft 服务的日志(如 Office 365、Microsoft Defender 和 Azure 活动),以及第三方日志(如防火墙日志、网络日志、SaaS 应用程序日志等)。
## 问题
* 除了作为 SIEM 解决方案之外,Microsoft Sentinel 还是什么?
答案:SOAR
* MS Sentinel 如何支持内置连接器中未包含的其他安全解决方案?
答案:REST API 集成
## 任务 3
## Kusto Query Language (KQL)
Kusto Query Language 是释放 Microsoft Sentinel 全部潜力的关键,它将帮助您将原始的安全事件转化为可操作的洞察,从而在与恶意行为者的对抗中获得竞争优势。KQL 不仅仅是一种语法。在 Microsoft Sentinel 的背景下,它是发现和引入可疑活动的工具。通过每一次查询,您都可以从海量日志中筛选出有用的信息,检测网络威胁的蛛丝马迹,并将这些线索关联起来,从整个数字资产的日志中获取可操作的洞察。
## KQL 实战
随着网络威胁日益复杂,MS Sentinel 始终严阵以待。它让您深入了解所有恶意活动,并利用 KQL 的强大功能在表格和图表中揭示可疑动向。

图 3
通过每一次查询,输出结果都能让您更深入地了解每一个恶意活动,安全团队随后可以根据这些结果采取行动,加固其数字资产的防御。
# KQL 详解
Kusto Query Language 由 Microsoft 开发,用于查询大量的结构化、半结构化和非结构化数据。它最初是为 Azure Data Explorer 创建的,但已被广泛应用于各种 Microsoft 服务,包括 Azure Monitor、Azure Sentinel、Microsoft 365 Defender 等。值得注意的是,KQL 查询是在存储引入日志的日志存储库(在本例中为 Log Analytics 工作区)上运行的。
对 KQL 的一个简单描述是,它是一种:
1. 安全分析语言:用于过滤、搜索和分析安全日志及事件。
2. 强大且灵活的工具:用于运行简单和复杂的查询,以提取详细的安全洞察。
3. 用于大型数据集的工具:专门优化以处理海量的安全日志。
4. Microsoft Sentinel 的内置工具:无缝集成以进行数据探索和威胁狩猎。
5. 用于其他 Microsoft 服务的工具:如 Azure Data Explorer、Log Analytics、Azure Monitor 和 Azure Sentinel。
在警惕的安全管理员手中,KQL 将帮助揭示基础设施内可能隐藏威胁的区域,进而为团队带来安心。
## Kusto Query Language 编辑器

图 4:KQL 查询
## KQL 查询示例
以下是 KQL 查询的可能形式:
Heartbeat
| summarize AggregatedHeartbeatCount = count() by Computer
| order by AggregatedHeartbeatCount desc
| take 10

图 5:KQL 查询
# 解释
* 此查询从 Heartbeat 表中检索数据,该表通常包含有关组织内设备或系统的健康和状态信息。
* 然后,summarize 运算符通过计算每台唯一计算机的心跳数来聚合数据。
* 随后,结果将根据聚合的心跳数按降序输出。
* 最后,take 运算符将输出限制为心跳次数最高的前 10 台计算机。
## 问题
* KQL 最初是为哪种服务创建的?
答案:Azure Data Explorer
* 分析任务中的示例查询。该查询将返回多少台计算机?
答案:10 台计算机
* 示例查询正在从哪个表检索数据?
答案:Heartbeat 表
# Microsoft Sentinel 中的 KQL 概念
既然我们已经介绍了 MS Sentinel 和 KQL,我们需要熟悉一些关键概念,以全面掌握 KQL 是如何查询和分析摄入的日志的。
## 表
由于日志存储库(Log Analytics 工作区)使用表来管理摄入的各种日志,每个表通常与特定的数据源相关联。例如:
* 安全事件日志
* Azure 活动日志
* Windows 防火墙日志
* 网络监控日志
* 或任何自定义数据源。
这些表就是您在运行 KQL 查询时所查询的对象。注意:自定义日志的名称以 _CL 结尾

图 6:自定义日志
自定义日志
AzureNetworkAnalytics_CL
AzureNetworkAnalyticsIPDetai..
ManagementPackHistory_CL
ServiceMapComputer_CL
ServiceMapProcess_CL
WorkloadEvents_CL
WorkloadHealthState_CL
WorkloadPerformance_CL
# 示例

图 7:KQL 查询
上面的查询显示了过去 24 小时内 SecurityEvent 日志表中的所有安全事件。
# 函数和运算符
函数和运算符是执行操作的符号或关键字,例如对摄入的日志执行特定任务或计算。它们用于操作、聚合、过滤、转换或分析数据,通常通过名称或自定义参数来调用。
## 示例
count(), sum(), avg(), where(), parse()
== - (等于)
!= - (不等于)
< - (小于)
render
summarize
`|` - (管道)
## 表达式
表达式是值、函数、运算符和表名的组合,用于计算得出一个有意义的单元。它定义了条件、计算、转换和其他操作。
## 示例

图 8:KQL 查询

图 9:KQL 查询表

图 10:KQL 查询表
# 解释
| 运算符/函数 |
描述 |
示例 |
| search |
在指定表中搜索匹配的值或模式 |
search "failed" |
| where |
根据指定条件过滤指定的表 |
SigninLogs | where EventID == "4624" |
| take |
用于限制结果集中返回的行数 |
SigninLogs | take 5 |
| sort |
根据指定列按升序或降序对记录进行排序 |
SigninLogs | sort by TimeGenerated, Identity desc | take 5 |
| ago |
返回相对于查询执行时间的时间偏移量 |
ago(1h) |
| print |
输出包含一个或多个标量表达式的单行 |
print bin(4.5, 1) |
| project |
从表中选择特定列 |
Perf | project ObjectName, CounterValue, CounterName |
| extend |
用于创建新的计算列并将其添加到结果集中 |
Perf | extend AlertThreshold = 80 |
| count |
计算表中的记录数 |
SecurityAlert | count() |
# KQL 快速参考
本文展示了一系列函数及其描述,以帮助我更深入地使用 Kusto Query Language。
展开表格
| 运算符/函数 |
描述 |
语法 |
| 过滤/搜索/条件 |
通过过滤或搜索查找相关数据 |
|
| where |
基于特定谓词进行过滤 |
T | where Predicate |
| where contains/has |
Contains:查找任何子字符串匹配 Has:查找特定词(性能更好) |
T | where col1 contains/has "[search term]" |
| 运算符/函数 |
描述 |
语法 |
| search |
在表的所有列中搜索该值 |
[TabularSource |] search [kind=CaseSensitivity] [in (TableSources)] SearchPredicate |
| take |
返回指定数量的记录。用于测试查询。注意: take 和 limit 是同义词。 |
T | take NumberOfRows |
| case |
添加条件语句,类似于其他系统中的 if/then/elseif。 |
case(predicate_1, then_1, predicate_2, then_2, predicate_3, then_3, else) |
| distinct |
生成一个包含输入表各列中不同组合的表 |
distinct [ColumnName], [ColumnName] |
| 日期/时间 |
使用日期和时间函数的操作 |
|
| ago |
返回相对于查询执行时间的时间偏移量。例如,ago(1h) 是当前时钟读数前的一小时。 |
ago(a_timespan) |
| format_datetime |
返回各种日期格式的数据。 |
format_datetime(datetime , format) |
| bin |
将时间范围内的所有值进行舍入并对它们进行分组 |
bin(value,roundTo) |
| 创建/删除列 |
在表中添加或删除列 |
|
| print |
输出包含一个或多个标量表达式的单行 |
print [ColumnName =] ScalarExpression [', ...] |
| project |
按指定顺序选择要包含的列 |
T | project ColumnName [= Expression] [, ...] Or T | project [ColumnName [(ColumnName[,]) =] Expression [, ...] |
| project-away |
选择要从输出中排除的列 |
T | project-away ColumnNameOrPattern [, ...] |
| project-keep |
选择要在输出中保留的列 |
T | project-keep ColumnNameOrPattern [, ...] |
| 运算符/函数 |
描述 |
语法 |
| project-rename |
重命名结果输出中的列 |
T | project-rename new_column_name = column_name |
| project-reorder |
重新排序结果输出中的列 |
T | project-reorder Col2, Col1, Col* asc |
| extend |
创建一个计算列并将其添加到结果集中 |
T | extend [ColumnName | (ColumnName[, ...]) =] Expression [, ...] |
| 排序和聚合数据集 |
通过以有意义的方式对数据进行排序或分组来重构数据 |
|
| sort operator |
按一列或多列以升序或降序对输入表的行进行排序 |
T | sort by expression1 [asc|desc], expression2 [asc|desc], ... |
| top |
返回使用 by 对数据集进行排序后的前 N 行 |
T | top numberOfRows by expression [asc|desc] [nulls first|last] |
| summarize |
根据 by 组列对行进行分组,并计算每个组的聚合 |
T | summarize [[Column =] Aggregation [, ...]] [by [Column =] GroupExpression [, ...]] |
| count |
计算输入表(例如 T)中的记录数。此运算符是 summarize count() 的简写形式 |
T | count |
| join |
通过匹配每个表中的指定列的值来合并两个表的行,形成一个新表。支持各种 join 类型:fullouter, inner, innerunique, leftanti, leftantisemi, leftouter, leftsemi, rightanti, rightantisemi, rightouter, rightsemi |
LeftTable | join [JoinParameters] ( RightTable ) on Attributes |
| union |
接受两个或多个表并返回其所有行 |
[T1] | union [T2], [T3], ... |
| range |
生成一个包含算术级数的表 |
range columnName from start to stop step step |
| 格式化数据 |
对数据进行重组以有用的方式输出 |
|
| 运算符/函数 |
描述 |
语法 |
| lookup |
使用维度表中查找到的值来扩展事实表的列 |
T1 | lookup [kind = (leftouter|inner)] ( T2 ) on Attributes |
|
| mv-expand |
将动态数组转换为行(多值扩展) |
T | mv-expand Column |
|
| parse |
计算字符串表达式并将其值解析为一个或多个计算列。用于结构化非结构化数据。 |
T | parse [kind=regex [flags=regex_flags] |simple|relaxed] Expression with * (StringConstant ColumnName [: ColumnType]) *... |
|
| make-series |
沿着指定的轴创建特定聚合值的序列 |
T | make-series [MakeSeriesParamters] [Column =] Aggregation [default = DefaultValue] [, ...] on AxisColumn from start to end step step [by [Column =] GroupExpression [, ...]] |
|
| let |
将名称绑定到可以引用其绑定值的表达式。值可以是 lambda 表达式,用于创建作为查询一部分的由查询定义的函数。使用 let 可以在表上创建表达式,其结果看起来像一张新表。 |
let Name = ScalarExpression | TabularExpression | FunctionDefinitionExpression |
|
| 常规 |
其他操作和函数 |
|
|
| invoke |
在其接收到的作为输入的表上运行函数。 |
T | invoke function([param1, param2]) |
|
| evaluate pluginName |
计算查询语言扩展(插件) |
[T |] evaluate [ evaluateParameters ] PluginName ( [PluginArg1 [, PluginArg2]... ) |
|
| 可视化 |
以图形格式显示数据的操作 |
|
|
| render |
将结果渲染为图形输出 |
T | render Visualization [with (PropertyName = PropertyValue [, ...] )] |
|
# 注意
管道 | 用于分隔查询的每一行。
总而言之,函数和运算符是对摄入的日志执行操作的符号或关键字,而表达式是值、函数和运算符的组合,用于计算得出单个单元。这些元素对于 KQL 至关重要,使安全分析师能够有效地分析和操作安全日志。
## 问题
* 什么运算符可用于以图形形式输出结果?
答案:render
* 什么运算符可用于根据指定条件过滤指定的表?
答案:Where
* 在我们上面的第二个示例查询中,查询的是哪个用户帐户名?
答案:JBOX$
## 任务 5
# KQL 语句结构
## 结构
在上一个任务中,我们讨论了编写 KQL 查询时的一些关键概念。让我们把它们组合起来构成一条语句。
KQL 语句的结构由多个组件组成,使您能够有效地检索、操作和分析安全日志。您可以从一个数据源开始,通过由管道 | 分隔符绑定的一组运算符进行操作。
以下是结合多个查询组件的查询典型示例
| SecurityEvent |
|
where TimeGenerated > ago(1d) |
|
|
summarize EventCount = count() by Computer |
|
|
order by EventCount desc |
limit 10 |

图 11:KQL 查询
# 解释
* 数据源:数据源指定要从中检索数据的表。
* SecurityEvent - 指定从中检索数据的表。
* 条件:用于对数据执行特定操作。
* `where TimeGenerated > ago(1d)` - 过滤数据,以仅包含在过去 24 小时 `ago(1d)` 内发生的事件。这确保仅分析最近的事件。
* `summarize EventCount = count() by Computer` - 按 `Computer` 列聚合过滤后的事件,并计算每台设备的事件数。
* 输出:定义您希望如何查看输出结果。
* `order by EventCount desc` - 按 `EventCount` 列以降序 `desc` 对聚合数据进行排序。
* `limit 10` - 将输出限制为安全事件数量最多的前 10 台设备。
理解了上面提到的查询后,如果出现登录提示,您可以结合 **Demo Log Analytics**(在新标签页中打开)和您的实验室凭据进行尝试,如任务 3 所述。此外,请记住将模式切换为 KQL。

图 12:KQL 查询
# 问题
* 我们示例查询中查询的表名称是什么?
答案:SecurityEvent
分析任务中的示例查询。该查询针对每台计算机聚合了什么内容?
* 答案:EventCount
# KQL 使用案例
现在我已经清楚地了解了 KQL 查询的概念和结构,我打算探索一些实际场景,看看 KQL 如何帮助我作为安全分析师从安全日志中获得更深入的洞察。
**场景:** 今天在办公室,您需要识别特定用户帐户的失败登录尝试,以调查潜在未经授权的访问。
**解决方案:** 要识别失败的登录尝试,您可以使用以下查询在 `SecurityEvent` 表中搜索失败的登录尝试。这将在整个组织范围内查找所有失败的登录尝试。您可以修改时间范围以扩大搜索范围。
| SecurityEvent |
|
|
where EventID == 4625 |

图 13:KQL 查询
然后,为了专注于特定用户帐户的失败登录尝试,您可以向查询添加一个过滤器,如下所示:
# SecurityEvent
`| where EventID == 4625 and TargetUserName contains "admin"`

图 14:KQL 查询
您还可以缩小结果范围,查看过去一小时内的失败登录尝试,如下所示:
| SecurityEvent |
| where EventID == 4625 and TargetUserName contains "admin" |
| where TimeGenerated > ago(1h) |

图 15:KQL 查询
请注意查询的演进过程,以及如何应用额外的语句为我们提供经过细化和特定的结果;在上面的输出中,过去一小时内没有结果。我们可以通过不同方式修改此查询,以达到我们想要的目的。KQL 的应用没有上限。
# KQL 技术使用案例
以下是 Microsoft Sentinel 中的一些 KQL 技术使用案例:
* 调查安全事件:您可以使用 KQL 分析安全警报,通过查询相关日志来查明事件的根本原因并调查攻击时间线。
* 狩猎恶意软件:KQL 查询可用于检测异常并搜索与恶意软件相关的可疑活动,例如恶意文件下载、异常的注册表更改或网络操纵。
* 检测横向移动:KQL 可以识别来自不同设备或位置的可疑用户登录,这可能表明存在未经授权的访问和您网络内的横向移动。
* 监控用户活动:作为安全分析师,您可以使用 KQL 查询审查登录尝试、访问模式和特权用户活动,这有助于检测帐户滥用或入侵。
* 安全运营自动化:安全管理员可以通过将 KQL 查询集成到工作流中,并根据查询结果触发警报、通知或补救措施,从而实现安全运营和事件响应的自动化。
* 告警:在 Microsoft Sentinel 中,可以使用 KQL 查询创建自定义警报,通过在查询中指定特定条件来通知您可能发生的安全事件。此外,还可以从查询开始在 KQL 中创建警报规则。
* 日志分析和报告:此外,您可以使用 KQL 查询提取和分析安全日志,创建自定义报告以确定您当前的安全态势、使用情况和性能指标、合规性要求以及威胁趋势。

图 16:KQL 查询
## 问题
* 在第一个查询中,我们在 SecurityEvent 表中搜索的是什么?
答案:失败的登录尝试
* 在第二个查询中,我们使用哪个运算符将搜索范围缩小到了一系列用户帐户中?答案:TargetUserName 列?
答案:Contains
# 总结
我们将 MS Sentinel 探讨为一种强大的 SIEM 解决方案,它使组织能够轻松识别、调查和响应安全威胁。另一方面,KQL 是查询和分析安全日志的有效方法。两者结合在一起,就构成了一个全面的安全运营工具,用于保护现代数字基础设施。
对 KQL 的不断探索越多,您就越能发现它在提升组织整体安全态势方面的广泛能力。
# 学习曲线
要成为一名熟练的安全分析师和威胁猎人,这里有一些入门指南:
* 从简单开始:** 从基本查询开始,以识别核心安全事件,随着自信心的增强,逐步过渡到更复杂的查询。
* **熟能生巧:** 练习编写 KQL 查询的次数越多,您就会变得越游刃有余和专业。
* **释放潜力:** 随着 KQL 熟练程度的提高,您可以深入研究 join、parse 和用户定义函数等高级概念。这为复杂数据分析和威胁狩猎场景提供了更强大的功能。
# 即将开展的项目
我即将推出的大型动手实践项目将重点关注 Microsoft 安全产品,以了解扩展检测与响应 (XDR) 如何结合来自以下支柱的信号来检测和缓解威胁:
* Microsoft Defender XDR 威胁防护
* Microsoft Sentinel
* 为 Microsoft Sentinel 创建 KQL 查询
* Microsoft Defender for Endpoint 威胁缓解
* Microsoft Defender for Cloud Apps
* Microsoft Purview 威胁缓解
* Microsoft Security Copilot 威胁缓解