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

如何在Azure Sentinel中实现Azure IP范围白名单并对比CIDR与CallerIP

问题描述

我有一个用于获取Azure公网IP范围的KQL查询,需要把这些IP范围加入到检测可疑资源部署的现有警报白名单中:

// Pulling Azure IPs from link and parsing them in to a readable format for query.
let AzureIPRangesPublicCloud = (externaldata(changeNumber:string, cloud:string, values: dynamic)
[@"https://download.microsoft.com/download/7/1/D/71D86715-5596-4529-9B13-DA13A5DE5B63/ServiceTags_Public_20240722.json"]
with (format="multijson"));
let AzureSubnetRangeWhitelist = AzureIPRangesPublicCloud
| mvexpand values
| extend addressPrefixes = parse_json(parse_json(values).properties).addressPrefixes
| mvexpand addressPrefixes
| project  addressPrefixes;
AzureSubnetRangeWhitelist

另外,我还有一个检测可疑资源部署的查询:

// Add or remove operation names below as per your requirements.
let szOperationNames = dynamic(["Microsoft.Compute/virtualMachines/write", "Microsoft.Resources/deployments/write", "Microsoft.Resources/subscriptions/resourceGroups/write"]);
let starttime = 14d;
let endtime = 1d;
let RareCaller = AzureActivity
| where TimeGenerated between (ago(starttime) .. ago(endtime))
| where OperationNameValue in~ (szOperationNames)
| summarize count() by CallerIpAddress, Caller, OperationNameValue, bin(TimeGenerated,1d)
// Returns all the records from the right side that don't have matches from the left.
| join kind=rightantisemi (
AzureActivity
| where TimeGenerated > ago(endtime)
| where OperationNameValue in~ (szOperationNames)
| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), ActivityTimeStamp = make_set(TimeGenerated,100), ActivityStatusValue = make_set(ActivityStatusValue,100), CorrelationIds = make_set(CorrelationId,100), ResourceGroups = make_set(ResourceGroup,100), ResourceIds = make_set(_ResourceId,100), ActivityCountByCallerIPAddress = count()
by CallerIpAddress, Caller, OperationNameValue) on CallerIpAddress, Caller, OperationNameValue;
RareCaller
| extend Name = iif(Caller has '@',tostring(split(Caller,'@',0)[0]),"")
| extend UPNSuffix = iif(Caller has '@',tostring(split(Caller,'@',1)[0]),"")
| extend AadUserId = iif(Caller !has '@',Caller,"")

请问如何将格式为4.145.74.52/30的addressPrefixes与CallerIpAddress进行对比,从而将落在该JSON文件IP范围内的CallerIpAddress加入白名单,避免触发警报?


解决方案

使用KQL的ipv4_is_in_range()函数判断单个IP是否属于CIDR范围,再将白名单逻辑整合到可疑资源检测查询中即可实现需求。具体实现如下:

整合后的完整查询

// 获取Azure公网IP范围白名单
let AzureIPRangesPublicCloud = (externaldata(changeNumber:string, cloud:string, values: dynamic)
[@"https://download.microsoft.com/download/7/1/D/71D86715-5596-4529-9B13-DA13A5DE5B63/ServiceTags_Public_20240722.json"]
with (format="multijson"));
let AzureSubnetRangeWhitelist = AzureIPRangesPublicCloud
| mvexpand values
| extend addressPrefixes = parse_json(parse_json(values).properties).addressPrefixes
| mvexpand addressPrefixes
| project CIDRRange = tostring(addressPrefixes); // 确保格式为字符串类型CIDR

// 可疑资源部署检测(含白名单过滤)
let szOperationNames = dynamic(["Microsoft.Compute/virtualMachines/write", "Microsoft.Resources/deployments/write", "Microsoft.Resources/subscriptions/resourceGroups/write"]);
let starttime = 14d;
let endtime = 1d;
let RareCaller = AzureActivity
| where TimeGenerated between (ago(starttime) .. ago(endtime))
| where OperationNameValue in~ (szOperationNames)
| summarize count() by CallerIpAddress, Caller, OperationNameValue, bin(TimeGenerated,1d)
| join kind=rightantisemi (
    AzureActivity
    | where TimeGenerated > ago(endtime)
    | where OperationNameValue in~ (szOperationNames)
    // 过滤白名单IP范围:排除落在Azure IP范围内的请求
    | join kind=leftanti (AzureSubnetRangeWhitelist | extend dummy=1) on dummy
    | where ipv4_is_in_range(CallerIpAddress, CIDRRange) == false
    | summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), ActivityTimeStamp = make_set(TimeGenerated,100), ActivityStatusValue = make_set(ActivityStatusValue,100), CorrelationIds = make_set(CorrelationId,100), ResourceGroups = make_set(ResourceGroup,100), ResourceIds = make_set(_ResourceId,100), ActivityCountByCallerIPAddress = count()
    by CallerIpAddress, Caller, OperationNameValue
) on CallerIpAddress, Caller, OperationNameValue;
RareCaller
| extend Name = iif(Caller has '@',tostring(split(Caller,'@',0)[0]),"")
| extend UPNSuffix = iif(Caller has '@',tostring(split(Caller,'@',1)[0]),"")
| extend AadUserId = iif(Caller !has '@',Caller,"")

核心逻辑说明

  • ipv4_is_in_range():校验CallerIpAddress是否属于指定的CIDR范围,返回布尔值。
  • leftanti连接:将白名单范围与请求日志关联,过滤掉所有在白名单内的IP请求,仅保留可疑的非白名单请求。
  • 类型转换:将addressPrefixes转为字符串类型的CIDRRange,确保函数能正确解析格式。

可选优化:针对特定服务标签白名单

如果只需白名单特定Azure服务的IP范围(如AzureCloud),可在白名单查询中添加过滤条件:

let AzureSubnetRangeWhitelist = AzureIPRangesPublicCloud
| mvexpand values
| extend serviceTag = parse_json(values).name
| extend addressPrefixes = parse_json(parse_json(values).properties).addressPrefixes
| where serviceTag == "AzureCloud" // 指定目标服务标签
| mvexpand addressPrefixes
| project CIDRRange = tostring(addressPrefixes);

内容的提问来源于stack exchange,提问作者Rachel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 16:59:53