如何用ClientRequestProperties绑定动态应用列表规避KQL注入
用ClientRequestProperties实现动态应用列表的KQL参数绑定(防范注入)
问题背景
现有需重构以防范KQL注入的原始查询:
let apps= dynamic(["a", "a.b.c"]); MainTable | where Day == datetime(2024-06-20) and Region == "region" | where (Component contains "a") or (Component contains "a" and Component contains "b" and Component contains "c") | summarize sum(TotalBytes) * 1.0 / 24 / 60 / 60
当前通过拼接字符串生成where条件的方式存在注入风险:
var appNameFilter = string.Join(" or ", appNames.Select(name => getAppNameParts(name))); private static string getAppNameParts(string app) { var splited = app.Split('.'); return " ( " + string.Join(" and ", splited.Select(name => $"Component contains \"{name}\"")) + " ) "; }
需要改用ClientRequestProperties绑定参数实现动态应用列表过滤,此前尝试使用has_all时遇到错误:has_all(): 无法将参数2转换为标量常量,同时存在内存限制问题。
解决方案
1. 改造KQL查询为参数化模板
将每个应用的拆分片段列表作为动态数组参数传入,用any()+all()组合实现多应用、多片段的匹配逻辑,替代原有的字符串拼接条件:
MainTable | where Day == datetime(@Day) and Region == @Region | where any( app in @AppFragmentLists, all(part in app, Component contains part) ) | summarize sum(TotalBytes) * 1.0 / 24 / 60 / 60
@Day、@Region为常规参数,@AppFragmentLists是核心动态参数,格式为嵌套动态数组,对应原始示例的[["a"], ["a", "b", "c"]]any(...)遍历每个应用的片段列表,只要有一个应用满足匹配条件就保留该行all(...)确保当前行的Component包含该应用的所有拆分片段
2. C#端用ClientRequestProperties绑定参数
在C#代码中,将应用列表转换为嵌套的JArray,通过ClientRequestProperties传递参数,完全规避字符串拼接:
using Microsoft.Azure.Kusto.Data; using Newtonsoft.Json.Linq; // 输入的应用列表 var appNames = new List<string> { "a", "a.b.c" }; // 转换为嵌套JArray:每个应用拆分为片段数组,再组合成大数组 var appFragmentLists = new JArray(appNames.Select(app => new JArray(app.Split('.', StringSplitOptions.RemoveEmptyEntries)) )); // 初始化Kusto客户端(根据实际集群、数据库信息创建) var client = KustoClientFactory.CreateCslQueryProvider(new KustoConnectionStringBuilder("your_cluster_uri", "your_database")); // 设置参数集合 var requestProps = new ClientRequestProperties(); requestProps.SetParameter("Day", new DateTime(2024, 6, 20)); requestProps.SetParameter("Region", "region"); requestProps.SetParameter("AppFragmentLists", appFragmentLists); // 执行参数化查询 var query = @" MainTable | where Day == datetime(@Day) and Region == @Region | where any( app in @AppFragmentLists, all(part in app, Component contains part) ) | summarize sum(TotalBytes) * 1.0 / 24 / 60 / 60 "; var result = client.ExecuteQuery(query, requestProps); // 后续处理查询结果
3. 方案优势
- 彻底杜绝KQL注入:所有用户输入通过参数绑定传递,不直接拼接进查询字符串
- 规避
has_all的限制:用any()+all()组合实现相同逻辑,无类型转换和内存溢出问题 - 动态适配性强:无需修改查询模板,调整参数即可适配任意数量的应用及片段
内容的提问来源于stack exchange,提问作者mohanakrishnavh
相关产品推荐
相关产品推荐

