codeql 初使用及规则分析 -
字数 1893 2025-08-10 20:57:54
CodeQL 使用指南及规则深度解析
一、CodeQL 简介
CodeQL 是 GitHub 开发的语义代码分析引擎,用于自动化安全漏洞检测。它通过将代码转换为可查询的数据库,使用类似 SQL 的查询语言来发现代码中的安全漏洞。
二、CodeQL 基础使用
1. 安装与配置
- CodeQL CLI 下载地址: https://github.com/github/codeql-cli-binaries/releases
- CodeQL 规则库地址: https://github.com/github/codeql
2. 创建数据库
对于 Java 项目:
codeql database create DB_DIR --language=java --command='mvn clean install'
3. 分析数据库并导出结果
两种常用输出格式:
- SARIF 格式(详细结果):
codeql database analyze DB_DIR --format=sarifv2.1.0 --output=/tmp/result.json codeql-main/java/ql/src/codeql-suites/java-code-scanning.qls
- CSV 格式(简化结果):
codeql database analyze DB_DIR --format=csv --output=/tmp/result.csv codeql-main/java/ql/src/codeql-suites/java-code-scanning.qls
4. 使用注意事项
-
过滤警告报告:
修改codeql-main/misc/suite-helpers/code-scanning-selectors.yml文件,注释掉problem.severity下的warning部分。 -
启用实验性规则:
- 实验性规则位于
codeql-main/java/ql/src/experimental目录 - 如 MyBatis SQL 注入规则:
codeql-main/java/ql/src/experimental/Security/CWE/CWE-089/MyBatisMapperXmlSqlInjection.ql - 修改
code-scanning-selectors.yml,注释掉exclude - query path下的/^experimental\/.*/
- 实验性规则位于
三、CodeQL 规则深度解析
1. 不安全反序列化规则 (java/unsafe-deserialization)
检测原理
- 主要检测 FastJson、XStream、Yaml 等不安全反序列化
- 核心检测方法:
unsafeDeserialization(MethodAccess ma, Expr sink)
FastJson 检测逻辑
ma.getMethod() instanceof FastJsonParseMethod
and not fastJsonLooksSafe()
and sink = ma.getArgument(0)
FastJson 安全模式检测
exists(FastJsonSetSafeMode setsafe | not setsafe.getMode() = false)
仅检测是否设置了 safeMode,无法检测 FastJson 版本。
改进建议
可结合 IAST 进行更精确检测,参考洞态实现:
https://github.com/HXSecurity/DongTai-agent-java
2. 路径注入规则 (java/path-injection)
规则组成
- Source: 远程用户输入 (
RemoteFlowSource) - Sink: 文件操作相关方法调用或实例创建
- Sanitizer: 净化规则
- AdditionalTaintStep: 额外污点传播步骤
Sink 定义
位于 PathCreation.qll,包含各种文件操作方法:
sink.asExpr() = any(PathCreation p).getAnInput()
or sinkNode(sink, "create-file")
污点传播 (AdditionalTaintStep)
建立 java.net.URI 参数 path 到构造函数调用的传播:
override predicate isAdditionalTaintStep(DataFlow::Node n1, DataFlow::Node n2) {
any(TaintedPathAdditionalTaintStep s).step(n1, n2)
}
净化规则 (Sanitizer)
主要净化类型:
- 基本类型/包装类型/数字类型
- 路径相关净化器 (
PathInjectionSanitizer)
PathInjectionSanitizer 子类
- ExactPathMatchSanitizer: 精确路径匹配检查
- AllowedPrefixSanitizer: 允许的前缀检查
- DotDotCheckSanitizer: 路径穿越检查
- BlockListSanitizer: 黑名单检查
ExactPathMatchSanitizer 实现
private class ExactPathMatchSanitizer extends PathInjectionSanitizer {
ExactPathMatchSanitizer() {
this = DataFlow::BarrierGuard<exactPathMatchGuard/3>::getABarrierNode()
or this = ValidationMethod<exactPathMatchGuard/3>::getAValidatedNode()
}
}
exactPathMatchGuard 定义
检测路径相关类型的精确比较:
private predicate exactPathMatchGuard(Guard g, Expr e, boolean branch) {
exists(MethodAccess ma, RefType t |
t instanceof TypeString or t instanceof TypeUri or t instanceof TypePath
or t instanceof TypeFile or t.hasQualifiedName("android.net", "Uri")
or t instanceof StringsKt or t instanceof FilesKt |
e = getVisualQualifier(ma).getUnderlyingExpr()
and ma.getMethod().getDeclaringType() = t
and ma = g
and getSourceMethod(ma.getMethod()).hasName(["equals", "equalsIgnoreCase"])
and branch = true
)
}
ValidationMethod 实现
private module ValidationMethod<DataFlow::guardChecksSig/3 validationGuard> {
DataFlow::Node getAValidatedNode() {
exists(MethodAccess ma, int pos, RValue rv |
validationMethod(ma.getMethod(), pos)
and ma.getArgument(pos) = rv
and adjacentUseUseSameVar(rv, result.asExpr())
and ma.getBasicBlock().bbDominates(result.asExpr().getBasicBlock())
)
}
}
自定义净化规则示例
// 经过 FilenameUtils.getExtension 方法处理的路径认为安全
private class ExtractExtensionSanitizer extends PathInjectionSanitizer {
ExtractExtensionSanitizer() {
this.asExpr().(MethodAccess).getMethod().getName() = "getExtension"
and this.asExpr().(MethodAccess).getMethod()
.getDeclaringType().hasQualifiedName("org.apache.commons.io","FilenameUtils")
}
}
四、高级技巧与最佳实践
- 规则调试: 使用
--ram=8000参数增加内存分配 - 性能优化: 针对大型项目,可以分模块创建数据库
- 自定义规则: 继承现有规则类实现特定检测逻辑
- 结果验证: 结合动态测试验证静态分析结果
五、推荐阅读
六、总结
CodeQL 是一个强大的静态分析工具,通过深入理解其规则实现原理,可以:
- 更准确地识别漏洞
- 减少误报
- 针对特定项目定制检测规则
- 提高自动化安全检测效率
掌握 CodeQL 需要对其查询语言、Java 代码分析模型以及安全漏洞模式有深入理解,建议从实际项目入手,逐步深入。