CodeQL 学习笔记【10】调试 CodeQL

使用 CodeQL 进行查询的时候,可能会出现一些意外情况,导致我们查不到自己想要的结果。如果是其他语言,我们可以尝试断点调试、gdb 调试、print 调试等等方法。但是 CodeQL 不一样,它不是一种常规的编程语言,它没法使用常见的那些方法。不过 CodeQL 还是有办法进行调试的。

那就是查看抽象语法树、偏路径图等方法。

但是我们平时写查询的时候进行简单的调试肯定不需要这么复杂的方法。平时我们可以将一个复杂的查询,慢慢简化,简化为一个单独的查询,然后慢慢的去增加子语句,直到发现问题的所在。

或者在一个 predicate 谓词名称上右键,然后选择快速评估。我这里差不多就相当于执行 select inSink

然后你就可以先简单判断是不是谓词写错了?

抽象语法树(AST)

如果说简单测试后发现 sink 和 source 都没有问题,都能正确找到我们想要找的代码,但是整体结果还是查不出来漏洞传播路径。那么问题可能就出现在了 source 到 sink 的流程追踪了。

这个时候就需要 AST 抽象语法树来帮忙了。 我这里还是拿以前写的测试代码来举个例子了。

js 复制代码
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking

module MyFlowConfiguration implements DataFlow::ConfigSig {
  predicate isSource(DataFlow::Node source) {
    source instanceof RemoteFlowSource
  }

  predicate isSink(DataFlow::Node sink) {
    exists(Call call |
      sink.asExpr() = call.getArgument(0) and
      call.getCallee().(Constructor).getDeclaringType().hasQualifiedName("java.net", "URL")
    )
  }
}

module MyFlow = TaintTracking::Global<MyFlowConfiguration>;

from MyFlow::PathNode source, MyFlow::PathNode sink
where MyFlow::flowPath(source, sink)
select source,source.getLocation()

我在刚才在 isSink() 上执行了快速评估,发现 isSink() 确实找到我想要的代码,然后就可以在 java 代码那里鼠标右键选择 CodeQL: View AST

然后就可以在 CodeQL 插件这里看到抽象语法树了。 当你有了抽象语法树,当你鼠标点击一个节点的时候,就会显示一段代码在 CodeQL 中是什么类型。

比如我上面这张图片中高亮的部分的代码 :InputStream in = new URL(url).openStream() 在 CodeQL 中的类型就是 LocalVariableDectStmt

new URL(url).openStream() 就是一个 MethodCall

这样我们就可以很细化的去找我们要找的东西,可以排除一些误报等等之类的。

当然除了查看 AST 还有 getAQlClass() 谓词可以获取一段代码的类型,比如:

js 复制代码
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking

module MyFlowConfiguration implements DataFlow::ConfigSig {
  predicate isSource(DataFlow::Node source) {
    source instanceof RemoteFlowSource
  }

  predicate isSink(DataFlow::Node sink) {
    exists(Call call |
      sink.asExpr() = call.getArgument(0) and
      call.getCallee().(Constructor).getDeclaringType().hasQualifiedName("java.net", "URL")
    )
  }
}

module MyFlow = TaintTracking::Global<MyFlowConfiguration>;

from MyFlow::PathNode source, MyFlow::PathNode sink
where MyFlow::flowPath(source, sink)
select source,source.getAQlClass()

查询的结果就是 PathNode,当然,我这个例子比较傻,毕竟本来 source 定义的时候就是定义的 PathNode ,但你明白意思就行。

部分路径图

还有部分路径图也可以帮助你查看 source 到 sink 的流程从那里断开了,导致查询不到结果。但是用这个东西的时候要特别注意,因为它会将所有 source 到所有 sink 的流向图都展示出来,如果 source 和 sink 都特别多,那么估计电脑会卡死的。

所以我这里演示的时候限制一下代码的文件。

部分路径图有两种形式,一种是正向部分路径图 FlowExplorationFwd (追踪某一个 source 到任意 sink 的路径) ,一种是逆向部分路径图 FlowExplorationRev (追踪一个 sink 到任意 source 的路径).

js 复制代码
/**
 * @name test for partial path graph
 * @description This query tracks data flow from SSRFTask2 source to any sink.
 * @kind path-problem
 * @problem.severity warning
 * @id 5/3
 */

import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking

module MyFlowConfiguration implements DataFlow::ConfigSig {
  predicate isSource(DataFlow::Node source) {
    source instanceof RemoteFlowSource and source.getLocation().getFile().getBaseName() = "SSRFTask2.java"
  }

  predicate isSink(DataFlow::Node sink) {
    exists(Call call |
      sink.asExpr() = call.getArgument(0) and
      call.getCallee().(Constructor).getDeclaringType().hasQualifiedName("java.net", "URL")
    )
  }
}

module MyFlow = TaintTracking::Global<MyFlowConfiguration>;
int explorationLimit() { result = 10 }
module PartialFlow = MyFlow::FlowExplorationFwd<explorationLimit/0>;
import PartialFlow::PartialPathGraph

from PartialFlow::PartialPathNode source, PartialFlow::PartialPathNode sink
where PartialFlow::partialFlow(source, sink, _)
select sink.getNode(), source, sink, "Partial Graph $@.", source.getNode(), "user-provided value."

我这里查到了 5 条路径,哪些 3 步、2 步就结束的路径应该是指向其他 sink 的,但是中途就断了。希望 CodeQL 早日出图形化的展示图吧......

相关推荐
三秋树2 小时前
CodeQL 学习笔记【9】扩展用法: 使用 CodeQL 扫描代码库
安全
三秋树2 小时前
Fastjson RCE 复现 【01】1.2.24 版本利用及原理分析
安全·黑客·测试
烛衔溟2 小时前
TypeScript 特殊类型与空值安全
安全·typescript·前端开发·空值处理
EasyDSS3 小时前
企业级私有化部署视频直播点播平台EasyDSS如何构建企业远程会议安全防线
安全·音视频
dgw26486338093 小时前
深信服数据传输安全-NPN-(1)
安全
2401_832298103 小时前
OpenClaw 3.28 终章:从 “激进重构” 到 “稳健治理”,AI 智能体安全与体验的平衡之道
人工智能·安全·重构
EasyGBS3 小时前
国标GB28181视频分析平台EasyGBS视频质量诊断助力能源矿山行业实现安全高效管控体系
安全·音视频·能源
她说..3 小时前
Spring单例Bean线程安全问题 深度解析
java·后端·安全·spring·springboot
桌面运维家4 小时前
Windows防火墙高级配置:网络安全深度优化
windows·安全·web安全