名称: codeql 描述: 运行CodeQL静态分析以进行安全漏洞检测、污点跟踪和数据流分析。在需要分析代码、创建CodeQL数据库、编写自定义QL查询、执行安全审计或设置CodeQL在CI/CD管道中使用。 允许的工具:
- Bash
- Read
- Glob
- Grep
CodeQL静态分析
何时使用CodeQL
理想场景:
- 能够访问源代码并具有构建能力(对于编译语言)
- 开源项目或GitHub高级安全许可证
- 需要跨过程数据流和污点跟踪
- 查找需要AST/CFG分析的复杂漏洞
- 综合分析时间不关键的安全审计
考虑使用Semgrep的情况:
- 编译语言没有构建能力
- 许可证限制
- 需要快速、轻量级的模式匹配
- 简单的单文件分析足够
为什么跨过程分析重要
简单的grep/模式工具一次只能看到一个函数。真正的漏洞通常跨越多个函数:
HTTP处理程序 → 输入解析器 → 业务逻辑 → 数据库查询
↓ ↓ ↓ ↓
源点 转换 传递 汇点 (SQL)
CodeQL跟踪所有这些步骤的数据流。处理程序中的污染输入可以通过5+个函数调用追踪到它到达危险汇点的地方。
基于模式的工具会错过这个,因为它们无法连接文件A中的request.param到文件B中的db.execute(query)。
何时不使用
不要将此技能用于:
- 无法构建的项目(CodeQL要求编译语言成功编译)
- 快速模式搜索(使用Semgrep或grep以提高速度)
- 非安全的代码质量检查(使用linters代替)
- 没有源代码访问权限的项目
环境检查
# 检查CodeQL是否安装
command -v codeql >/dev/null 2>&1 && echo "CodeQL: 已安装" || echo "CodeQL: 未安装(运行下面的安装步骤)"
安装
CodeQL CLI
# macOS/Linux (Homebrew)
brew install --cask codeql
# 更新
brew upgrade codeql
手动: 从https://github.com/github/codeql-action/releases下载捆绑包
Trail of Bits查询(可选)
安装公共ToB安全查询以增加覆盖范围:
# 下载ToB查询包
codeql pack download trailofbits/cpp-queries trailofbits/go-queries
# 验证安装
codeql resolve qlpacks | grep trailofbits
核心工作流
1. 创建数据库
codeql database create codeql.db --language=<LANG> [--command='<BUILD>'] --source-root=.
| 语言 | --language= |
是否需要构建 |
|---|---|---|
| Python | python |
否 |
| JavaScript/TypeScript | javascript |
否 |
| Go | go |
否 |
| Ruby | ruby |
否 |
| Rust | rust |
是 (--command='cargo build') |
| Java/Kotlin | java |
是 (--command='./gradlew build') |
| C/C++ | cpp |
是 (--command='make -j8') |
| C# | csharp |
是 (--command='dotnet build') |
| Swift | swift |
是 (仅限macOS) |
2. 运行分析
# 列出可用查询包
codeql resolve qlpacks
运行安全查询:
# SARIF输出(推荐)
codeql database analyze codeql.db \
--format=sarif-latest \
--output=results.sarif \
-- codeql/python-queries:codeql-suites/python-security-extended.qls
# CSV输出
codeql database analyze codeql.db \
--format=csv \
--output=results.csv \
-- codeql/javascript-queries
使用Trail of Bits查询(如果已安装):
codeql database analyze codeql.db \
--format=sarif-latest \
--output=results.sarif \
-- trailofbits/go-queries
编写自定义查询
查询结构
CodeQL使用类似SQL的语法: from Type x where P(x) select f(x)
基本模板
/**
* @name 查找SQL注入漏洞
* @description 识别来自用户输入的潜在SQL注入
* @kind path-problem
* @problem.severity error
* @security-severity 9.0
* @precision high
* @id py/sql-injection
* @tags security
* external/cwe/cwe-089
*/
import python
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
module SqlInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
// 定义污染源(用户输入)
exists(source)
}
predicate isSink(DataFlow::Node sink) {
// 定义危险汇点(SQL执行)
exists(sink)
}
}
module SqlInjectionFlow = TaintTracking::Global<SqlInjectionConfig>;
from SqlInjectionFlow::PathNode source, SqlInjectionFlow::PathNode sink
where SqlInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "SQL注入来自 $@.", source.getNode(), "用户输入"
查询元数据
| 字段 | 描述 | 值 |
|---|---|---|
@kind |
查询类型 | problem, path-problem |
@problem.severity |
问题严重性 | error, warning, recommendation |
@security-severity |
CVSS分数 | 0.0 - 10.0 |
@precision |
置信度 | very-high, high, medium, low |
关键语言特性
// 谓词
predicate isUserInput(DataFlow::Node node) {
exists(Call c | c.getFunc().(Attribute).getName() = "get" and node.asExpr() = c)
}
// 传递闭包: + (一个或多个), * (零个或多个)
node.getASuccessor+()
// 量化
exists(Variable v | v.getName() = "password")
forall(Call c | c.getTarget().hasName("dangerous") | hasCheck(c))
创建查询包
codeql pack init myorg/security-queries
结构:
myorg-security-queries/
├── qlpack.yml
├── src/
│ └── SqlInjection.ql
└── test/
└── SqlInjectionTest.expected
qlpack.yml:
name: myorg/security-queries
version: 1.0.0
dependencies:
codeql/python-all: "*"
CI/CD集成(GitHub Actions)
name: CodeQL分析
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: '0 0 * * 1' # 每周
jobs:
analyze:
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
matrix:
language: ['python', 'javascript']
steps:
- uses: actions/checkout@v4
- name: 初始化CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
queries: security-extended,security-and-quality
# 添加自定义查询/包:
# queries: security-extended,./codeql/custom-queries
# packs: trailofbits/python-queries
- uses: github/codeql-action/autobuild@v3
- uses: github/codeql-action/analyze@v3
with:
category: "/language:${{ matrix.language }}"
测试查询
codeql test run test/
测试文件格式:
def vulnerable():
user_input = request.args.get("q") # 源点
cursor.execute("SELECT * FROM users WHERE id = " + user_input) # 警报: sql-injection
def safe():
user_input = request.args.get("q")
cursor.execute("SELECT * FROM users WHERE id = ?", (user_input,)) # 安全
故障排除
| 问题 | 解决方案 |
|---|---|
| 数据库创建失败 | 清理构建环境,验证构建命令独立运行 |
| 分析缓慢 | 使用--threads,缩小查询范围,检查查询复杂度 |
| 缺少结果 | 检查文件排除,验证源文件已解析 |
| 内存不足 | 设置CODEQL_RAM=48000环境变量(48GB) |
| CMake源路径问题 | 调整--source-root指向实际源位置 |
拒绝的理由
| 捷径 | 为什么错误 |
|---|---|
| “没有发现意味着代码安全” | CodeQL只查找它有查询的模式;新颖漏洞不会被检测到 |
| “此代码路径看起来安全” | 复杂数据流可能隐藏跨5+函数调用的漏洞;追踪完整路径 |
| “小更改,低风险” | 小更改可能引入关键错误;每次更改运行完整分析 |
| “测试通过所以安全” | 测试证明行为,而非漏洞缺失;它们测试预期路径,而非攻击者路径 |
| “查询未标记它” | 默认查询套件不覆盖所有内容;检查是否需要自定义查询 |
资源
- 文档: https://codeql.github.com/docs/
- 查询帮助: https://codeql.github.com/codeql-query-help/
- 安全实验室: https://securitylab.github.com/
- Trail of Bits查询: https://github.com/trailofbits/codeql-queries
- VSCode扩展: “CodeQL” 用于查询开发