什么是 CodeQL?
CodeQL 是开发人员用于自动执行安全检查,安全研究人员用于执行变体分析的分析引擎。
在 CodeQL 中,代码被视为数据。 安全漏洞、bug 和其他错误建模为可针对从代码中提取的数据库执行的查询。 可以运行由 GitHub 研究人员和社区参与者编写的标准 CodeQL 查询,也可以编写自己的查询以用于自定义分析。 查找潜在 bug 的查询会直接在源文件中突出显示结果。
在此单元中,你将了解 CodeQL 静态分析工具,以及它如何使用数据库、查询套件和查询语言包来执行变体分析。
变体分析
变体分析是使用已知安全漏洞作为种子在代码中查找类似问题的过程。 这是安全工程师用来识别潜在漏洞并确保这些威胁跨多个代码库正确修复的技术。
使用 CodeQL 查询代码是执行变体分析的最高效方法。 可以使用标准 CodeQL 查询来识别种子漏洞,或者通过编写自己的自定义 CodeQL 查询来查找新漏洞。 然后可以开发或循环访问查询,以自动查找使用传统手动技术可能错过的同一 bug 的逻辑变体。
CodeQL 数据库
CodeQL 数据库包含从代码库中提取的关于单个编程语言在特定时间点的可查询数据。 数据库包含代码的完整分层表示形式,包括抽象语法树、数据流图和控制流图的表示形式。
每种语言都有其自己的唯一数据库架构,该架构定义用于创建数据库的关系。 该架构在提取过程中执行的初始词法分析与 CodeQL 查询评估器的实际复杂分析之间提供了一个接口。 例如,架构指定每个语言构造都有一个表。
对于每种语言,CodeQL 库都会定义类以在数据库表上提供一个抽象层。 这提供了一个面向对象的数据视图,使编写查询更加容易。
例如,在 Java 程序的 CodeQL 数据库中,两个键表为:
expressions
表,其中包含在生成过程中分析的源代码中每个表达式对应的行。statements
表,包含构建过程中每个被分析的源代码语句对应的行。
CodeQL 库定义类,用于在其中每个表上提供一个抽象层(以及相关辅助表):Expr
和 Stmt
。
查询套件
CodeQL 查询套件提供了一种根据查询的文件名、元数据属性或磁盘或 QL 包中的位置选择查询的方法。 为想要在 CodeQL 分析中经常使用的查询创建查询套件。
使用查询套件,可将多个查询传递给 CodeQL,而无需单独指定每个查询文件的路径。 查询套件定义存储在扩展名为 .qls
的 YAML 文件中。 套件定义是一系列指令,其中每条指令都是带有(通常)单个键的 YAML 映射。 指令按它们在查询套件定义中的显示顺序执行。 执行套件定义中所有指令后,结果为一组选定的查询。
默认查询套件
CodeQL 包括两个内置查询套件:
default
:这些是在 GitHub 上的 CodeQL 代码扫描中默认运行的查询,在代码扫描的默认设置中可用。 此查询套件中的查询高度精确,返回的误报代码扫描结果很少。 相对于security-extended
查询套件,默认套件返回的低置信度代码扫描结果更少。security-extended
:此套件包含default
套件中的所有查询,以及精度和严重性略低的额外安全查询。 它在默认设置代码扫描时可用,并在查询套件下拉列表中列为“扩展”选项。 相对于default
查询套件,此套件可能会返回更多的误报代码扫描结果。
代码扫描的默认设置将使用 default
查询套件。 可以通过选择溢出图标来查看 CodeQL 配置,然后选择“编辑”按钮来更改此设置。 在“扫描设置”下,可以选择作为查询套件概述的两个选项之一。
CodeQL 包
CodedQL 包用于组织 CodeQL 分析中使用的文件,以便你可以轻松创建、共享、依赖和运行 CodeQL 查询和库。 它们包含查询、库文件、查询套件和重要元数据。 使用 CodeQL 包和 CodeQL CLI 中的包管理命令,可以发布自定义查询并将其集成到代码库分析中。
CodeQL 包有三种类型:查询包、库包和模型包。
- 查询包是为运行而设计的。 发布查询包时,除了查询源外,捆绑包还包括每个查询的所有可传递依赖项和预编译表示形式。 这可确保一致且高效地执行包中的查询。
- 库包设计为供查询包(或其他库包)使用,并且不包含查询本身。 库不会单独编译。
- 模型包可用于扩展代码扫描分析,以包含默认情况下不支持的依赖项。 模型包目前为 beta 版,可能会发生更改。 在 beta 版本中,模型包可用于存储库级别的 Java 分析。 有关创建自己的模型包的详细信息,请参阅“创建 CodeQL 模型包”。
CodeQL 包结构
CodeQL CLI 可用于使用 pack init
命令开发和发布包。 此命令将创建所需的目录结构和文件,包括在其根目录中名为 qlpack.yml
的主文件。 每个 qlpack.yml
文件中的元数据会告知 CodeQL 如何编译包中的任何查询、包所依赖的库,以及查找查询套件定义的位置。
CodeQL 包的内容(CodeQL 分析中使用的查询或库)包含在与 qlpack.yml
相同的目录或其子目录中。
包含 qlpack.yml 文件的目录会充当 CodeQL 包内容的根目录。 也就是说,对于 .ql
包中的所有文件和 .qll
s 文件,CodeQL 将解析与包含包根目录中qlpack.yml文件的目录相关的所有导入语句。
下面是一个示例 qlpack.yml
文件:
name: codeql/java-queries
version: 0.0.6-dev
groups: java
suites: codeql-suites
extractor: java
defaultSuiteFile: codeql-suites/java-code-scanning.qls
dependencies:
codeql/java-all: "*"
codeql/suite-helpers: "*"
有关创建和发布自己的 CodeQL 包的详细信息,请参阅“发布和使用 CodeQL 包”。[1]