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

相关推荐
BEOL贝尔科技1 小时前
样本安全存储中还有哪些重要因素需要考虑?如何设置样本安全?
人工智能·安全·数据分析
卓豪终端管理1 小时前
零信任落地,终端是「最后一公里」也是「最难一公里」
安全
RisunJan3 小时前
Linux命令-shutdown(安全关闭或重启系统)
linux·服务器·安全
贩卖黄昏的熊4 小时前
NestJS简明教程——安全
开发语言·javascript·安全·typescript·nest.js
山东科恩光电5 小时前
如何通过安全地毯确保工业现场的人员防护?
安全
小小代码狗6 小时前
PHP 常用函数与变量参考文档
开发语言·安全·php
笨鸟先飞,勤能补拙7 小时前
下一个十年:网络安全正在被重写
网络·人工智能·安全·web安全·网络安全·github
月光船幽幽7 小时前
安全域公理:连续与脉冲扰动的量化约束
科技·安全
各类产品分享8 小时前
化工园区做AR安全巡检推荐哪家供应商
安全·ar·ar智慧运维解决方案
米瑞格门窗8 小时前
上海系统门窗哪个靠谱
大数据·人工智能·安全·家装·家装建材·系统门窗