1. 概述
CodeQL是GitHub 开发的一种强大的静态应用程序安全测试 (SAST) 引擎和代码分析平台。它允许开发者和安全研究人员像查询数据库一样去“查询”代码,从而自动化地发现潜在的安全漏洞和编码错误。
CodeQL最大的核心创新在于“将代码视为数据”:CodeQL 会先将目标源码编译、解析并转化成一个结构化的关系数据库(CodeQL Database),然后安全研究员可以使用一种声明式的、类似于 SQL 的面向对象查询语言(QL),像查询数据库一样去检索代码中的安全漏洞。
2. CodeQL核心原理
CodeQL 的完整挖掘流程分为三个步骤:
[ 目标源码 ] ──(通过 codeql database create 编译)──> [ CodeQL 数据库 ] ──(运行 QL 查询规则)──> [ 发现 0day 漏洞 / 污点链路 ]
- 提取与建库(Extracting): CodeQL 监控目标源码的编译过程(对于编译型语言如 C/C++, Java, Go)或直接解析语法(对于解释型语言如 Python, JavaScript)。它把抽象语法树(AST)、控制流图(CFG)以及数据流信息全部提取出来,打包成一个闭源的 .db 数据库文件,;
- 使用 QL 查询语言: 通过专用的声明式面向对象查询语言(<0.6.4>QL,Query Language)编写规则,编写 .ql 脚本在代码数据库上运行,精准匹配特定的代码模式、数据流(污点分析)或逻辑缺陷,调用 CodeQL 内置的语义库进行深度分析;
- 漏洞输出(Results): 结果不仅是一个“漏洞点”,通常是一条完整的动态代码执行路径;安全人员可以利用已知漏洞编写 CodeQL 查询,在整个代码库中自动搜索类似的未知变种漏洞;
CodeQL支持的编程语言包括C/C++、C#、Go、Java/Kotlin、JavaScript/TypeScript、Python、Ruby、Rust、Swift 以及 GitHub Actions 流程,暂不支持PHP、Scala 等未列出语言。
3. CodeQL CLI下载与安装
CodeQL是开源免费的,可以直接下载CodeQL CLI(命令行界面)和相关的QL规则库,而且还能支持VS Code插件等集成工具。
目前来说,搭建 CodeQL 漏洞挖掘环境,最标准且最高效的配置是 CodeQL CLI(命令行工具) + VS Code 插件 + 官方 QL 规则库。
以下是完整的保姆级安装与配置流程:
3.1 下载并安装 CodeQL CLI (核心引擎)
CodeQL CLI 是负责解析代码、创建数据库和执行查询的命令行工具:
- 1. 下载CLI压缩包:访问 GitHub CodeQL CLI Release,根据你的操作系统(Windows 对应 codeql-win64.zip,Mac 对应 codeql-osx64.zip,Linux 对应 codeql-linux64.zip)下载最新版;
- 2. 解压文件:在本地找一个没有中文和空格的路径(例如 Windows 下的 D:\Security\codeql 或 Mac 下的 /Users/username/codeql),将压缩包解压至该目录下;
- 3. 配置环境变量:将解压出来的 codeql 可执行文件所在目录(包含 codeql.exe 或 codeql 的文件夹)添加到系统的 PATH 环境变量中;
- 4. 验证安装:打开终端或 PowerShell,输入以下命令,若显示版本号则安装成功:
codeql --version

3.2 下载 GitHub 官方 QL 规则库 (核心资源)
CodeQL 本身只是个引擎,想要进行漏洞扫描,必须下载官方维护的各语言漏洞查询规则库:

3.3 配置 VS Code 图形化开发环境 (IDE)
编写 QL 脚本和可视化查看漏洞污点链路,需要依靠 VS Code:
- 1. 安装 VS Code: 若未安装,请前往官网下载;
- 2. 安装 CodeQL 官方插件:在 VS Code 左侧扩展市场(Extensions)搜索
CodeQL(由 GitHub 官方发布),点击安装; - 3. 配置插件路径:安装完成后,进入 VS Code 设置(Ctrl + ,),搜索 codeql.cli.executablePath,将其设置为第一步中 codeql 可执行文件的绝对路径(例如:D:\ProgramSoftware\codeql\codeql.exe);


3.4 实战验证(创建数据库与运行查询)
为了确保环境彻底配置成功,我们可以用一个简单的开源项目(以 WebGoat 为例)进行联调测试。
3.4.1 下载WebGoat
WebGoat 是一款故意设计得不安全的应用程序,由java语言开发,且需要提前安装maven,下载地址:https://github.com/WebGoat/WebGoat
3.4.2 创建 CodeQL 数据库
在WebGoat根目录下面执行如下命令,会自动编译并且为该项目创建一个名为webgoat-qldb的QL数据库:
codeql database create webgoat-qldb --language=java
找到你本地的一个源码项目,打开终端,执行建库命令,通用型的命令如下:
# 通用解释型语言(如 Python, JavaScript)
codeql database create my-target-db --language=python --source-root=/path/to/source
# 编译型语言(如 Java, C/C++)需要确保本地有编译环境,CodeQL 会在建库时自动编译
codeql database create my-target-db --language=java --source-root=/path/to/source
命令执行完毕后,本地会生成一个名为 my-target-db 的文件夹,这就是你的代码数据库。
创建完该项目的数据库后,该项目的源码文件在后面几乎就用不到了(除非像更新QL数据库这种需求),CodeQL查询时主要使用的便是该项目的数据库文件。
3.4.3 创建QL包
新建一个文件夹,存放后续编写的CodeQL脚本,也就是QL Pack。接着在文件夹中创建1个QL Pack的配置文件,名称固定为qlpack.yml,再创建一个.ql后缀的文件,名称随意。在VSCode中打开这个文件夹。
3.4.4 编写QL包的配置文件
将以下代码写入到配置文件中:
name: example-query //表示QL包名为example-query,必选,如果你在VSCode中同时打开多个QL包时,要保证这个name的值唯一不重复
version: 0.0.0 //表示QL包的版本号,必选
libraryPathDependencies: codeql-java //表示QL包的依赖,必选,codeql-java表示需要Java语言的QL标准库依赖
3.4.5 VSCode工作区增加CodeQL标准库
为了让CodeQL解释器能够访问标准库,我们需要将标准库所在文件夹也加入到加入工作区中。
VSCode – 文件 – 将文件夹加入工作区 – 选择在【环境准备 – CodeQL标准库】章节中存放CodeQL标准库的文件夹
3.4.6 VSCode添加CodeQL数据库
在VSCode的CodeQL插件中添加之前用CodeQL创建的WebGoat的数据库
3.4.7 编写查询
在webgoat-queyr.ql文件中编写如下代码,用来查找WebGoat项目中所有声明的方法:
import java
from Method m
select m
然后右键点击CodeQL: Run Query来执行本次查询,执行完成后在右边可以看到多出一列用来显示查询结果。点击结果里面的任意条目,可以跳到对应的文件中。
当然,codeql也有自带的规则,将数据库导入 VS Code:
- 在 VS Code 左侧工具栏找到 CodeQL 图标(一个类似 Q 字母的盾牌图标);
- 在 DATABASES 面板中,点击 From a folder;
- 选择刚刚创建的 webgoat-qldb 文件夹。成功导入后,该数据库前会出现一个绿色的对勾;

直接选择规则运行查询:
- 在 VS Code 的
codeql-repo目录中,导航到java/ql/src/Security/目录; - 随便打开一个自带的
.ql规则文件(例如CWE-022路径遍历相关的规则); - 在代码编辑器中单击右键,选择
CodeQL: Run Query on Selected Database; - 此时 VS Code 右侧会弹出
CodeQL Query Results面板。如果代码中有漏洞,点击结果即可直接在左侧代码中看到高亮的漏洞触发路径;


4. CodeQL使用方式
在 0day 漏洞挖掘实战中,熟练使用 CodeQL 主要围绕两个核心场景:基础的命令行批量扫描(使用 CLI) 以及 深度的自定义规则开发(在 VS Code 中进行污点分析)。
4.1 核心命令速查表(CLI 视角)
日常扫描和自动化流水线中,最常使用的四个核心命令:
- 创建数据库:
codeql database create <db_name> --language=<lang>; - 运行单个查询:
codeql query run <query_file> --database=<db_path>; - 批量运行规则包:
codeql database analyze <db_path> <pack_or_dir> --format=sarif-latest --output=result.sarif; - 更新规则依赖:
codeql pack install;
4.2 场景一:使用官方规则库进行快速漏洞筛查(黑盒/白盒初筛)
如果你拿到了一个开源项目或审计目标的源码,想先用 GitHub 专家写好的成百上千条规则过一遍,流程如下:
4.2.1 为目标生成 CodeQL 数据库:
进入目标源码根目录,执行建库命令(以 Java 为例):
codeql database create target-java-db --language=java --command="mvn clean install -DskipTests"
4.2.2 批量运行官方安全规则包(Suite):
使用 database analyze 命令,直接调用官方预设的安全查询包进行全方位体检:
codeql database analyze target-java-db \
codeql/java-queries:codeql/java-security-and-quality.qls \
--format=csv --output=scan_results.csv
执行后,你可以在生成的 scan_results.csv 中直接看到该项目是否存在已知的反序列化、SQL 注入、XSS 等安全隐患。
4.3 在 VS Code 中编写自定义规则挖掘 0day(高级进阶)
商业或通用的规则往往只能扫出“标准”漏洞。面对魔改的框架或自研组件,0day 挖洞的精髓在于编写自定义的污点追踪(TaintTracking)脚本,在 VS Code 中运行自定义 QL:
第一步:启动 VS Code: 打开之前克隆的官方规则库(如 codeql-repo)或一个全新的独立工作区;
第二步:导入数据库: 在 VS Code 的 CodeQL 插件面板中,点击 From a local folder,选择你在上一步创建的 target-java-db 文件夹;
第三步:编写查询规则:在工作区新建一个名为 find_my_0day.ql 的文件。假设目标的私有组件中有一个名为 executePayload(String cmd) 的未公开危险函数,你想排查有没有外部输入能流向它:
/**
* @name 寻找私有组件命令执行0day
* @kind path-problem
* @id custom/java/private-cmd-injection
*/
import java
import semmle.code.java.dataflow.TaintTracking
import DataFlow::PathGraph
// 继承并配置污点追踪
config class MyPrivate0dayConfig extends TaintTracking::Configuration {
MyPrivate0dayConfig() { this = "MyPrivate0dayConfig" }
// 1. 定义污染源:这里我们偷懒,让所有来自 Servlet 的参数都作为 Source
override predicate isSource(DataFlow::Node source) {
exists(MethodAccess ma |
ma.getMethod().getName() = "getParameter" and
source.asExpr() = ma
)
}
// 2. 定义漏洞陷阱:目标的私有危险函数 executePayload
override predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma |
ma.getMethod().getName() = "executePayload" and
sink.asExpr() = ma.getArgument(0)
)
}
}
// 3. 关联路径图并输出
from MyPrivate0dayConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "警告:发现一条完整的外部输入流向私有危险函数的通路!"
第四步:一键执行: 在编辑器内对该代码点击右键,选择 CodeQL: Run Query on Selected Database;
第五步:看图挖洞: VS Code 右侧会立即弹出 CodeQL Query Results 面板。如果是 path-problem 类型(路径问题),点击结果后,左侧代码会自动亮起一条带有剪头的动态传递链(数据流向动画),顺着箭头就能直接定位 0day 的触发链路;
5. 实战:一个简化的 CodeQL 查询示例
以下是一个寻找 Java 命令注入漏洞(Runtime.exec 污点分析) 的标准 QL 脚本结构:
/**
* @name Find Java Command Injection
* @kind path-problem
* @id java/example/command-injection
*/
import java
import semmle.code.java.dataflow.TaintTracking
import DataFlow::PathGraph
// 1. 定义污点分析配置
config class CmdInjectionConfig extends TaintTracking::Configuration {
CmdInjectionConfig() { this = "CmdInjectionConfig" }
// 2. 定义 Source:任何获取远程 HTTP 请求参数的方法
override predicate isSource(DataFlow::Node source) {
exists(MethodAccess ma |
ma.getMethod().getName() = "getParameter" and
source.asExpr() = ma
)
}
// 3. 定义 Sink:Runtime.exec() 的第一个参数
override predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma |
ma.getMethod().getDeclaringType().hasQualifiedName("java.lang", "Runtime") and
ma.getMethod().getName() = "exec" and
sink.asExpr() = ma.getArgument(0)
)
}
}
// 4. 执行查询并输出整条漏洞链路
from CmdInjectionConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "发现0day:用户可控参数流向了命令执行函数!"
1. 一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。