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 早日出图形化的展示图吧......

相关推荐
上海控安28 分钟前
实时系统保障关键技术-最坏情况执行时间(WCET)分析
测试工具·安全
网安蟹佬霸44 分钟前
密码学安全实战:从加密原理到哈希破解的完整攻防指南
网络·算法·安全·web安全·开源·密码学·哈希算法
0xBADCODE2 小时前
Flask SSTI读SECRET_KEY+伪造Session:税务系统渗透全流程
前端·后端·python·安全·web安全·网络安全·flask
迪康coolmu2 小时前
企业文件外发防泄漏实践:从通道封堵到三层全链路管控
大数据·运维·网络·人工智能·安全·阿里云
石头猫灯11 小时前
WordPress wp2shell 漏洞链完整拆解流程
网络·数据结构·安全·web安全
网安蟹佬霸12 小时前
OSINT开源情报收集实战:从信息搜集到资产测绘(2026最新万字保姆级指南)
前端·网络·安全·web安全·网络安全·开源
ltl12 小时前
TLS 1.3 工程实践:1-RTT 与 0-RTT 的安全权衡
安全
mennekes14 小时前
数据中心安全配电设备如何选择?
运维·人工智能·科技·安全·制造
Flynt15 小时前
就编译了一下代码,浏览器密码没了——Rust 生态遭遇史上最狠供应链攻击
安全·rust·开源
行业研究员17 小时前
企业智能体安全产品选型指南
安全·智能体安全·产品选型