基于执行域敏感属性图的指针类漏洞检测

2024-11-29 00:00:00陶韬王伟杰唐成华
电脑知识与技术 2024年27期

摘要:针对同内存空间操作的多指针变量关系和跨函数调用的指针特征,文章提出一种基于执行域敏感属性图的指针类漏洞检测方法。文章采用语法、控制流、指针关系和函数调用来刻画程序及其指针变量的执行过程并构建执行域敏感属性图,聚焦于指针行为特征及与内存域的联系,通过图遍历得到与指针类漏洞相关的节点与边,并基于漏洞特征实现指针类漏洞的检测。实验结果表明,提出的方法在漏洞发现的准确率、误报率和漏报率上均有较好表现,为执行域敏感属性应用于软件漏洞检测提供了新的可靠途径。

关键词: 指针漏洞;指针依赖;函数调用;敏感属性图;漏洞检测

中图分类号:TP393.08 文献标识码:A

文章编号:1009-3044(2024)27-0004-04

0 引言

由错误使用内存所引发的安全漏洞是软件开发的安全隐患之一,主要涉及对内存管理的错误或不当使用。常见的内存相关漏洞包括缓冲区溢出、已释放内存重用、内存泄漏等,通常发生在程序未正确验证输入数据的长度或类型,导致数据超过分配的内存空间或者内存数据被篡改,并可能被攻击者利用来执行任意代码、绕过安全检查、拒绝服务等。典型的如微软披露的涉及25个严重内存分配漏洞的家族“BadAl⁃loc”,源于易受攻击的内存功能相关的指针使用,攻击者可以利用这些漏洞绕过安全控制,以执行恶意代码或导致系统崩溃。深信服科技《2022漏洞威胁分析报告》指出[1],漏洞数量持续增长,由漏洞引发的主要威胁有未授权的信息泄露和管理访问权限获取,网络攻击趋于破坏性攻击。Fortinet《2023上半年全球威胁态势报告(1H 2023 Global Threat Landscape report) 》指出[2],过去五年间检测到特定漏洞被利用次数增加了68%,潜在威胁者往往使用转入捕获技术拦截用户输入以非法窃取凭据信息或通过在内存中查找凭据并收集数据。在众多漏洞类型中,与内存相关漏洞的危害性不容小觑,其中,“释放后重用”(Use-After-Free) 更是成为2023年CWE TOP 5之一。

鉴于软件开发中的安全左移原则,静态分析在检测指针类漏洞方面已取得一定成果,其判定依据主要包括数据流分析中指针的位置与精度以及内存数据的变化情况。然而,当前方法仍面临诸多挑战。一方面,由于与内存相关联的多指针变量之间的复杂关系由内存区域决定,若多个指针对同一内存空间进行操作,简单的别名分析方法难以准确判定指针间的实际关系,从而可能导致漏洞的误报或漏报[3]。另一方面,静态分析指针类漏洞的过程需跨越函数或过程的界限,全面考虑函数调用时参数与其他变量的相互影响、内存共享以及指针运算时的内存指向信息,否则将忽略过程间行为或上下文信息,降低漏洞检测的准确性。

1 基于执行域敏感属性图的漏洞检测模型

基于代码属性图(CPG) 的生成[4],通过指针关系依赖和函数调用等子图构建执行域敏感属性图并用于指针类漏洞检测的模型(EDSPG) ,如图1所示。首先,构建源代码的执行域敏感属性图,包含多个角度检测漏洞所需的语义信息,其关键在于通过定义指针与内存区域之间的抽象关系和函数调用的规则[5],旨在获取指针变量之间基于内存区域的精确联系,并用于构建属性图的指针关系子图和函数调用子图。其中,前者通过指针变量所分配的内存域体现它们之间的关系,并用于刻画程序的执行过程,尤其是涉及指针变量的部分。其次,建立基于特定标签或属性的遍历规则,用于指导沿图的边和节点的移动策略,目的在于获得与指针类漏洞相关的部分,该过程涉及识别和跟踪关键的节点和边,用于漏洞的准确定位。第三,基于漏洞特征建立漏洞判定规则,基于漏洞的特征形式化描述,针对执行域敏感属性图实现指针类漏洞的检测。

执行域敏感属性图展示了程序相关语义和执行流程,包括运行时为指针分配的动态内存域以及指针指向的内存域变化。图的结构由源代码抽象语法树、程序控制流图、指针关系依赖图和函数调用图聚合而成,聚焦于指针的行为特征及与内存联系,并用于检测指针类漏洞。

2 指针关系依赖图

指针描述内存单元的地址,指针变量间的关系体现指针所指向内存的关联性。采用基本变量的数据流分析方法不能有效检测出由内存状态引发的漏洞。因此,建立面向指针变量的抽象内存模型,通过记录程序路径中各个程序点的指针变量并形成相应的抽象内存模型记录,以获得指针变量与内存的关联,进而通过分析抽象内存模型获得指针之间的依赖关系,构建指针关系依赖图。

定义1 指针抽象内存模型可描述为Mp=。其中,Var表示指针变量名称;Type表示指针变量定义的类型;Region表示指针变量关联的抽象内存区域属性,描述为(typex,byte,offset),这里typex为指针指向抽象内存区域的唯一编号,byte表示指针变量指向内存区域占用的字节数;offset表示指针的偏移量;Scope表示指针变量的作用域;State代表指针变量的状态;LineN为代码行号。

定义2 指针运算是包含指针和地址的操作,用于对表达式左值的指针赋值,可描述为pointer opera⁃tion ::= p+offset| array+offset| array[j]+ offset。

指针运算的形式包括指针变量对于分配基本变量类、数组类、数组元素类等内存后的偏移量运算等。每种运算形式可能会改变左值变量指针指向的内存域,从而导致左值指针变量的指针抽象内存模型发生变化。

通过定义指针抽象内存模型以及指针运算,可得到程序中具体指针变量的六元组及指针变量指向内存的状态变化。图2为一段能引发Use-After-Free漏洞的代码实例,可用定义第2行指针变量q,用 表示第3行状态更新后的指针变量q,用定义第7行指针变量p,使用公式np=p+offset计算第8行的op()操作,形如(np:p) = (p:q)+(offset:0),可将指针变量p的指针抽象内存模型更新为,计算出指针变量p 和q 指向同一块内存区域int1,为指针变量p 和q之间依赖关系的定义提供条件。

为了捕获指针变量基于内存域的联系,通过抽象内存模型获取指针变量分配的内存域信息,并基于指针运算规则更新抽象内存模型六元组以更新指针变量指向内存域的变化信息。通过抽象内存模型六元组描述指针变量的依赖关系,基于指针变量的依赖关系建立指针关系依赖图。

3 函数调用图

通过函数调用图获得本体函数到被调用函数的可达路径,实现跨函数的路径分析。当变量的值取决于其他函数的输出时,通过追踪这些依赖关系,可准确地获取这些变量的信息,提高代码分析的精度。在源代码抽象语法树中,一个函数体内调用的其他函数方法被表示为这个函数体形成的源代码抽象语法树中的一个节点,它对应于被调用函数的源代码抽象语法树的根节点。因此,基于源代码抽象语法树,合并同名方法的函数调用节点和函数定义节点,形成函数调用边并最终得到函数调用图。

图2漏洞代码实例的函数调用图构建过程如图3 所示。首先遍历函数体内调用函数类型的节点,主函数中调用了名为op的函数,表现为主函数的源代码抽象语法树中有一个类型为“FunctionExpression”的名为op的节点,再遍历找到根节点与其同名的源代码抽象语法树,添加一条函数调用边将主函数调用语句节点与被调用函数根节点连接。

4 执行域敏感属性图及其遍历

执行域敏感属性图由源代码抽象语法树、程序控制流图、指针关系依赖图和函数调用图取并集建立,Computer Knowledge and Technology 电脑知识与技术第20 卷第27 期 (2024 年9 月)不同子图表示不同的代码语义信息。对执行域敏感属性图遍历,是按一定的规则检索图中节点和边,即从任一节点或边开始,匹配属性和边的类型,沿边正向或者逆向搜索到与之相邻的下一组节点或边,终止于符合条件的节点或边。

图2 代码实例在执行printf 函数时引发Use-After-Free 漏洞,其中,指针变量q和p、malloc 函数、free函数等构成漏洞的词法特征。实际上,与指针类漏洞相关的词法特征包括指针变量与指针运算符、内存分配函数(如malloc、calloc、realloc、new等)、内存释放函数(如free、delete等)、内存区域操作行为运算符等。将漏洞的词法特征定义为敏感因子s,它是漏洞出现的必要条件。由于属性图节点由源代码抽象语法树节点构成,因此属性图包含源代码抽象语法树的全部信息,这些信息可以描述程序的词法和语法结构信息,通过语法结构找到漏洞敏感因子。

图2代码实例漏洞的出现依赖于对指针变量分配内存的操作、对指针指向的内存区域进行操作以及释放指针所指向内存的操作等3个关键语法特征。因此,与指针类漏洞相关的语法特征包括为指针变量分配内存的语句、释放所分配内存的语句、内存区域操作的语句等。显然,漏洞的语法特征包含了漏洞敏感因子。将包含敏感因子的语句定义为漏洞敏感点Ns。

除了漏洞敏感点,还需分析其语义特征才能判定是否存在漏洞。在图2代码实例中,因为op函数为指针变量q分配内存后进行了释放内存的操作,之后又通过指针p访问了该内存域,表现为程序中存在漏洞敏感点,且漏洞敏感点按一定顺序执行。这一特征构成了Use-After-Free漏洞的语义特征,称为漏洞约束,记为R。

定义3 漏洞特征C 可描述为C(VType)={Ns, R}。其中:VType为漏洞类型;Ns为漏洞敏感点;R为漏洞约束。

定义3 具有性质{Prog}CVType{VulVTypeProg},即对于程序Prog,若满足漏洞类型VType的漏洞特征CVType,则Pro47e50379a2c962015116d6ddba14844fdd3255a9cd178e1706c29192168fd77fg存在状态为VulVTypeProg,类型为VType的漏洞。

5 实验结果与分析

实验选取C/CPP 的Juliet Test Suite for C/C++ 1.3 作为测试数据集,选取CWE-401(Memory Leak) 、CWE-415(Double-Free) 、CWE-416(Use-After-Free) 和CWE-762(Mismatched Memory Management Rou⁃tines) 4种指针类漏洞用于测试。使用Cloc工具获得数据集信息如表1所示。

将本文方法EDSPG 与Cppcheck[6]、Flawfinder[7]、Splint[8]、MRVDAVE[9]、CPG等模型进行对比,采用误报率FPR、漏报率FNR和准确率Acc作为评估指标。

用不同检测方法对数据集开展漏洞检测实验,其中与CWE-416漏洞有关的检测情况如表2所示,表中,DVN为相应方法或模型检测出的漏洞数量,DVT 为检测出的正确漏洞数量,DVF为误报漏洞数量。针对CWE-416 漏洞,Cppcheck 和Flawfinder 出现100% 误报率,主要因为Cppcheck专注语法和代码质量检查,不能深入分析内存使用的状态变化,而Flawfinder 基于文本搜索和模式匹配,无法理解内存生命周期。相比之下,MRVDAF和EDSPG方法通过内存分配、使用及释放等语义规则,能更准确地追踪和理解内存周期,均提高了正确漏洞识别的数量。

误报率情况如图4所示。由于Cppcheck和Flaw⁃finder不进行数据流深度分析,检测存在较高误报率。Splint虽然增加了语义分析,但误报率也较高。而具有数据流分析能力的MRVDAF和聚合了多种层次语义的联合图结构的CPG,误报率均较低。EDSPG构建了指针变量之间的关系依赖边,表达了更为精确的指针变量关系语义,同时基于执行域敏感属性图对这4 种漏洞类型进行形式化描述,在指针类漏洞检测上具有更低的误报率。

漏报率情况如图5所示。Cppcheck和Flawfinder 由于没有涉及语义分析,对于含较复杂语义程序的漏报率很高。Splint只匹配了基本程序语义,对于深层程序行为无法分析,导致漏报率也较高。MRVDAF因为定义了漏洞的形式化信息并用于程序分析,较低了漏报率。CPG由于结构是单一函数且缺少过程间分析,导致漏报率偏高。EDSPG通过关系依赖边获得指针变量的精确语义,并具备程序过程间分析,实现了更低的指针类漏洞漏报率。

准确率情况如图6所示。在需要语义分析的漏洞中,Cppcheck和Flawfinder均无法准确检测出漏洞,仅依赖数据流分析的Splint和依赖各层图语义的CPG在漏洞检测准确性上表现不佳。MRVDAF在数据流分析的基础上增加了漏洞的形式化信息,提升了漏洞检测准确率。EDSPG方法包含了与指针有关的行为信息,通过定义图的遍历与指针的行为描述,实现了较为全面的基于模型的漏洞分析,进一步提升了漏洞检测准确率。

6 结束语

不同漏洞类型蕴含不同的特征,本文提出基于执行域敏感属性图的指针类漏洞检测方法,通过分析指针与内存关系,定义模型的子图并使方法具备过程间分析的能力。实验表明,EDSPG在Juliet数据集上对于4种指针类漏洞的检测能力更好,漏洞检测的准确率上升,误报率与漏报率降低。由于本文未考虑指向函数的指针变量情况,某些特殊的调用过程是通过函数指针调用并引发漏洞问题,且本文提出模型未考虑程序路径的可达性问题。下一工作,将进一步完善指针规则描述和可达性判断,提升方法的有效性。

参考文献:

[1] Sangfor. 2022 漏洞威胁分析报告[EB/OL]. [2023-11-16]https://www.sangfor.com.cn/document/.

[2] FORTINET. FortiGuard Labs 1H 2023 Global Threat Land⁃scape Report[EB/OL]. [2023-09-28] https://www.fortinet.com/demand/gated/threat-report-1h-2023.

[3] JIN W H,ULLAH S,YOO D,et al.NPDHunter:efficient null pointer dereference vulnerability detection in binary[J]. IEEE Access,2021,9:90153-90169.

[4] YAMAGUCHI F,GOLDE N,ARP D,et al.Modeling and discov⁃ering vulnerabilities with code property graphs[C]//2014 IEEE Symposium on Security and Privacy.May 18-21,2014,Berkeley,CA,USA.IEEE,2014:590-604.

[5] 陈涛清,范广生,尹帮虎,等.基于抽象解释的函数内联过程间分析优化方法[J].软件学报,2022,33(8):2964-2979.

[6] Cppcheck-2.12[CP/OL]. [2023-09-10] http://cppcheck.source⁃forge.net.

[7] Flawfinder-2.0.19[CP/OL].[2023-09-06]https://www.dwheeler.com/flawfinder.

[8] Splint-3.1.2[CP/OL]. [2023-9-6] https://www.splint.org.[9] HU J C,CHEN J F,ZHANG L,et al.A memory-related vulner⁃ability detection approach based on vulnerability features[J].Ts⁃inghua Science and Technology,2020,25(5):604-613.

【通联编辑:代影】

基金项目:国家自然科学基金(项目编号:62062028) ;广西可信软件重点实验室基金(项目编号:202320) ;广西研究生教育创新计划项目(项目编号:YCSW2023295)