You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Kusto查询语言(KQL)识别Azure AD B2C中特定登录操作序列的恶意活动问题求助

使用Kusto查询语言(KQL)识别Azure AD B2C中特定登录操作序列的恶意活动问题求助

我完全理解你的困扰!你之前的查询确实能筛选出经历过所有四个操作的用户,但它没有验证这些操作是否严格按照你指定的顺序(Validate local account credentials→Update user→Reset user password→Update StsRefreshTokenValidFrom Timestamp)发生——这就是为什么你会得到不符合预期的结果,因为summarize countif()只关心操作是否存在,完全不考虑时间先后顺序。

要解决这个问题,我们需要追踪每个用户操作的时间序列,并检测其中是否包含你要找的连续操作顺序。这里推荐使用KQL的scan运算符,它专门用于识别事件流中的特定序列模式,非常适合你的场景。

下面是修改后的查询代码,我会逐段解释它的作用:

AuditLogs
// 第一步:提取需要的字段,给每个操作分配顺序编号,过滤掉无关操作
| extend OperationOrder = case(
    OperationName == "Validate local account credentials", 1,
    OperationName == "Update user", 2,
    OperationName == "Reset user password", 3,
    OperationName == "Update StsRefreshTokenValidFrom Timestamp", 4,
    0 // 标记无关操作,后续过滤掉
)
| where OperationOrder != 0 // 只保留我们关心的四个操作
| extend UserPrincipalName = tostring(parse_json(TargetResources)[0].userPrincipalName)
| project UserPrincipalName, OperationOrder, TimeGenerated

// 第二步:按用户和时间排序,确保操作按发生顺序排列
| order by UserPrincipalName asc, TimeGenerated asc

// 第三步:使用scan检测每个用户的操作序列中是否存在1→2→3→4的连续顺序
| scan declare (is_match:bool=false) with (
    step s1: UserPrincipalName != prev(UserPrincipalName) => is_match = false; // 切换用户时重置匹配状态
    step s2: OperationOrder == 1 => is_match = false; // 遇到操作1,准备开始匹配序列
    step s3: OperationOrder == 2 and prev(OperationOrder) == 1 => is_match = false; // 操作1之后到操作2,继续
    step s4: OperationOrder == 3 and prev(OperationOrder) == 2 => is_match = false; // 操作2之后到操作3,继续
    step s5: OperationOrder == 4 and prev(OperationOrder) == 3 => is_match = true; // 操作3之后到操作4,标记为匹配
)
// 第四步:筛选出匹配的用户,并去重(避免同一个用户多次触发序列导致重复结果)
| where is_match == true
| distinct UserPrincipalName

代码解释:

  1. 初始过滤与字段提取:和你原来的逻辑类似,给目标操作分配编号,同时过滤掉无关操作,提取用户主体名和时间戳。
  2. 排序:确保每个用户的操作严格按照时间先后顺序排列,这是检测序列的前提。
  3. scan运算符:这是核心部分,它会逐个检查每个用户的操作流:
    • 当切换到新用户时,重置匹配状态;
    • 依次检测操作1→2→3→4的连续出现,只有当这四个操作按顺序连续发生时,才会标记is_match为true。
  4. 去重输出:最后筛选出匹配的用户,并去重,避免同一个用户多次触发序列导致重复结果。

如果你需要允许操作之间存在其他无关操作(比如四个目标操作按顺序出现,但中间夹杂了其他不相关的操作),可以稍微调整scan的逻辑,比如:

// 允许目标序列中间夹杂其他操作的版本
| scan declare (match_stage:int=0) with (
    step reset: UserPrincipalName != prev(UserPrincipalName) => match_stage = 0;
    step look_for_1: OperationOrder == 1 => match_stage = 1;
    step look_for_2: match_stage == 1 and OperationOrder == 2 => match_stage = 2;
    step look_for_3: match_stage == 2 and OperationOrder == 3 => match_stage = 3;
    step found_match: match_stage == 3 and OperationOrder == 4 => match_stage = 4;
)
| where match_stage == 4
| distinct UserPrincipalName

这个版本会忽略目标序列之间的其他操作,只要四个目标操作按1→2→3→4的顺序出现(不管中间有没有其他操作),就会被识别出来。

备注:内容来源于stack exchange,提问作者girish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.20 09:09:51