CodeQL 概览
CodeQL是一个静态代码分析引擎,用来给半自动化检查代码中可能存在的漏洞和bug。使用 CodeQL 进行代码审计包括下面三个步骤:
- 从源代码中提取必备信息,然后创建 codeql 数据库
- 用他人编写好 or 自定义的 ql 语句进行查询
- 解释分析查询结果
创建数据库
创建数据库通常使用固定的命令:
1 | codeql database create /codeql-dbs/example-repo --language=<language-label> --source-root /checkouts/example-repo |
当然不同语言存在差异,可以以编译型 / 非编译型进行区分,可以参考:为 CodeQL 分析准备代码
非编译型语言
非编译型语言构成的项目,其数据库的构建方式通常比较简单,指定源码文件夹和输出文件夹即可。
Javascript 和 typescript 项目
1 | codeql database create --language=javascript-typescript --source-root <folder-to-extract> <output-folder>/javascript-database |
Python 项目
1 | codeql database create --language=python <output-folder>/python-database |
Rubu 项目
1 | codeql database create --language=ruby --source-root <folder-to-extract> <output-folder>/ruby-database |
编译型语言
编译型语言的数据库构建相对复杂,因为项目需要先进行编译,然后生成最终的项目,而不同的项目可以使用不同的构建工具进行管理,所以这一块比较复杂。
codeql-cli 提供了两种思路,一是自动识别进行数据库生成, 二是显式指定生成最终项目的命令,既项目构建的命令。
例如,自动构建 C++ / C 项目的数据库的命令如下:
1 | codeql database create --language=cpp <output-folder>/cpp-database |
而显式指定构建项目的命令来生成 C / C++项目的数据库的命令如下,多一个参数而已:
1 | codeql database create cpp-database --language=c-cpp --command=make |
显式指定构建命令生成 C## 项目数据库:
1 | codeql database create csharp-database --language=csharp --command='dotnet build /t:rebuild' |
显式 指定环境变量 / 指定构建脚本 生成 Go 项目数据库:
1 | CODEQL_EXTRACTOR_GO_BUILD_TRACING=on codeql database create go-database --language=go |
显示指定 maven 生成 Java 项目数据库:
1 | codeql database create java-database --language=java-kotlin --command='mvn clean install' |
显示指定 Ant 生成 Java 项目数据库:
1 | codeql database create java-database --language=java-kotlin --command='ant -f build.xml' |
执行查询
创建完数据库之后,在 vscode 的插件里按文件夹导入,即可创建 ql 脚本,执行查询操作。
查询结果
类似 sql 查询,通过 运行 ql 语句进行查询操作,同时返回一个结果集,包含符合 ql 语句要求的代码片段。
CodeQL 快速入门
首先是环境搭建,官方文档推荐使用 vscode extension,本质就是下面三步走:
- 下载 codeql-cli 和 packs 的捆绑包,并配置好环境变量
- vscode 安装 CodeQL 插件,并在 vscode extension settings 里配置好 codeql-cli 的路径
- 下载 vscode-codeql-starter workspace,双击
vscode-codeql-starter.code-workspace
打开 workspace
游戏例子
官方文档里,通过游戏例子帮助入门: https://codeql.github.com/docs/writing-codeql-queries/ql-tutorials/
例-01:find the thief
1 | // See https://codeql.github.com/docs/writing-codeql-queries/ql-tutorials/#ql-tutorials. |
例-02:Catch the fire starter
1 | import tutorial |
例-03:Crown the rightful heir
1 | import tutorial |
例-04:Cross the river,这个偏算法思想,不看。
实际例子
以 java-sec-code 项目为例,创建数据库命令的命令:
1 | codeql database create /Users/jasper/Documents/Security/tools/CodeQL/databases/java-sec-code-database --language=java --source-root=/Users/jasper/Documents/Security/java/java-sec-code --command="mvn clean package" |
点侧栏点CodeQL插件,选Java -> 导入上面创建的数据库 -> 运行example.ql,能正常运行输出结果说明环境正常。
再以 activemq 为例,注意 maven build 需要科学上网,源码是直接在 activmq GitHub clone 的。
1 | codeql database create .\codeql-databases\activemq --language=java-kotlin --source-root .\activemq-activemq-6.1.5\ --command='mvn clean install -Dmaven.test.skip=true' |
编写查询,查找 activemq 项目里所有调用了 .equals("")
的函数,并且调用 该 equals()
的对象的类型应为 String
注意:官方文档上 MethodAccess 已经弃用,MethodAccess 改名为 MehtodCall,MehtodCall.getMethod()获取到的是被调用的函数,即 callee
。
1 | import java |
再例如,创建一个 python 项目的 codeql-database 命令如下:
1 | codeql database create ./salt-codeql-database --language=python --source-root ./salt-master |
再写入如下 ql 语句,查找函数参数数量大于7的函数
1 | import python |
CodeQL 参考文档
- codeql for java:在 Java 项目中进行简单的 CodeQL 查询,常用的类都有一些例子,具备参考价值。
- QL language reference :QL 查询语言教程,列举了 Predicates、Types 等类的广义用法,比上面的更全面。
- standard librares for java :有关 codeql for java 的所有类和方法的文档,过于全面。
- CWE for Java : 漏洞扫描脚本,包括 JNDI、log4j等,可作为查询编写的参考,在
java-queries/securiy
目录下。