Web应用代码自动化审计浅谈
代码审计是找到应用缺陷的过程。自动化审计通常有白盒、黑盒、灰盒等多种方式。白盒指通过对源代码的分析找到应用缺陷;黑盒通常不涉及到源代码,多使用模糊测试等方式来找到漏洞;而灰盒则是黑白结合的方式,利用黑盒特性来减少白盒的计算复杂度,使用白盒的信息来衡量漏洞的有效性。
1. 基础概念
1.1 输入 (Source)
Web应用的输入,可以是请求的参数(GET、POST等)、上传的文件、Cookie、数据库数据等用户可控或者间接可控的地方。
例如PHP中的 $_GET / $_POST / $_REQUEST / $_COOKIE / $_FILES / $_SERVER 等,都可以作为应用的输入。
1.2 处理函数 (Filter)
处理函数是对数据进行过滤或者编解码的函数。这些函数会对输入造成影响,为漏洞利用带来不确定性。
同样以PHP为例,这样的函数可能是 mysqli_real_escape_string / htmlspecialchars / base64_encode / str_rot13 等,也可能是应用自定义的过滤函数。
1.3 危险函数 (Sink)
危险函数又常叫做Sink Call、漏洞点,是可能触发危险行为如文件操作、命令执行、数据库操作等行为的函数。
在PHP中,可能是 include / system / echo 等。
1.4 问题定义
一般认为一个漏洞的触发过程是从输入经过过滤到危险函数的过程(Source To Sink),而自动化审计就是寻找这个链条的过程。自动化审计的难点主要在于以下几个方面。
1.4.1 输入多样化
对Web应用来说,可能的输入可以来自GET/POST的参数、Cookie、Url等多个地方,这些输入格式不固定,输入空间很大。
1.4.2 过滤函数复杂
在审计的过程中,从输入没有经过任何过滤函数就到达危险函数的过程较少。但是自动化判断一些过滤数是否可以绕过较为困难。
1.4.3 代码本身的复杂度
现代Web框架,代码复杂度极高,有相当多的动态加载和调用的过程,为自动化分析带来了困难。
2. 技术基础
2.1 抽象语法树
抽象语法树,顾名思义,是一种树形的数据结构。构造AST树的基本方法是将表达式的操作数作为树结构的叶子,将表达式的操作符号作为树结构的根,依次循环迭代进行构造。
例如在JavaScript中, a=1 的抽象语法树如下:
{
"type": "Program",
"body": [
{
"type": "ExpressionStatement",
"expression":
{
"type": "AssignmentExpression",
"operator": "=",
"left":
{
"type": "Identifier",
"name": "a"
},
"right":
{
"type": "Literal",
"value": 1,
"raw": "1"
}
}
}],
"sourceType": "script"
}
2.2 程序控制流图
AST树依旧是比较高层次的形式,其中模块之间的调用、循环等依旧不利于数据流的处理,因此引入了更底层的程序控制流图来进行分析。
程序控制流图(Control Flow Graph,CFG)是静态分析过程中的另一种状态,可以反映程序代码控制流程。其实,程序控制流图是由一个入口、若干个出口组成的有向图,图中的每一个节点代表一个基本块,基本块中可以有一系列顺序执行的语句;图中的有向边,代表从出发节点到目标节点的控制依赖关系。
3. 解决方案
3.1 危险函数匹配
白盒审计最常见的方式是通过查找危险函数来定位漏洞,比较有代表性的工具是Seay开发的审计工具。这个工具直接找出所有危险函数的位置,这种方式没有对调用流程进行深入分析,相对误报率会比较高。
不过同样的,这种方式在一些环境下能做到几乎无漏报,只要审计者有耐心,可以发现应用大部分的漏洞,但是在高度框架化的代码中,这种方式能找到的漏洞相对有限。
3.2 代码相似性比对
一些开发者会复制其他框架的代码,或者使用各种框架。如果事先有建立对应的漏洞图谱,则可使用相似性方法来找到漏洞。
3.3 控制流分析
在2012年,Dahse J等人设计了RIPS,该工具引入AST进行数据流与控制流分析,结合过程内与过程间的分析得到审计结果,相对危险函数匹配的方式来说误报率少了很多,但是同样的也增加了开销。RIPS初始的版本开放源代码,而后闭源进行商业化。
3.4 基于图的分析
基于图的分析是对控制流分析的一个改进,其利用CFG的特性和图计算的算法,一定程度上简化了计算,比较有代表性的是微软的Semmle QL和NDSS 2017年发表的文章Efficient and Flexible Discovery of PHP Application Vulnerabilities。
3.5 灰盒分析
基于控制流的分析开销较大,于是有人提出了基于运行时的分析方式,对代码进行Hook,当执行到危险函数时自动回溯输入,找到输入并判断是否可用。
这种方式解决了控制流分析实现复杂、计算路径开销大的问题,在判断过滤函数上也有一定的突破,但是灰盒的方式并不一定会触发所有的漏洞。fate0大佬开发的prvd就是基于这种设计思路。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!