题目:Software Vulnerability Detection using Backward Trace Analysis and Symbolic Execution
作者:Hongzhe Li, Taebeom Kim, Munkhbayar Bat-Erdene and Heejo Lee
单位:Div. of Computer and Communication Engineering, Korea University, Seoul, South KOREA
问题:
符号执行存在路径爆炸问题,且在大型程序分析中效率不高。事实上,大多数的路径是与安全问题无关的,软件脆弱性通常由于不正当使用一些安全敏感的函数导致的,通过从安全敏感的函数开始逆向追溯敏感数据可以只考虑脆弱性相关的路径,这样就可以有效减少路径数量。
方案:
先逆向地分析执行轨迹然后正向地进行符号执行。
首先通过模式匹配技术分析源代码找到所有可能造成脆弱性的热点,然后从每个热点开始,逆向分析源代码并为每个热点构建数据流树,从数据流树中可以得到到达这个热点的所有可能路径。根据执行路径执行符号执行收集程序约束PC和安全性约束SC。如果程序中的变量存在满足PC && !SC的赋值,就会报这个热点存在脆弱性。
实验评估性能是已有工具中最好的,有效缓解了传统符号执行中路径爆炸问题。
贡献:
1.与其他静态分析技术不同,在检查软件脆弱性时考虑到了程序追踪执行条件(program trace execution conditions),极大降低了误报率。
2.只考虑脆弱性相关路径缓解符号执行路径爆炸问题。逆向追溯热点处使用的敏感数据,利用数据流树只覆盖与敏感数据相关的分支。使检测更高效。
3.PC && !SC的约束求解准确检测软件脆弱性
原理:
1.热点(hot spot)定义:一个安全敏感的函数,在它的参数中包含敏感数据。
敏感数据派生自不信任的输入源(如输入文件或网络消息、命令行选项等)。
2.安全性约束SC(security constraint)是确保系统安全程序变量必须要满足的约束条件。
3.五个步骤:
1)检查热点,敏感函数比如strcpy,memcpy,printf等。采用简单的模式匹配策略完成
脆弱性通常由于在敏感函数中溢出的值造成的,分类四类:
a.内存拷贝
b.内存访问
c.内存分配
d.格式化字符串
2)构造数据流树:用于生成可能的执行路径,在这个过程中与热点或敏感数据无关的路径会被自动裁剪掉。易于观察用户输入与函数参数之间的关系以检查出热点中的参数是否被用户输入污染。从每个热点开始,逆向追溯参数直到到达敏感数据的源头(origin)。
几个定义:
a.Variable Source(S):获得变量来源的代码语句
–变量被赋值的代码语句:Va=expression
–变量被作为参数的函数声明语句: Va=void f(int Va,..,)
b.Variable Origin(O):变量值不依赖于任何其他变量的代码语句。variable origin也是variable source,variable source可能是variable origin。
–变量被赋值为具体值的代码语句:Va=const
–变量从输入文件、网络消息或命令行选项获得值的代码语句:Va=readfile(); scanf(“%s”, &Va);
–变量被创建的代码语句:char Va=’C’
热点语句被作为数据流树的根节点。构建数据流树的关键部分是追溯变量,过程如下:
a.在树节点中找到需要被追溯的变量
b.对于在树节点A中需要被追溯的变量,我们找到它的source并把它放到A的子节点B中,如果该变量的source在n个不同的互斥分支中我们就把这n个source分别放到A的n个子节点中。
c.重复步骤a直到树节点中的source都变为origin。
d.找到origin后,再根据函数定义-调用逻辑继续构建子节点直到到达程序入口函数,如main函数。
构建数据流树的算法:
3)生成可能的执行路径:构建了数据流树后自动生成可能的执行路径。
4)程序约束PC和安全约束SC生成:在生成的追踪轨迹上执行符号执行获得PC和SC。
沿着生成的执行路径进行符号执行得到的可能是个粗略的路径约束条件,因为由数据流树得到的路径只关注了部分变量,还有其他的约束我们没有发现。
A. 到目前位置的PC的生成:沿着上一步骤得到的路径执行符号执行会得到粗略的路径约束条件集合,这里面有没被找到origin的变量,我们要把对它们再进行分析:
变量分为两种:
a.被追踪的:已经被追溯了,知道它的origin
b.未被追踪的:未被追溯,不知道它的origin
对未被追溯的变量我们对他进行追踪直到找到它的origin,在此过程中之前的路径会被分裂为更为准确的路径。这个过程直到约束集中没有未被追溯的变量为止。
B. SC的生成:来自于事先定义好的安全要求。
PREDEFINED SECURITY CONSTRAINTS:
strcpy(dst., src) Dst.spcace > src.strlen
strncpy(dst, src, n) (dst.space = n) ∧ (n = 0)
strcat(dst, src) Dst.space > dst.strlen + src.strlen
getcwd(buf, size) (buf.space = size) ∧ (size = 0)
fgets(dst, size, f ) (dst.space = size) ∧ (size = 0)
printf (f ormat, …) #of formats = #of parameters − 1
5)PC和SC验证:可满足性检查器用于检查PC && !SC的可满足性,当有解时发现了一个脆弱性。用求解结果生成揭露这一脆弱性的测试用例。将PC和SC都用SMT-LIB的形式表示,并用Yices SMT-solver作为求解器。
评估:
选取了20个Juliet Test Suite v1.1 C/C++测试集中包含缓冲区溢出和格式化字符串错误的程序用例。考察误报率和漏报率。
准确率83.33%,回调率90.90%,F1分数F1_Value86.95%
局限:
1.由于无法处理与敏感函数无关的路径导致有些类型的缺陷无法覆盖
2.没有处理复杂真实世界程序中的复杂的数据类型如C语言里的结构等,造成误报
3.有些复杂函数如加密函数、校验和函数等导致约束求解遇到困难