CodeQL 初探

简介

CodeQL 是 GitHub 开发的一种静态分析工具,广泛用于代码安全性和质量的检测。CodeQL 允许开发人员使用一种类似于 SQL 的查询语言来分析源代码,并查找潜在的漏洞或代码缺陷。它通过创建一个"代码数据库",使得用户可以查询程序中的各种数据流、控制流、API 调用等信息,从而发现安全漏洞、代码重复或不良编码实践。

CodeQL 支持多种编程语言,包括但不限于:C/C++、Java、JS、Python、Golang、Ruby、Rust、C#等。

环境搭建

下面我们搭建 CodeQL 所需要的环境。

CodeQL CLI

CodeQL CLI 是进行代码分析的核心工具,它允许您创建数据库、运行查询等操作

  • Linux
bash 复制代码
wget https://github.com/github/codeql-cli-binaries/releases/download/v2.20.7/codeql-linux64.zip

配置.bashrc文件,这里我是通过定义别名来使用的:

shell 复制代码
alias codeql=/tools/binary/codeql/codeql

VSCode插件

扩展插件搜索 codeql 插件,然后安装即可。

点击插件自动更新右边的齿轮按钮设置插件一些参数,Code QL>Cli:Execuble Path表示我们的 CodeQL CLI 路径,这里我们设置为我们的 codeql 目录下的 codeql 路径。

工作区

下载工作区

shell 复制代码
git clone --recursive https://github.com/github/vscode-codeql-starter

从文件打开工作区。

创建数据库

接下来我们需要为要审计的项目创建一个 CodeQL 数据库,以便进行查询。

假如我们要审计以下test.c文件:

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {

    char buffer[16];
    strcpy(buffer, input);  // 无边界检查
    printf("Copied: %s\n", buffer);

    return 0;
}

使用以下命令来创建:

shell 复制代码
codeql database create ./test-db --language=cpp --command="gcc test.c -o test"
  • codeql database create:创建数据库;
  • test-db:指定数据库创建成功后存放在test-db目录下;
  • language:指定语言,这里选择cpp即 C++;
  • command:编译指令,如果使用 make 编译那么就将 make 语句写在这里。

选择数据库

在 VSCode 中选择数据库。

之后我们就可以编写ql语句文件,然后运行在数据库中查询就可以了。而且我们不仅可以自己编译数据库,还可以使用别人编译好的数据库。

QL查询语句

CodeQL 所使用的查询语言是一种类 SQL 的语法。用于查找每种受支持语言最相关和最有趣的问题。您还可以编写自定义查询来查找与您自己的项目相关的问题。

重要的查询类型包括:

  • 警报查询:突出显示代码中特定位置的问题的查询。
  • 路径查询:描述代码中源和接收器之间的信息流的查询。

基本结构

q 复制代码
import <语言库>  // 如 java, cpp, python

from <变量声明>
where <条件表达式>
select <输出结果>
  • import - 导入库

codeql 为每种语言提供了大量库,包含类、谓词和辅助工具。

复制代码
import cpp

cpp 模块会自动导入所有核心 C/C++ 库,使你能访问整个抽象语法树(AST)、数据流、控制流等类和谓词。

  • from - 变量声明

用于声明要操作的元素(如函数、表达式、语句等)。

示例:

sql 复制代码
from Function f, Parameter p
  • where - 过滤条件

用于描述逻辑约束,筛选出满足条件的变量。

常见构造:逻辑运算(and, or, not),聚合与比较(=, !=, <, >=),调用谓词(isPublic(), hasName()),库提供的数据流、控制流谓词。

sql 复制代码
where f.getName() = "main"
  • select - 输出结果

定义最终展示的内容。

查询输出格式:

q 复制代码
select element,string

element 是由查询标识的代码元素,用于定义警报的显示位置;string 表示一条消息,其中还可以包含连接和占位符,说明生成警报的原因。

示例:

sql 复制代码
select c, "Found dangerous call here: " + c.getTarget().getName()

基础抽象类

类名 描述 子类示例
Element 所有 CodeQL 元素基类 ---
AstNode 抽象语法树节点 Stmt, Expr, Decl
Stmt 所有语句 IfStmt, SwitchStmt, ReturnStmt
Expr 所有表达式 CallExpr, BinaryExpr
Decl 所有声明 Function, VariableDecl
Type 所有类型 PrimitiveType, PointerType

声明类

  • 变量声明
CodeQL 类 示例
GlobalVariable int g;
NamespaceVariable namespace ns { int x; }
MemberVariable class C{int x;};

示例:查找所有类型为std::string的类成员变量。

sql 复制代码
from MemberVariable v
where v.getType().getName() = "string"
select v
  • 函数声明
CodeQL 类 示例
Function void foo()
VirtualFunction virtual void f()
FormattingFunction printf()
Parameter void foo(int param)

查找静态函数:

sql 复制代码
from Function f
where f.isStatic()
select f, "static function"

查找从未调用的函数:

sql 复制代码
from Function f
where not exists(FunctionCall fc | fc.getTarget() = f)
select f, "unused function"
  • 模板与类
CodeQL 类 示例
ClassDecl class C {...}
StructDecl struct S{...}
ClassTemplateInstantiation vector<int>
TemplateParameter typename T
Constructor ClassName()
Destructor ~ClassName()
TemplateDecl template<typename T>
TemplateInstantiation vector<int>
TemplateParameter typename T

查找所有vector<int>实例化点:

sql 复制代码
from ClassTemplateInstantiation c
where c.getTemplate().getName() = "vector"
select c

语句类

  • 控制流语句
CodeQL 类 示例
IfStmt if(x)
IfElseStmt if(x) else y
SwitchStmt switch(x)
WhileStmt while (x)
DoStmt do {...} while(x)
ForStmt for(int i=0;i<n;i++)
RangeBasedForStmt for(auto& x : v)

查找空if语句:

sql 复制代码
from IfStmt ifs, BlockStmt blk
where ifs.getThen() = blk and blk.getNumStmt() = 0 and not ifs.hasElse()
select ifs, "redundant if"
  • 跳转语句
CodeQL 类 示例
BreakStmt break;
ContinueStmt continue;
ReturnStmt return x;
GotoStmt goto label;
  • 复合语句
CodeQL 类 示例
CompoundStmt { ... }
BlockStmt 一组语句

表达式类

  • 运算符
CodeQL 类 示例
BinaryExpr a + b
UnaryExpr !x
AssignExpr a = b
CallExpr foo()
MemberAccess obj.a
ArrayAccess arr[i]

查找调用sprintf的位置且 format 字符串不是字面量(格式化字符串漏洞):

sql 复制代码
from FunctionCall fc
where fc.getTarget().getName() = "sprintf"
  and not fc.getArgument(1) instanceof StringLiteral
select fc, "sprintf with non-literal format string"
  • 字面量
示例
IntegerLiteral 42
StringLiteral "abc"
FloatingLiteral 3.14

查找右边为 0 的赋值:

sql 复制代码
from AssignExpr e
where e.getRValue().getValue().toInt() = 0
select e
  • 特殊表达式
示例
NewExpr new int[x]
DeleteExpr delete p
LambdaExpr [&](int x){...}

其它元素

  • 类型类
CodeQL 类 示例
PrimitiveType int
PointerType int*
ReferenceType int&
ArrayType int[10]
ClassType std::string
  • 预处理器类
CodeQL 类 示例
Macro #define X 1
MacroInvocation X
IncludeDirective #include <stdio.h>

自动化分析

使用 CodeQL 官方的 C/C++ 安全查询包分析目标数据库。

shell 复制代码
codeql database analyze test-db codeql/cpp-queries --format=sarifv2.1.0 --output=result.sarif

在 VSCode 中安装 SARIF Viewer 插件分析 result.sarif 文件。

Reference

CodeQL 入门和基本使用
适用于 C 和 C++ 的 CodeQL 库 --- CodeQL

[原创\]CodeQL入门 - U-Boot Challenge-二进制漏洞-看雪论坛-安全社区\|非营利性质技术交流社区](https://bbs.kanxue.com/thread-277560.htm#msg_header_h1_3)

相关推荐
Fullde福德负载箱厂家3 小时前
负载箱的隐性成本与全周期经济性:用户应知的持有成本与价值管理
大数据·安全·制造
Bruce_Liuxiaowei4 小时前
CVE-2026-31431 (Copy Fail) 漏洞复现与验证记录
linux·安全·漏洞复现·cve-2026-31431
alxraves4 小时前
基于YY 9706.106-2021标准可用性测试概述
安全·健康医疗·制造·可用性测试
北京盟通科技官方账号5 小时前
工业安全:FSoE (Fail Safe over EtherCAT) 常见技术问题解析
安全·具身智能·ethercat·人形机器人·工业安全·fsoe·ecmaster
kobesdu5 小时前
AGV安全防护全解析:安全产品分类与简介
人工智能·安全·移动机器人
KKKlucifer5 小时前
纵深防御视角下安全运维服务体系构建思路
运维·网络·安全
星幻元宇VR5 小时前
VR观景台推动安全科普走向沉浸体验
科技·学习·安全·vr·虚拟现实
菩提小狗5 小时前
每日安全情报报告 · 2026-04-30
网络安全·漏洞·cve·安全情报·每日安全
志栋智能6 小时前
超自动化安全:数字时代的网络免疫系统
网络·安全·自动化