自黑神话悟空上线
相信很多小伙伴已经痛揍黑熊精
暴打虎先锋
想玩的心思溢出屏幕
但是班还是要上T T
第一难——“黑公司:上班”
而为了腾出更多时间畅玩游戏
在工作上也需要提升效率
工欲善其事,必先利其器
今天给大家带来的依旧是SyntaxFlow相关内容
为什么需要配置项语法呢?举个很简单的例子,比如我们在进行污点分析的时候,我们可能会会从sink
使用#->
跟踪到source
,这个时候整条数据流是连起来的,我们就能确定这是危险的代码吗?答案是不能,因为我们不知道中间有没有一些filter
去进行限制。而使用配置项语法,我们可以设置配置规则,让sink
的数据流一路往上过程中,根据配置规则检查每处数据流流经的过程是否是filter
。
再比如说,使用-->找到底层使用的时候,不想要找的太深,就可以使用-{depth:5}->这种语法规定向下最多找5层。
配置项语法是一项被大括号包围的键值对,如下所示:
{key:value}
其中,key为配置项名称,目前支持的配置项包括depth、include、exclude、until和hook。value为配置项规则,除了depth的value为数字,其余规则的value都是以反引号包围的SyntaxFlow语法。例如:
* #{include:`SyntaxFlow Rule`}-> as $result;
在详细介绍include、exclude、until和hook四个主要的配置项的行为之前,我们先需要了解一下配置项执行的原理。
我们还是以下面sink->source的图片为例子。其中我们称图中数据流经过的点为节点,如果我们没有配置配置项,而只是使用sink #-> as $result语法的话,那么最后拿到的结果result的内容为图中所有节点。
但是我们使用配置项语法的话,数据流在经过每个节点的时候,将会使用其配置的SyntaxFlow Rule对每个节点再次进行判断(简单来说就是碰到一个新的节点的时候,就会再运行一次SyntaxFlow,即对每个节点都进行一次hook)。比如下图中,我们使用的就是
$sink #{ include: `*?{<typeName>?{have: 'XSSFilter'}} ` }-> as $result
其中配置项的规则为*?{<typeName>?{have: 'XSSFilter'}} as $filter
,<typeName>
可以简单理解为获取节点的名称,而?{expression}
是一个条件语句,用于判断expression是否为真。
该配置项的SyntaxFlow Rule用来判断每个节点的名称是否包含XSSFilter,如果是的话,就将其作为filter,存放进去最后的结果$result中。
了解完配置项语法运行原理后,接下来将着重讲解include、exclude、until和hook这四个配置规则的区别。这四个规则可以从影响最终结果和影响数据流流动两个角度去区分。includeinclude会将所有符合规则的节点添加进去最终结果里面,同时这个过程中数据流不会停止,而会持续流动到结束。我们以下图中寻找exec的cmd参数的顶层定义的流图为例(该图为为方便讲解本章内容所作数据流图,SyntaxFlow所绘实际图片要远比这个复杂)。运行的SyntaxFlow规则为
.exec(* #{include:`?{opcode:const}`} as $result);// $result: node2、node5
规则中opcode可以简单理解为节点是什么类型的,因此?{opcode:const}可以认为找为常量类型的节点。
include:数据流从下往上找的过程中,碰到每一个节点都会运行新的SyntaxFlow,并使用配置项规则判断这些node是否为常量,如果为常量就加进去$result中,并继续往上寻找。从流图可以看见只有node2和node5为常量,因此结果$result只包含node2和node5。所以include规则会影响最后的结果,不会影响数据流的流动。
exclude
exclude则是和include相反的过程,同样的以该流图做例子。运行的SyntaxFlow规则为:
.exec(* #{exclude:`?{opcode:const}`} as $result);// $result: sink、node1、node3、node4、souce
exclude:数据流从下往上找的过程中,碰到每一个节点都会运行新的SyntaxFlow,并使用配置项规则判断这些node是否为常量,如果为常量就不加进去$result中,并继续往上寻找。最后的结果包含了除node2和node5的所有节点。所以exclude规则会影响最后的结果,不会影响数据流的流动。
untiluntil将会到达符合配置项规则的节点的时候停止数据流的流动,并返回。还是以该流图为例子。运行的SyntaxFlow规则为:
.exec(* #{until:`?{opcode:const}`} as $result);// $result: sink、node1、node2
until:数据流从下往上找的过程中,碰到每一个节点都会运行新的SyntaxFlow,并使用配置项规则判断这些node是否为常量,并将沿途经过的所有node加进去$result,直到碰到为常量的node的时候停止。该流图中,数据流会沿着sink->node1->node2流动,到node2的时候判断该节点为常量,数据流停止流动。最后的结果为sink、node1、node2。所以until规则会影响最后的结果,也会影响数据流的流动。
让数据流停止流动有什么好处呢?就是我们想要继续利用我们得到的节点就进一步书写规则。比如我们可以将以上规则写成这样:
.exec(* #{until:`?{opcode:const} as $const`} as $result);
这样你就可以使用$const继续去写后面的SyntaxFlow规则。hook就像其名字hook一样,该配置项对数据流的流动、最终的结果都没有任何影响。但是它能够让你使用新的SytaxFlow对每个节点运行,并可以在后续规则中使用运行过程中产生的结果。在《吹爆SyntaxFlow!数据流分析实战解析》的进阶使用便是使用了该配置项,并有实战的例子。这里便不多介绍。
以下是目前SyntaxFlow中所支持的配置项:
配置名称 | 是否影响最终结果 | 是否影响数据流 | 用法示例 |
include | 影响。会将匹配规则的节点加入最终结果。 | 不影响。 | #{include:`syntaxFlow Rule`}-> as $result; |
exclude | 影响。会将不匹配规则的节点加入最终结果。 | 不影响。 | #{exclude:`syntaxFlow Rule`}-> as $result; |
until | 影响。会将数据流流经的节点加入最终结果。 | 影响。数据流会在匹配的节点停止。 | #{until:`syntaxFlow Rule`}-> as $result; |
hook | 不影响。 | 不影响。 | #{hook:`syntaxFlow Rule`}-> as $result; |
https://github.com/yaklang/syntaxflow在SyntaxFlow样例中,多次使用了带有配置项语法的#->或-->,感兴趣的小伙伴可以试着阅读相关Java源码与sf规则。参考上方链接或者点击阅读原文即可跳转。
- XSSFilter的检测。
- Spring框架下文件上传漏洞的检测。
- Servlet输入可控参数的检测。
END
YAK官方资源 Yak 语言官方教程:
https://yaklang.com/docs/intro/
Yakit 视频教程:
https://space.bilibili.com/437503777
Github下载地址:
https://github.com/yaklang/yakit
Yakit官网下载地址:
https://yaklang.com/
Yakit安装文档:
https://yaklang.com/products/download_and_install
Yakit使用文档:
https://yaklang.com/products/intro/
常见问题速查:
https://yaklang.com/products/FAQ