拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

CodeQL C 分析 1.19 改进全解:Autobuilder 构建定位、控制流图优化与新安全查询

CodeQL C 分析 1.19 改进全解:Autobuilder 构建定位、控制流图优化与新安全查询 静态分析SAST应用安全漏洞扫描代码质量【免费下载链接】codeqlCodeQL: the libraries and queries that power security researchers around the world, as well as code scanning in GitHub Advanced Security项目地址https://gitcode.com/gh_mirrors/co/codeql点击查看免费下载导读本文以 CodeQL 仓库中 C# 语言分析的 1.19 版本变更说明change-notes/1.19/analysis-csharp.md为核心系统梳理该版本在 Autobuilder 构建定位策略、控制流图CFG构造、新增与改进的查询、代码提取以及 QL 库 API 五个方面的技术改进。通过结合 csharp 目录下的提取器、Autobuilder 与查询源码读者可以理解这些变更背后的实现机制掌握新查询cs/uncontrolled-format-string与cs/use-of-vulnerable-package的检测逻辑并了解getArgument()、isInArgument()等 QL 库 API 的语义变化从而更有效地编写和调试针对 C# 的 CodeQL 查询。变更总览1.19 版本对 C# 分析栈的改进覆盖了从代码提取、数据库构建到查询执行的完整链路层面关键变更Autobuilder按.proj→.sln→.csproj/.vcxproj的顺序定位构建目标同类型多文件时优先使用最靠近仓库根目录的文件控制流图对局部变量的简单布尔条件进行路径敏感分析常量失败断言如Debug.Assert(false)之后的代码视为不可达新查询新增不受控格式字符串、已知漏洞依赖包两条安全查询既有查询XSS 与锁顺序查询扩大检出范围局部变量遮蔽成员查询减少误报代码提取支持in参数提取修复dynamic类型名与方法类型签名提取缺陷QL 库AccessorCall.getArgument()支持元组赋值新增AssignableAccess.isInArgument()Autobuilder 改进构建目标定位策略查找顺序与优先级在 1.19 版本中C# 提取器的 Autobuilder 在确定msbuild或dotnet build的构建目标时采用了新的查找顺序首先查找.proj文件其次查找.sln解决方案文件最后查找.csproj/.vcxproj项目文件。上述三类文件在查找时若同一类型存在多个文件则选择最靠近仓库根目录的那一个用于构建。这一策略保证了在多项目仓库中构建入口选择的确定性——根目录级别的解决方案或项目通常代表整个仓库的主构建目标。源码验证该逻辑在 csharp/autobuilder/Semmle.Autobuild.Shared/Autobuilder.cs 中有直接实现查找顺序与变更说明完全一致// First look for .proj files ret FindFiles(.proj, f new ProjectTAutobuildOptions(this, f))?.ToList(); // Then look for .sln files ret FindFiles(.sln, f new SolutionTAutobuildOptions(this, f, false))?.ToList(); // Then look for language specific solution files, e.g. .slnx files ... // Finally look for language specific project files, e.g. .csproj files同时Project.cs 中的注释也明确指出Project类统一表示.proj文件、C# 的.csproj文件以及 C 的.vcxproj文件因此该策略同时适用于 C# 与 C 的自动构建。注结合源码可以推断后续版本还在此基础上加入了.slnx语言特定解决方案文件的查找步骤1.19 的变更说明则主要记录了.proj/.sln/.csproj/.vcxproj三级顺序的确立。控制流图改进路径敏感与不可达代码简单布尔条件的路径敏感分析控制流图CFG构造现在会考虑局部作用域变量上的简单布尔条件。变更说明给出的例子if (b) x 0; if (b) x 1;在这段代码中CFG 现在能够反映如下事实第一个条件取true或false分支意味着第二个相同条件也必然取相同分支。因此第一个赋值x 0会被识别为死代码dead code——因为无论b取何值第二个if都会覆盖第一个赋值的结果。这一改进让 CodeQL 的“无用赋值”类查询以及依赖 CFG 可达性的其他分析对简单布尔状态传播更加精确减少了因缺乏路径敏感信息而漏报或误报的情况。常量失败断言之后的不可达代码代码中仅能通过常量失败的断言如Debug.Assert(false)到达的部分现在被视作不可达。这意味着位于Debug.Assert(false)之后的代码不会再参与数据流分析的可达路径相关的未使用变量、不可达语句等告警会更准确。该语义与 C# 运行时行为一致Debug.Assert在条件恒为false时必然触发断言失败其后的代码在正常执行流中永远无法到达。新增查询一不受控格式字符串cs/uncontrolled-format-string查询目的新查询cs/uncontrolled-format-string安全标签对应 CWE-134Use of Externally-Controlled Format String用于发现远程输入流入String.Format格式字符串的数据流路径。格式字符串中混入不受信任的输入可能导致异常抛出、拒绝服务DoS等安全后果。该查询的结果默认展示在 LGTM 上。查询实现剖析完整查询位于 csharp/ql/src/Security Features/CWE-134/UncontrolledFormatString.ql其元数据与核心逻辑如下/** * name Uncontrolled format string * description Passing untrusted format strings from remote data sources can throw exceptions * and cause a denial of service. * kind path-problem * problem.severity error * security-severity 7.3 * precision high * id cs/uncontrolled-format-string * tags security * external/cwe/cwe-134 */ import csharp import semmle.code.csharp.security.dataflow.flowsources.FlowSources import semmle.code.csharp.frameworks.Format import FormatString::PathGraph module FormatStringConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof ActiveThreatModelSource } predicate isSink(DataFlow::Node sink) { sink.asExpr() any(FormatStringParseCall call).getFormatExpr() } }实现要点数据流配置采用TaintTracking::GlobalFormatStringConfig全局污点追踪通过DataFlow::ConfigSig定义 source 与 sinkSourceActiveThreatModelSource即威胁模型下的活跃远程输入源与仓库的安全威胁模型配置联动Sink任何FormatStringParseCall调用的格式字符串表达式即call.getFormatExpr()输出select sink.getNode(), source, sink, This format string depends on $., source.getNode(), ...以路径问题path-problem形式呈现完整污点传播链。底层库支撑Format.qllsink 的定义依赖 csharp/ql/lib/semmle/code/csharp/frameworks/Format.qll 中的抽象类体系。FormatStringParseCall是解析格式字符串的方法调用如string.Format()的统一抽象其子类包括FormatCall格式化字符串的方法调用getFormatExpr()返回第getFormatArgument()个参数ParseFormatStringCall解析格式字符串的方法调用。FormatMethod抽象类进一步处理不同 API 的差异——例如string.Format(IFormatProvider, ...)重载的格式字符串参数位置是1而不是0见 Format.qlloverride int getFormatArgument() { if this.getParameter(0).getType() instanceof SystemIFormatProviderInterface then result 1 else result 0 }因此无论调用的是带IFormatProvider的重载还是普通重载sink 都能准确定位格式字符串参数避免因重载差异产生漏报。新增查询二使用含已知漏洞的包cs/use-of-vulnerable-package查询目的新查询cs/use-of-vulnerable-package安全标签对应 CWE-937Using Components with Known Vulnerabilities用于发现导入已知漏洞包的构建文件。它扫描项目构建文件如.csproj、packages.config等中的包引用与已知漏洞数据库比对后报告风险。该查询的结果同样默认展示在 LGTM 上。后续演进说明从仓库历史记录看该查询在后续版本对应 csharp/old-change-notes/2021-03-24-remove-vuln-package-query.md中被移除原因可以从仓库结构推断现代 CodeQL C# 分析已转向通过数据流与威胁模型覆盖供应链安全问题依赖漏洞检测能力并入统一的包安全体系如 GitHub 的依赖审查。对于 1.19 版本而言该查询仍然是依赖安全扫描的重要组成部分其思路静态比对构建文件中的包版本与漏洞库至今仍是供应链安全审计的基础手段。既有查询变更1.19 版本对三条既有查询做了行为调整查询预期影响变更内容Cross-site scriptingcs/web/xss更多结果现在能够发现 ASP.NET Core 应用程序中的跨站脚本漏洞Inconsistent lock sequencecs/inconsistent-lock-sequence更多结果现在能够跨调用全局发现不一致的锁顺序Local scope variable shadows membercs/local-shadows-member更少结果移除了构造函数参数遮蔽成员的情况——因为该参数通常用于初始化成员XSS 查询扩展至 ASP.NET CoreXSS 查询位于 csharp/ql/src/Security Features/CWE-079/XSS.ql其元数据确认了查询 ID 为cs/web/xss标签覆盖external/cwe/cwe-079与external/cwe/cwe-116/** * name Cross-site scripting * description Writing user input directly to a web page * allows for a cross-site scripting vulnerability. * kind path-problem * problem.severity error * security-severity 7.8 * precision high * id cs/web/xss * tags security * external/cwe/cwe-079 * external/cwe/cwe-116 */ import csharp import semmle.code.csharp.security.dataflow.XSSQuery import PathGraph from XssNode source, XssNode sink, string message where xssFlow(source, sink, message) select sink, source, sink, $ flows to here and message, source, User-provided value查询通过XSSQuery库中的xssFlow谓词完成数据流追踪。“更多结果”意味着 1.19 中该数据流配置新增了对 ASP.NET CoreRazor 页面、MVC 视图输出等的 sink/source 建模使得原本只在传统 ASP.NETWeb Forms中被识别的 XSS 路径现在也能覆盖到 ASP.NET Core 应用中。锁顺序查询扩大至全局跨调用cs/inconsistent-lock-sequence查询实现在 csharp/ql/src/Concurrency/LockOrder.ql用于检测不一致的加锁顺序这是经典死锁成因之一。变更后该查询从“仅单方法内”的锁顺序分析扩展为跨调用全局分析即能够沿着方法调用链追踪锁的获取顺序从而发现跨多个方法、多个类之间形成环路的锁序不一致问题。局部变量遮蔽成员查询减少误报cs/local-shadows-member查询位于 csharp/ql/src/Bad Practices/Declarations/LocalScopeVariableShadowsMember.ql。1.19 移除了构造函数参数遮蔽成员的结果——这是有意的误报削减构造函数中形如public Person(string name) { this.name name; }的写法是惯用法参数与成员同名并不构成可读性风险。这一改动使查询专注于真正令人困惑的遮蔽场景如局部变量无意间遮蔽了字段或属性。代码提取变更1.19 版本对 C# 提取器做了三处修正与增强支持in参数提取使用in关键字传递的参数现在会被正确提取。in是 C# 7.2 引入的只读引用传递修饰符语义上介于ref与值传递之间此前提取器未能完整建模该参数传递形式。修复dynamic类型名提取缺陷在特定情况下dynamic类型名未被正确提取的 bug 已修复。dynamic在元数据层面的特殊处理它在编译期表现为object并附带DynamicAttribute容易导致类型名解析出错。修复方法类型签名提取缺陷某些情况下方法类型签名method type signature被错误提取的 bug 已修复。方法类型签名直接影响重载解析与调用图构建此修复提升了数据流与调用分析的准确性。这些提取层面的修复保证了 QL 数据库TRAP 文件中类型与参数信息的完整性是上游查询精度提升的基础。QL 库变更AccessorCall.getArgument() 支持元组赋值AccessorCall上的getArgument()方法得到增强现在会将元组赋值纳入考量。元数据访问器property accessor的隐式value参数位置计算更准确对于属性P的 setter 中隐式value参数在元组赋值(P, x) (0, 1)中其参数索引为0对于复合赋值compound assignmentvalue参数现在只取展开后的值。例如P 7中value参数是P 7而非7。这一语义修正让依赖访问器参数的数据流分析如属性写入追踪在元组赋值与复合赋值场景下不再丢失或混淆传播值。从源码看AccessorCall定义于 csharp/ql/lib/semmle/code/csharp/exprs/Call.qll而PropertyCall的getArgument通过AssignableInternal::getAccessorCallValueArgument(this)计算 value 参数见 Call.qll该内部谓词正是处理元组赋值与复合赋值展开逻辑的位置。新增 AssignableAccess.isInArgument()AssignableAccess类新增谓词isInArgument()该谓词对作为in参数传递的可赋值表达式成立。实现位于 csharp/ql/lib/semmle/code/csharp/exprs/Access.qll/** * Holds if this access passes the assignable being accessed as an in * argument in a method call. */ predicate isInArgument() { expr_argument(this, 3) }这与提取器对in参数的支持见上文“代码提取变更”相互呼应提取器在 TRAP 层面将in参数标记为第三种参数传递模式expr_argument的第三个参数取值为3QL 库则通过isInArgument()向查询作者暴露这一信息。与之并列的还有isRefArgument()、isOutArgument()与isOutOrRefArgument()共同构成完整的参数传递修饰符查询 API。实践建议与总结升级后的构建定位行为在包含多解决方案或多项目文件的仓库中执行codeql database create时Autobuilder 会按.proj→.sln→.csproj/.vcxproj顺序并选择最接近根目录的目标。若希望构建特定项目建议在仓库根目录保留对应的解决方案文件或在配置中显式指定构建命令。新查询的接入方式cs/uncontrolled-format-string与cs/use-of-vulnerable-package均已随 1.19 的 C# 查询包发布。执行默认查询套件codeql query run或 CI 中的 code scanning即可自动纳入也可通过查询 ID 单独运行例如针对格式化字符串数据流进行专项审计。查询编写者收益isInArgument()与改进后的getArgument()让涉及in参数和访问器调用的数据流/污点追踪更加精确控制流图对布尔条件的路径敏感分析则提升了死代码类查询与不可达代码分析的准确性。追溯查询行为变化查询 ID 是稳定的标识符如cs/inconsistent-lock-sequence、cs/local-shadows-member可在 csharp/ql/src 与 csharp/ql/lib/CHANGELOG.md 中持续追踪其后续行为演变。综合来看CodeQL 1.19 的 C# 分析改进体现了“提取精度 → 库 API → 查询能力”的纵向联动提取器对in参数与类型签名的修复为 QL 库提供了更完整的事实基础QL 库的 API 增强getArgument、isInArgument则让新查询与既有查询XSS、锁顺序能够覆盖更广的代码形态最终以更少误报、更多真阳性的方式呈现给安全研究者。赞分享静态分析SAST应用安全漏洞扫描代码质量【免费下载链接】codeqlCodeQL: the libraries and queries that power security researchers around the world, as well as code scanning in GitHub Advanced Security项目地址https://gitcode.com/gh_mirrors/co/codeql点击查看免费下载相关推荐CodeQL 1.18 C 分析改进全解新查询、查询重构与 QL 库 API 演进CodeQL 1.18 C 分析改进全解新查询、查询重构与 QL 库 API 演进 导读 本文以 CodeQL 仓库的 change notes/1.18/a静态分析SAST应用安全漏洞扫描代码质量CodeQL Python 分析能力升级详解CFG 语义重构、新安全查询与提取器改进1.19 版本CodeQL Python 分析能力升级详解CFG 语义重构、新安全查询与提取器改进1.19 版本 导读 本文以 CodeQL 仓库 change not静态分析SAST应用安全漏洞扫描代码质量CodeQL 1.23 C/C 分析改进详解新查询、查询精度调整与数据流库重构CodeQL 1.23 C/C 分析改进详解新查询、查询精度调整与数据流库重构 本指南基于 CodeQL 开源仓库中 change notes/1.23/静态分析SAST应用安全漏洞扫描代码质量创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表