本文档发表于2024年IEEE Conference on Software Testing, Verification and Validation (ICST)。主要作者包括中国海洋大学的鄢卓、刘可、屈超、曲海鹏(通讯作者)以及奇安信技术研究院的应凌云(通讯作者)。
研究团队旨在解决软件漏洞根因分析(Root Cause Analysis, RCA)领域的核心挑战。随着模糊测试(Fuzzing)技术的广泛应用,安全漏洞被大量发现,但随之而来的海量崩溃报告(Crash Reports)给开发人员修复漏洞带来了沉重负担。自动化漏洞根因分析技术,特别是基于统计行为的分析方法,能够通过对比崩溃输入与非崩溃输入的执行差异,定位导致崩溃的根本原因代码,从而辅助开发人员快速理解和修复漏洞。然而,现有方法(如Aurora和VulnLoc)存在高时间成本、强随机性以及结果不精确等问题,限制了其在现实场景中的实用价值。具体来说,这些方法在“数据增强”(Data Augmentation)阶段严重依赖长时间、非确定性的模糊测试来生成大量崩溃/非崩溃输入,且未能有效确保新生成的崩溃与原始概念验证(Proof of Concept, PoC)文件具有相同的崩溃根因,即存在“崩溃一致性”(Crash Consistency)问题,导致数据集引入噪音,最终影响分析精度。
为此,研究者提出了一种高效、准确的基于统计分析的漏洞根因分析工具,命名为RCLocator。其核心目标是:1)显著降低根因分析的时间成本;2)提高分析结果的准确性;3)为开发人员提供关于根因谓词的有效解释。RCLocator的设计与工作流程包含三个核心模块:预处理、数据增强和特征提取。
在预处理阶段,研究团队首先使用其自主研发的自定义消毒剂(Sanitizer)CSan编译目标程序。CSan的核心功能是在程序发生崩溃时捕获一个“崩溃信息元组”(Crash Information Tuple, CIT)。CIT根据崩溃类型(如栈溢出、堆溢出、除零错误等)包含不同的信息组合,例如崩溃类型、崩溃点、调用栈哈希、导致崩溃的数据结构地址或变量名等。CIT的引入是为了严格区分不同根因的崩溃,其比传统的基于覆盖率或调用栈的崩溃分桶(Crash Bucketing)方法更加严格和可靠。接着,对原始的PoC文件进行最小化处理,去除其中不影响触发目标崩溃的冗余字节,使得后续字节突变能更有效地影响程序执行路径。
数据增强阶段的目标是为后续的特征提取提供足量且多样化的、保证崩溃一致性的输入文件。RCLocator摒弃了传统的耗时模糊测试方法,提出了一种基于CIT和字节级突变的高效数据增强方法。该方法分为单字节突变和多字节突变两种策略: 1. 单字节突变:对最小化PoC文件的每一个字节,依次尝试将其值修改为0-255。对于每个突变结果,运行程序并检查其输出。如果程序崩溃,则使用CSan获取其CIT,并与原始PoC的CIT进行比对。仅当两者一致时,该崩溃文件才被保留,确保了崩溃输入集的一致性。如果程序未崩溃且未主动报错,则视为非崩溃文件。为避免生成过多文件增加后续开销,研究人员设计了一个基于PoC文件长度和总突变次数的概率采样公式,同时规定:如果一个字节的突变既能产生崩溃也能产生非崩溃结果,则该字节的所有突变结果均被保留,这有助于增强结果的稳定性。 2. 多字节突变:针对文件长度较大的情况,采用每次随机选取10-100个字节并赋随机值的策略,执行足够次数(如6000次)的突变,并同样使用CIT进行崩溃一致性过滤。
这种基于字节突变和CIT过滤的方法,能够在极短的时间内(几分钟到几十分钟)生成数千个可靠的崩溃和非崩溃输入文件,相比Aurora(2-12小时)和VulnLoc(4小时)的数据增强阶段,效率得到了数量级的提升,并从根本上解决了崩溃一致性问题。
在特征提取阶段,RCLocator对上一步生成的数据集进行动态执行。研究团队使用Intel Pin工具来收集程序执行信息,记录每条指令最后一次执行的动态值(修改的寄存器或内存地址及其值)和执行顺序。基于这些动态执行信息,RCLocator为每条指令生成“谓词”(Predicate)。一个谓词包含指令地址、对指令动态值的语义描述(例如“变量x的值大于等于3”)、一个根因得分以及一个谓词必要性得分。其中,根因得分的计算公式为 (满足谓词语义且崩溃的次数 + 不满足谓词语义且不崩溃的次数) / 总输入文件数。该得分用于衡量该谓词在语义上区分崩溃与非崩溃执行的能力,得分越高(越接近1),表明该谓词越可能是崩溃的根因。谓词必要性得分的计算公式为 满足谓词语义且崩溃的次数 / 总崩溃次数,用于衡量该谓词对于触发崩溃的必要性。谓词的语义是通过遍历该指令修改的寄存器或内存的所有动态值,并测试“大于等于”和“小于”两种模板,选取能获得最高根因得分的那个语义描述而动态生成的。此外,RCLocator还计算了指令必要性得分(执行了该指令的崩溃输入占所有崩溃输入的比例)和指令执行顺序得分(该指令与崩溃点在动态执行中的距离)。
在结果排序阶段,RCLocator根据四个指标对指令谓词进行排序,优先级依次为:根因得分、谓词必要性得分、指令必要性得分、指令执行顺序得分。理想情况下,根因谓词在前三个指标上的得分都应为1。最终,RCLocator输出排序靠前的谓词,特别是那些被认为是“根因谓词”的指令及其语义解释,为开发人员提供了对崩溃原因的清晰说明。
研究团队在RCABench漏洞数据集以及从现实世界收集的共计15个不同类型(包括堆溢出、栈溢出、全局溢出、空指针解引用、释放后重用、浮点异常等)的漏洞上对RCLocator进行了系统评估,并与当前最先进的方法Aurora和Vulnloc进行了对比。
评估的主要结果如下: 1. CIT的有效性验证(RQ1):通过对Aurora所使用的AFL崩溃探索模式生成的崩溃数据集进行分析,发现对于Aurora能成功分析的漏洞,其生成的崩溃文件中CIT与原始PoC一致的占比较高;而对于Aurora分析失败的漏洞,其崩溃数据集中包含大量不一致的CIT(即不同根因的崩溃),这直接引入了噪声。例如,在CVE-2016-9264中,只有9.8%的崩溃文件与原始PoC的CIT一致。这验证了CIT作为崩溃一致性过滤标准的合理性与必要性。 2. RCLocator的整体有效性(RQ2): * 准确性:在15个测试漏洞中,RCLocator成功为其中的14个(93.3%)生成了根因谓词,并对崩溃原因提供了合理的解释。开发者实际修复的代码位置在RCLocator的输出结果中排名大多位于前10位。 * 效率:RCLocator完成一次根因分析的平均时间成本约为40分钟。相比之下,Aurora和VulnLoc仅数据增强阶段就需要120-720分钟和240分钟。综合来看,RCLocator将获得正确根因分析结果的概率提升了46.7%,并且分析速度提升了9.0倍。 3. 模块化有效性验证(RQ3):通过交叉实验,将RCLocator的数据增强方法与Aurora的特征提取方法结合,结果显示在大多数案例中,其分析结果优于原始的Aurora,验证了RCLocator数据增强方法(CIT过滤+字节突变)的优越性。同时,对比完全使用RCLocator流程的结果,也证明了其新设计的特征提取与排序方案的有效性。
研究团队还通过两个案例研究进一步阐述了RCLocator的价值。在CVE-2016-9264(libming全局缓冲区溢出) 中,RCLocator准确地定位到了未经边界检查的数组索引赋值语句,并给出了精确的语义解释(索引值大于等于3),与开发者的修复位置完全吻合。在CVE-2017-15232(libjpeg空指针解引用) 中,开发者仅在崩溃点附近添加了空指针检查,而RCLocator则追溯到了更早的根因位置——一个计算错误导致后续变量值异常,最终引发空指针传递。这揭示了RCLocator不仅能定位修复点,更能深入解释“为什么会发生崩溃”,提供了更深层次的洞察。
本研究的结论是,RCLocator通过引入崩溃信息元组(CIT)和基于字节突变的高效数据增强方法,有效解决了现有统计根因分析技术中的崩溃一致性和高时间成本两大核心问题。其新颖的特征提取与排序方案能够精确识别崩溃与非崩溃执行间的语义差异,并以谓词的形式为开发人员提供清晰易懂的根因解释。评估结果表明,RCLocator在保证高准确性的同时,实现了分析效率的显著飞跃,使其具备了在实际软件开发与安全响应流程中应用的巨大潜力。
本研究的亮点在于:1)创新性地提出了CIT概念及其实践工具CSan,为崩溃一致性验证提供了严格、可靠的标准;2)设计了一种不依赖传统模糊测试的高效数据增强方法,通过确定性(单字节突变)与随机性(多字节突变)结合,在极短时间内生成高质量数据集;3)构建了一个从预处理、数据增强、特征提取到结果排序的完整、高效的自动化根因分析流程,并在真实漏洞数据集上证明了其显著优于现有方法的综合性能(准确性+效率)。这些贡献为软件漏洞的快速诊断与修复提供了有力的自动化工具和新的技术思路。