概述
语法语义检测本质上属于静态代码分析,鉴于篇幅原因,我们分三讲来进行该部分:
- 第一讲从理论角度,论述基于语法语义的静态分析如何应用在webshell检测上,给出一个通用的检测框架。
- 第二讲从实践角度,讲述RIPS在基于给出的理论框架下的具体实现,实现从理论到实践的落地过程。
- 第三讲从代码角度,分析RIPS的架构设计和核心代码部分,从源码入手,深入分析其核心检测原理。
web应用安全漏洞的本质
一个web应用的大致结构如下:
一个web应用安全漏洞发生在用户提供的数据没有被正确过滤,并且该数据被应用在动态脚本的恶意操作中,因此也被称为污染型漏洞。
污染型漏洞的本质,是因为不可信的数据源的数据(比如用户提供的数据,通常被称为“污点数据”)到达了程序中的漏洞部分(sensitive sinks)。
任何能被用户修改的数据都需要被当做污点数据(比如GET/POST/COOKIE和数据库内的条目)。而程序中的漏洞部分通常指的是潜在的漏洞函数,简称为PVF(Potentially Vulnerable Functions)。PVF通常可能会被用来执行恶意操作,因此在正常业务中,PVF只能操作可信数据或者被净化过的数据。
下图展示了部分污染型漏洞的本质:
基于静态代码分析的检测框架
动态分析通常通过运行程序,指定输入,但是其只能分析在特定执行环境下程序能够走到的部分。而静态代码分析分析程序源代码不用去实际执行,可以同时分析代码中不同的执行路径,并对每一种可能的输入序列做出判断。
静态代码分析被用于很多用途,比如语法高亮,类型检查,bug查找等。任何检测源代码而不用执行它的工具都可以被归类为静态分析工具。
基于静态代码分析的检测包含四个步骤:
- 配置;
- 模型构建;
- 分析;
- 结果处理;
配置
首先,检测工具需要定义准确的规则来得知需要找什么。对漏洞分析来说,必须制定哪种类型的漏洞需要被检测和该种类型漏洞所包含的程序漏洞的具体模式(比如eval+外部输入即可判定为远程代码执行漏洞)。
然后,我们也需要定义哪些用户输入能够污染数据。
最后,需要定义适当的安全动作,用来处理最终的分析检测结果。
模型构建
静态分析工具需要把源代码转换成中间模型,中间模型是源代码的一种抽象内部表现形式,比如AST(抽象语法树)可以认为是源代码的一种中间表示形式。
检测工具的质量很大程度上依赖程序模型的质量,因此工具对语言语法的理解是非常重要的。
构建一个程序模型需要下面几步:
- 词法分析:工具需要切割源代码成词法单元(token)序列,用于准确识别程序结构。为了准确识别有联系的tokens不重要的token例如空格和注释会被清掉。
- 语义分析:检测工具检查每一个token的语义,这一步很重要的,用来决定一个token是函数调用,还是单纯的字符串或者其他语义单元。
- 控制流分析:所有可能的程序执行路径都会被检查。包括很少情况被执行的分支和函数调用。这些路径然后被综合成几个控制流图(control flow graphs:CFG),CFG代表了所有的数据流路径。
- 数据流分析:工具在每个CFG上执行数据流分析来检测数据在程序中的移动。此阶段可以定位漏洞的位置。数据流分析基于语义分析和控制流分析,所以之前分析的结果需要尽可能准确。
分析
基于构建的模型,工具可以进行在每一个被发现的PVF上进行漏洞分析。
污点分析
此阶段发现污染数据到达了PVF,因此一个安全漏洞可能存在。检测工具工具必须区分被污染的数据和不被污染的数据。比如下面例子:
/********************************远程命令执行漏洞*******************************/
<?php
$a = $_GET["a"];
$b = $a;
system($b, $ret);
/********************************无害的静态命令执行*******************************/
<?php
$a = $_GET["a"];
$b = "date";
system($b, $ret);
通过分析PVF参数的数据流,可以判断是否污染数据到达了敏感位置,还是PVF只是调用了一些无害的静态数据。
过程内和过程间分析
过程内分析包括追踪在一个被调用的自定义函数内的数据。如果一个PVF调用在函数定义内被发现,工具必须确定在哪种情况下该函数会触发一个漏洞。很大可能是PVF依赖用户自定义函数的参数,而该参数又可能是被污染的数据。
工具还必须有能力判断是否被污染数据又离开了自定义函数还是在函数内被净化了。函数也有可能返回被污染的数据,尽管并没有在参数中出现污染数据。
过程间分析是关于理解一个函数调用的上下文。随着程序状态的不同,函数调用的行为可能会不尽相同,或者在过程间全局变量的值发生了改变。
结果处理
最后一步需要把分析结果展示给用户,展示的方式需要能够让用户快速发现严重的漏洞。只展现重要的漏洞代码部分并且语法高亮能帮助回顾和分析问题。
同时,提供修复漏洞的帮助信息同样也很有用。
静态代码分析经常会产生误报和警告,因此以用户能自己判断是真正的漏洞还是误报的方式展示结果很重要。
总结
这一讲我们主要讲述了web安全漏的的形成机制,并以该形成机制为出发点,提出了一个通用的,可以用来检测各种web漏洞的检测框架。
下一讲,我们将以该框架为脉络,详细分析RIPS在框架各个部分的具体实现。