KQL查询排除美国登录记录失效问题求助
解决KQL查询中仍包含美国登录记录的问题
嘿,我帮你分析下问题出在哪,以及怎么解决~你的原始查询有两个核心问题,导致筛选美国的条件没生效:
1. 先看最明显的语法错误
你把SecurityEvent和SigninLogs两个完全不同的表查询逻辑直接拼在一起了,这不符合KQL的语法规则,相当于让查询逻辑混乱了,后面的LocationDetails != 'United States'根本没被正确应用到目标数据上。
2. 字段使用错误(关键问题)
SigninLogs里的LocationDetails不是字符串,而是一个动态对象,结构大概是这样的:
{"City": "Seattle", "State": "Washington", "CountryOrRegion": "United States"}
你直接拿这个对象和字符串"United States"比较,相当于在问“一个苹果等于香蕉吗?”,结果永远是true(因为不等),但这根本不是你要的筛选逻辑——等于没加这个筛选条件,所以美国的记录自然会被包含进来。
正确的查询方案
根据你的需求,分两种常见场景给你正确的查询:
场景1:查询Azure AD登录日志(SigninLogs)的非美国成功登录
这是最常用的场景,SigninLogs记录了Azure AD的用户登录行为,我们需要提取LocationDetails里的CountryOrRegion子字段来筛选:
SigninLogs | where ResultType == 0 // ResultType=0表示登录成功 and TimeGenerated > ago(1d) // 只查近1天的记录 // 排除美国,同时处理没有地理位置信息的情况(可选,根据你的需求调整) and (isempty(LocationDetails.CountryOrRegion) or LocationDetails.CountryOrRegion != "United States") // 选择你需要展示的字段,比如用户、国家、登录时间、IP | project UserPrincipalName, Country = LocationDetails.CountryOrRegion, TimeGenerated, IPAddress
额外优化:覆盖别名/大小写问题
如果还是有美国的记录,可能是因为国家地区的取值有别名(比如"US")或者大小写不一致,你可以用不区分大小写的比较,同时覆盖常见别名:
SigninLogs | where ResultType == 0 and TimeGenerated > ago(1d) and ( isempty(LocationDetails.CountryOrRegion) or not(tolower(LocationDetails.CountryOrRegion) in ("united states", "us")) ) | project UserPrincipalName, Country = LocationDetails.CountryOrRegion, TimeGenerated, IPAddress
场景2:查询Windows本地登录事件(SecurityEvent)的非美国成功登录
SecurityEvent的4624事件是Windows本地登录成功事件,但这个表本身没有直接的地理位置字段,需要通过IPAddress结合IP地理位置查询来判断:
SecurityEvent | where AccountType == "User" and EventID == 4624 // Windows登录成功事件 and TimeGenerated > ago(1d) and IPAddress != "-" // 排除本地登录(IP为"-"的情况) // 提取纯IP地址(去掉端口部分) | extend CleanIP = tostring(split(IPAddress, ":")[0]) // 使用内置的IP地理位置查询函数获取国家信息 | invoke geo_ip_lookup(CleanIP) // 排除美国的记录 | where Country != "United States" // 展示需要的字段 | project Account, CleanIP, Country, TimeGenerated, LogonType
内容的提问来源于stack exchange,提问作者rk3
相关产品推荐
相关产品推荐

