人与代码的桥梁-聊聊SAST

0x00 前言 自从人类发明了工具开始,人类就在不断为探索如何更方便快捷的做任何事情,在科技发展的过程中,人类不断地试错,不断地思考,于是才有了现代伟大的科技时代。 在安全领域里,每个安全研究人员在研究的过程中,也同样的不断地探索着如何能够自动化的解决各个领域的安全问题。其中自动化代码审计就是安全自动化绕不过去的坎。 而SAST作为自动化代码分析的一种,有着其特有的定位以及作用,这篇文章我们就来聊聊静态分析的一些发展历程和思路。 :::info SAST是什么? ChatGPT:SAST是Static Application Security Testing(静态应用程序安全测试)的缩写。它是一种用于检测软件应用程序中潜在安全漏洞和代码缺陷的自动化安全测试方法。 ::: 0x01 静态代码分析工具 静态代码分析我们可以理解为在不执行代码的情况下,通过静态的手段进行分析代码,并挖掘相应的漏洞/Bug. 再过去的十几年里,静态代码分析工具经历了长期的发展与演变过程,下面我们就一起回顾一下(下面的每个时期主要代表的相对的发展期,并不是比较绝对的诞生前后): 上古时期 - 关键字匹配 如果我问你“如果让你设计一个自动化代码审计工具,你会怎么设计?”,我相信,你一定会回答我,可以尝试通过匹配关键字。紧接着你也会迅速意识到通过关键字匹配的问题。 这里我们拿PHP做个简单的例子。 虽然我们匹配到了这个简单的漏洞,但是很快发现,事情并没有那么简单。 也许你说你可以通过简单的关键字重新匹配到这个问题 \beval\(\$ 但是可惜的是,作为安全研究员,你永远没办法知道开发人员是怎么写代码的。于是选择用关键字匹配的你面临着两种选择: 高覆盖性 – 宁错杀不放过 这类工具最经典的就是Seay,通过简单的关键字来匹配经可能多的目标,之后使用者可以通过人工审计的方式进一步确认。 \beval\b\( 高可用性 – 宁放过不错杀 这类工具最经典的是Rips免费版 \beval\b\(\$_(GET|POST) 用更多的正则来约束,用更多的规则来覆盖多种情况。这也是早期静态自动化代码审计工具普遍的实现方法。 但问题显而易见,高覆盖性和高可用性是这种实现方法永远无法解决的硬伤,不但维护成本巨大,而且误报率和漏报率也是居高不下。所以被时代所淘汰也是历史的必然。 近代时期 - 基于AST的代码分析 有人忽略问题,也有人解决问题。关键字匹配最大的问题是在于你永远没办法保证开发人员的习惯,你也就没办法通过任何制式的匹配来确认漏洞,那么基于AST的代码分析方式就诞生了,开发人员是不同的,但编译器是相同的。 在分享这种原理之前,我们首先可以复习一下编译原理。拿PHP代码举例子: 随着PHP7的诞生,AST也作为PHP解释执行的中间层出现在了编译过程的一环。 通过词法分析和语法分析,我们可以将任意一份代码转化为AST语法树。PHP常见的语义分析库可以参考: PHP-Parser phply 当我们得到了一份AST语法树之后,我们就解决了前面提到的关键字匹配最大的问题,至少我们现在对于不同的代码,都有了统一的AST语法树。如何对AST语法树做分析也就成了这类工具最大的问题。 在理解如何分析AST语法树之前,我们首先要明白infomation flow、source、sink三个概念, source: 我们可以简单的称之为输入,也就是infomation flow的起点 sink: 我们可以称之为输出,也就是infomation flow的终点 infomation flow,则是指数据流动的过程。 把这个概念放在PHP代码审计过程中,Source就是指用户可控的输入,比如$_GET、$_POST等,而Sink就是指我们要找到的敏感函数,比如echo、eval,如果某一个Source到Sink存在一个完整的流,那么我们就可以认为存在一个可控的漏洞,这也就是基于infomation flow的代码审计原理。 在明白了基础原理的基础上,我举几个简单的例子: <?php $a = $_GET[‘a’]; eval($a); 这段代码对应的AST为: Assignment(Variable('$a'),ArrayOffset(Variable('$_GET'), 'a'), False) Eval(Variable('$a')) 1、Eval函数...

2023年12月20日 · 2 分钟 · LoRexxar