你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
适用于:✅Microsoft Fabric✅Azure 数据资源管理器✅Azure Monitor✅Microsoft Sentinel
根据路径或边缘数据计算目标节点的曝光外围(列表和分数)。
函数 graph_exposure_perimeter_fl() 是 UDF(用户定义的函数),可用于根据路径或边缘数据计算每个目标节点的曝光外围。 输入数据的每一行都包含一个源节点和一个目标节点,这些节点和目标之间的直接连接(边缘)或它们之间的多跃点路径更长。 如果路径不可用,我们首先可以使用 图形匹配 运算符或 graph_path_discovery_fl() 函数发现它们。 然后,可以在路径发现输出的基础上执行 graph_exposure_perimeter_fl()。
暴露外围表示来自相关源节点的特定目标的可访问性。 访问目标越多,攻击者就越容易受到攻击,因此名称就越暴露。 具有高暴露外围的节点在网络安全域中非常重要,因为它们有可能非法到达,并且受到攻击者的高度重视。 因此,在强化和监视外围方面,应相应地保护高暴露外围的节点。
该函数输出可到达每个目标的已连接源列表,以及表示源编号的分数。 (可选)如果每个源(例如漏洞或公开性)都有有意义的“权重”,则加权分数将计算为源权重的总和。 此外,每个列表中的最大显示目标总数和最大源数的限制将作为可选参数公开,以便更好地控制。
语法
graph_exposure_perimeter_fl(
sourceIdColumnName, targetIdColumnName, [sourceWeightColumnName], [resultCountLimit], [listedIdsLimit])
详细了解
参数
| 名字 | 类型 | 必填 | 描述 |
|---|---|---|---|
| sourceIdColumnName | string |
✔️ | 包含源节点 ID 的列的名称(边缘或路径)。 |
| targetIdColumnName | string |
✔️ | 包含目标节点 ID 的列的名称(边缘或路径)。 |
| sourceWeightColumnName | string |
包含源节点权重(如漏洞)的列的名称。 如果没有相关的权重,则加权分数等于 0。 默认列名为“noWeightsColumn”。 | |
| resultCountLimit | long |
返回的最大行数(按降序分数排序)。 默认值为 100000。 | |
| listedIdsLimit | long |
为每个源列出的目标的最大数目。 默认值为 50。 |
函数定义
可以通过将函数代码嵌入为查询定义的函数,或将其创建为数据库中的存储函数来定义函数,如下所示:
- 查询定义的
- 存储
使用以下 let 语句定义函数。 不需要任何权限。
let exposure_perimeter_fl = (T:(*), sourceIdColumnName:string, targetIdColumnName:string, sourceWeightColumnName:string= 'noWeightsColumn'
, resultCountLimit:long = 100000, listedIdsLimit:long = 50)
{
let paths = (
T
| extend sourceId = column_ifexists(sourceIdColumnName, '')
| extend targetId = column_ifexists(targetIdColumnName, '')
| extend sourceWeight = tolong(column_ifexists(sourceWeightColumnName, 0))
);
let aggregatedPaths = (
paths
| sort by targetId, sourceWeight desc
| summarize exposurePerimeterList = array_slice(make_set_if(sourceId, isnotempty(sourceId)), 0, (listedIdsLimit - 1))
, exposurePerimeterScore = dcountif(sourceId, isnotempty(sourceId))
, exposurePerimeterScoreWeighted = sum(sourceWeight)
by targetId
| extend isExposurePerimeterCapped = (exposurePerimeterScore > listedIdsLimit)
);
aggregatedPaths
| top resultCountLimit by exposurePerimeterScore desc
};
// Write your query to use the function here.
例
以下示例使用 调用运算符 来运行函数。
- 查询定义的
- 存储
若要使用查询定义的函数,请调用嵌入的函数定义之后。
let connections = datatable (SourceNodeName:string, TargetNodeName:string, SourceNodeVulnerability:int)[
'vm-work-1', 'webapp-prd', 0,
'vm-custom', 'webapp-prd', 4,
'webapp-prd', 'vm-custom', 1,
'webapp-prd', 'test-machine', 1,
'vm-custom', 'server-0126', 4,
'vm-custom', 'hub_router', 4,
'webapp-prd', 'hub_router', 2,
'test-machine', 'vm-custom', 5,
'test-machine', 'hub_router', 5,
'hub_router', 'remote_DT', 0,
'vm-work-1', 'storage_main_backup', 0,
'hub_router', 'vm-work-2', 0,
'vm-work-2', 'backup_prc', 1,
'remote_DT', 'backup_prc', 2,
'backup_prc', 'storage_main_backup', 0,
'backup_prc', 'storage_DevBox', 0,
'device_A1', 'sevice_B2', 1,
'sevice_B2', 'device_A1', 2
];
let exposure_perimeter_fl = (T:(*), sourceIdColumnName:string, targetIdColumnName:string, sourceWeightColumnName:string = 'noWeightsColumn'
, resultCountLimit:long = 100000, listedIdsLimit:long = 50)
{
let paths = (
T
| extend sourceId = column_ifexists(sourceIdColumnName, '')
| extend targetId = column_ifexists(targetIdColumnName, '')
| extend sourceWeight = tolong(column_ifexists(sourceWeightColumnName, 0))
);
let aggregatedPaths = (
paths
| sort by targetId, sourceWeight desc
| summarize exposurePerimeterList = array_slice(make_set_if(sourceId, isnotempty(sourceId)), 0, (listedIdsLimit - 1))
, exposurePerimeterScore = dcountif(sourceId, isnotempty(sourceId))
, exposurePerimeterScoreWeighted = sum(sourceWeight)
by targetId
| extend isExposurePerimeterCapped = (exposurePerimeterScore > listedIdsLimit)
);
aggregatedPaths
| top resultCountLimit by exposurePerimeterScore desc
};
connections
| invoke exposure_perimeter_fl(sourceIdColumnName = 'SourceNodeName'
, targetIdColumnName = 'TargetNodeName'
, sourceWeightColumnName = 'SourceNodeVulnerability'
)
输出
| 目标 ID | exposurePerimeterList | exposurePerimeterScore | exposurePerimeterScoreWeighted | isExposurePerimeterCapped |
|---|---|---|---|---|
| hub_router | [“vm-custom”,“webapp-prd”,“test-machine”] | 3 | 11 | 假 |
| storage_main_backup | [“vm-work-1”,“backup_prc”] | 2 | 0 | 假 |
| vm-custom | [“webapp-prd”,“test-machine”] | 2 | 6 | 假 |
| backup_prc | [“vm-work-2”,“remote_DT”] | 2 | 3 | 假 |
| webapp-prd | [“vm-work-1”,“vm-custom”] | 2 | 4 | 假 |
| test-machine | [“webapp-prd”] | 1 | 1 | 假 |
| server-0126 | [“vm-custom”] | 1 | 4 | 假 |
| remote_DT | [“hub_router”] | 1 | 0 | 假 |
| vm-work-2 | [“hub_router”] | 1 | 0 | 假 |
| storage_DevBox | [“backup_prc”] | 1 | 0 | 假 |
| device_A1 | [“sevice_B2”] | 1 | 2 | 假 |
| sevice_B2 | [“device_A1”] | 1 | 1 | 假 |
运行函数按目标聚合源和目标之间的连接或路径。 对于每个目标,曝光外围表示可以作为分数(常规和加权)和列表连接到它的源。
输出中的每个行包含以下字段:
-
targetId:从相关列获取的目标节点的 ID。 -
exposurePerimeterList:可以连接到目标节点的源节点 ID 列表(取自相关列)。 列表上限为 listIdsLimit 参数的最大长度限制。 -
exposurePerimeterScore:分数是可以连接到目标的源节点计数。 高暴露外围分数表示目标节点可从大量源访问,应相应地进行处理。 -
exposurePerimeterScoreWeighted:加权分数是可选源节点的权重列的总和,表示其值,例如漏洞或公开性。 如果存在此类权重,则加权暴露外围分数可能是目标节点值的更准确的指标,因为可能从高度易受攻击或公开的源进行访问。 -
isExposurePerimeterCapped:boolean 标志是否由 listIdsLimit 参数封盖源列表。 如果为 true,则其他源除了列出的源之外,还可以访问目标(最高为 exposurePerimeterScore 的数量)。
在上面的示例中,我们在源和目标之间的连接顶部运行 graph_exposure_perimeter_fl() 函数。 在输出的第一行中,可以看到目标节点“hub_router”可从三个源(“vm-custom”、“webapp-prd”、“test-machine”)进行连接。 我们使用输入数据源NodeVulnerability 列作为源权重,并获取累积权重 11。 此外,由于源数为 3,默认列表限制为 50,因此将显示所有源 ,因此 isExposurePerimeterCapped 列的值为 FALSE。
如果多跃点路径不可用,我们可以在源和目标之间生成多跃点路径(例如,通过运行“graph_path_discovery_fl()”并在结果顶部运行“graph_exposure_perimeter_fl()”。
输出看起来类似,但表示通过多跃点路径计算的曝光外围,因此是目标节点真实可访问性更好的指标。 为了查找源和目标方案(例如中断)之间的完整路径,graph_path_discovery_fl() 函数可用于相关源和目标节点上的筛选器。
函数 graph_exposure_perimeter_fl() 可用于计算目标节点的暴露外围,无论是直接边缘还是较长的路径。 在网络安全域中,它可用于多个见解。 暴露外围分数(常规和加权),表示目标节点从防御者和攻击者的角度的重要性。 具有高暴露外围(尤其是关键边界)的节点应相应地受到保护。 例如,在访问监视和强化方面。 安全信号(如警报)应优先处理可访问这些节点的源。 应监视暴露外围列表,以查找源和目标之间的意外连接,并在中断方案中使用。 例如,如果某些源遭到入侵,则它们与目标之间的连接应断开。