SyntaxFlow Zero to Hero: 跨函数与跨对象代码审计(一)

在第一篇 SyntaxFlow 引入文章 中,我们介绍了基本 SyntaxFlow 可以解决的问题,虽然我们屏蔽了大量的技术细节,但是很多读者并不只局限在“介绍”中,提出了很多比较经典的教科书中的问题。在接下来的系列文章中,我们将会花一些篇幅为大家介绍 SyntaxFlow 和 SSA IR 是如何解决教科书中的“高级话题”的。

当然,上篇文章中缺失了一些基本的引导,我们创建了

http://github.com/yaklang/syntaxflow-zero-to-hero 代码仓库,感兴趣的用户可以率先尝鲜~

什么是跨函数(跨过程)分析

跨函数分析我们在教科书中经常叫它“跨过程”分析,其核心是让数据流分析可以穿透一个函数执行过程。当然,我们已经默认现有的 IR 格式已经解决了数据流的问题。所以我们可以基于已经被理清楚的数据流进行分析(如果你有疑问,请先阅读《编译拾遗》两篇)。

我们用一个简单的 MVP 来说明跨过程分析的最核心的用途,大家一看便知。

在上述内容中,我们很轻易地发现了,Runtime.getRuntime().exec(actualCmd) 和 cmd 参数其实看起来通过 crossFunction 进行了链接(从语法上连接成立),但是仔细观察就会发现

public String crossFunction(String cmd) {

我们的 crossFunction 的返回值却和 cmd 没有半毛钱关系,那么从数据上的连接就是不成立的,这是一个数据流问题

从上面的这个案例来思考分析跨过程分析的意义,如果说我们可以洞悉 crossFunction,那么得出的结论是:“这命令执行的点不可控”,如果我们不知道 crossFunction 的实现,则得到的结论是“cmd”参数会影响 exec,这是一个命令执行漏洞点。如果不具备跨过程能力,得到的结论是不正确的,会有大量误报。

自动跨过程的表现形式

在进行下面的实验中,如果用户对

https://github.com/yaklang/syntaxflow-zero-to-hero 有一定了解,并尝试过 Hello World,会减轻很大部分的操作负担。

在保证安装了 yak 命令行之后,可以在

yak ssa-compile -t lesson-2 --program lesson2

编译后,执行审计代码

yak ssa --program lesson2 --sf 'getRuntime().exec(* #-> * as $source)'

这个含义是,审计 getRuntime() 这个成员的 exec 调用,追踪 exec 参数的最顶级定义(自动跨过程)

我们会看到执行结果为

❯ yak ssa --program lesson2 --sf 'getRuntime().exec(* #-> * as $source)'

我们虽然从语法上观察到了这个结果的可能受控制,但是代码分析并不应该给出控制位点,这个印证了我们自动跨过程分析的技术实现效果。

扫盲:变量追踪与数据流追踪

很多人会觉得上面这个跨过程案例比较难写代码审计,实际上是陷入了“变量”的陷阱,实际上我们在 SyntaxFlow 分析追踪数据流的过程中,并不知道变量是何物。我们只知道“值”什么时候存在,什么时候消亡

上面的代码看起来压缩成了一行

Process proc = Runtime.getRuntime().exec(extern.crossFunction(cmd));

人读起来非常精炼,但是代码审计的难度非常大,如果要使用“词法变量”概念来描述的话,甚至我们连 exec 参数的变量应该是谁都很难表达。更不用说递归调用的问题了。实际翻译成 SSA 之后,“临时变量”也会自动建立 Use-Def 关系,因此我们可以成功追踪。我们可以用一个很直观的图来表示这次审计出结果的数据流追踪问题(新版本中追加 --dot):

 yak ssa --program lesson2 --sf 'getRuntime().exec(* #-> * as $source)' --dot

将会得到输出中包含:

[INFO] 2024-06-20 11:57:55 [ssacli:195] ===================== DOT ===================

我们使用 dot 渲染图可以看最后一个目标数据流是什么,同样的,我们可以观察别的数据流

复杂数据流

我们决定观察一个数据流叫 fis,那我们如何获取这个 fis 的数据流?可以直接使用 fis #-> * as $data 来执行。

 yak ssa --program lesson2 --sf 'fis #-> * as $data' --dot

执行这个语句,将会在输出结果中看到:

[INFO] 2024-06-20 12:02:53 [ssacli:195] ===================== DOT ===================

渲染成图之后将会看到

我们通过底层 t1190527号 SSA 指令对应的数据流,直接追踪到了 Hello World。用人能听的描述可以说:“getInputStream() 的执行结果和 Runtime 还有 "echo Hello World" 有关(支配关系)”

总结

本文描述的内容中包含了 SyntaxFlow 的技术追踪跨过程数据流的能力,并且提供了在上一次文章的基础上,提供可以供用户使用的训练指引,后续我们将会逐步完善这些能力的细节实现并且逐步向大家揭示 SyntaxFlow 技术的技术实现:http://github.com/yaklang/syntaxflow

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值