神经网络修复安全漏洞的效果如何

互联不一般哥 2024-06-10 16:42:36

How effective are neural networks for fixing security vulnerabilities

Yi Wu1, Nan Jiang1, Hung Viet Pham2, Thibaud Lutellier3, Jordan Davis1, Lin Tan1, Petr Babkin4, Sameena Shah4

1Purdue University West Lafayette, USA

2York University Toronto, Canada

3University of Alberta Camrose, Canada

4J.P. Morgan AI Research New York, USA

引用

Wu Y, Jiang N, Pham H V, et al. How effective are neural networks for fixing security vulnerabilities[C]//Proceedings of the 32nd ACM SIGSOFT International Symposium on Software Testing and Analysis. 2023: 1282-1294.

论文:https://dl.acm.org/doi/pdf/10.1145/3597926.3598135

摘要

安全漏洞修复是一项艰巨并且迫切需要自动化的任务。已有两组技术表明:(1)大型代码语言模型(LLM)已经在源代码上进行了预训练,用于完成代码等任务;(2)自动程序修复(APR)技术使用深度学习(DL)模型自动修复软件错误。本文通过实验,首次研究并比较LLM和基于DL的APR模型的Java漏洞修复能力。

1 引言

软件漏洞,如缓冲区溢出和SQL注入,对全球经济产生重大影响,可能会危害数百万用户。一旦发现漏洞,及时修复通常至关重要。最近研究发现,修复漏洞的平均时间(发现与修复之间的时间)在60到79天之间,过长的时间为攻击者提供充足的机会。例如,严重的Apache Log4Shell漏洞于2021年11月24日报告,Apache在报告后12天部署第一个修复。在这12天内,Cloudflare和Cisco都报告了利用该漏洞的多次攻击。大多数漏洞基准和漏洞修复解决方案专注于C/C++或二进制文件。尽管Java是一种广泛使用的编程语言(在开源社区中排名第三),但缺乏针对Java的解决方案和基准,尽管它有许多严重的漏洞。

Java已被用于实现重要的服务器,包括Web服务器和服务(例如Tomcat、Spring、CFX、Log4J),这些服务器特别容易受到攻击。例如,Google评估称,Log4J包中的Log4Shell漏洞影响17,000个Maven项目,甚至被国家级攻击者利用。其他编程语言的基准和解决方案通常对于修复Java漏洞要么无法工作,要么效果不佳。例如,C/C++中最常见的漏洞是缓冲区溢出。作为一种类型安全的语言,Java旨在避免缓冲区溢出。因此,大多数针对缓冲区溢出漏洞的C/C++技术对Java无关。我们需要针对修复Java安全漏洞的新基准和技术。

本文研究并比较应用两种类型的技术——基于学习的自动程序修复和LLMs——自动修复Java安全漏洞的空间和可行性。首先,基于学习的程序修复已经变得流行。这些编码器-解码器方法从大量的bug和它们的修复(在开源项目中)中学习,以自动修复未见的Java软件bug。研究这样的学习型程序修复模型在修复软件漏洞子集方面的有效性将是有趣的。LLMs最近应用于源代码,预训练模型从GitHub等大量源代码学习,与APR模型不同,LLMs不以bug及其修复对为学习对象,而是用于标识符标记和代码完成等任务。尽管任务不同,研究显示,LLMs在修复一般的Java漏洞方面具有竞争能力。探究LLMs在未了解修复方法的情况下,对软件漏洞修复的效果将是有趣的。第三,比较基于DL的APR技术和LLMs修复Java漏洞的能力是有趣的。DL-based APR和LLMs代表不同的模型应用角度。DL-based APR利用通用数据集学习修复特定软件漏洞,而LLMs则利用代码序列学习修复漏洞,不需要bug和修复对。由于LLMs不需特定对照数据,其建模数据通常比APR模型多几个数量级。研究表明,LLMs可能因数据量或数据格式匹配而胜出,进一步调查对网络安全至关重要。最后,LLMs通常微调以适应不同任务,最近研究表明微调可提升修复能力至少31%。但由于缺乏Java漏洞数据,为修复Java漏洞微调LLMs不现实。因此,研究基于一般APR数据微调LLMs在修复软件漏洞方面的效果将很有意义。与DL-based APR技术相比,更多数据加微调是否更优,或者数据格式匹配更胜一筹?

本论文做出了以下贡献:

进行首次研究,评估五种LLMs、四种微调LLMs和四种APR技术在两个真实世界的Java漏洞基准(Vul4J和我们的新VJBench)上的修复能力。

- 现有的LLMs和APR技术只修复极少数Java漏洞。Codex的平均修复率为10.2(20.4%),表现出最佳的修复能力。

- 使用一般APR数据进行微调可以提高LLMs的漏洞修复能力。微调后的InCoder修复了9个漏洞,表现出与Codex相竞争的修复能力。

- Codex的编译率最高,为79.7%。其他LLMs(无论是否微调)和APR技术的编译率较低(CodeT5最低,为6.4%,其余在24.5%到65.2%之间),显示缺乏语法领域知识。

- 除Codex之外,LLMs和APR模型只修复需简单更改的漏洞。

- 新VJBench揭示LLMs和APR模型无法修复许多CWE类型,包括CWE-172编码错误、CWE-325缺少加密步骤、CWE-444 HTTP请求走私、CWE-668资源暴露给错误的领域以及CWE-1295调试消息泄露不必要的信息。

我们为自动程序修复创建了两个Java漏洞基准:(1)VJBench,其中包含42个可再现的真实世界Java漏洞,涵盖了12种新的CWE类型;(2)VJBench-trans,其中包含150个转换后的Java漏洞。使用代码转换来减轻LLMs和黑盒Codex可能见过的基准的威胁。

- 评估LLMs和APR技术在转换后的漏洞(VJBench-trans)上的修复能力。

- 代码转换使LLMs和APR技术修复的漏洞数量减少。一些模型,如Codex和微调后的CodeT5,对代码转换更具鲁棒性。另一方面,一些转换使漏洞更容易修复。

我们提供了未来方向的启示和建议。

2 技术介绍

图1概述了本文研究。首先构建了一个包含42个新漏洞的新数据集VJBench。本研究使用这个新数据集和原始数据集(Vul4J)来评估基于DL的APR技术、LLMs和微调LLMs的漏洞修复能力。每个语言模型通过推理为每个漏洞生成10个补丁。对于每个APR模型,使用其默认的beam搜索大小,并验证其前10个补丁。生成的补丁然后通过测试用例进行验证,并手动验证所有通过测试用例的补丁。然后在Vul4J和VJBench上应用代码转换以生成VJBench-trans。最后,评估代码转换对所有LLMs、微调LLMs和APR技术的漏洞修复能力的影响。

图1:研究概述

本文进行第一项研究,评估和比较自动程序修复(APR)技术和LLMs修复Java漏洞的能力。共评估五种LLMs(Codex、CodeT5、CodeGen、PLBART和InCoder)以及四种使用一般APR数据进行微调的LLMs,以及四种APR技术(CURE、Recoder、RewardRepair和KNOD),并在两个Java漏洞基准(Vul4J和创建的新VJBench)上进行评估。本文主要面临两个主要挑战。

(1) 用于评估Java漏洞修复工具的基准很少。尽管Vul4J包含了79个可再现的Java漏洞,但仅属于25种漏洞类型(CWE)。此外,数据集中60%的CWE(15种漏洞类型)仅涵盖一个可再现的漏洞。为解决这一挑战,本研究开发了新的基准。分析了整个国家漏洞数据库(NVD),以识别适合进行漏洞修复评估的可再现的真实世界Java漏洞,并使用这些创建了VJBench基准。这些漏洞涵盖Vul4J数据集未包含的12种CWE类型,还向Vul4J中仅关联一个漏洞的四种CWE类型添加了更多漏洞。新基准可以促进未来Java漏洞修复技术的评估。

(2) Codex是在收集自GitHub的大量代码语料库上进行训练的,而训练数据集尚未公开。由于Vul4J和VJBench中的项目是GitHub上的公共存储库,无法确定Vul4J和VJBench中的漏洞是否不在Codex的训练数据中。这是对评估有效性的主要已知威胁。虽然数据集HumanEval不在Codex的训练数据中,但它用于Python代码完成,不包含Java漏洞。本文尽最大努力解决这一挑战,通过转换现有基准中的漏洞代码。使用两种类型的代码转换:标识符重命名和代码结构更改。这些转换生成新的等效程序,仍保留漏洞,但不包含Codex和其他LLMs可能见过的任何开源数据集中。因此,通过在Vul4J和VJBench中的漏洞上应用两种转换策略,创建了VJBench-trans,一个转换漏洞的基准。

3 实验评估

3.1 实验设置

评估数据集。本研究专注于修复单一代码块的Java漏洞,如最先进的基于DL的APR模型设计等用于修复单一代码块的错误。本文从Vul4J数据集中筛选并获取了35个单一代码块的漏洞,加上来自VJBench的15个单一代码块漏洞,总共有50个Java漏洞。然后本文对这些Java漏洞使用完美的故障定位,即使用开发人员补丁中修改的代码行作为有缺陷的代码行。

大型语言模型设置。本文使用两种输入设置评估每个LLM:(1)有缺陷的代码行被注释为输入的一部分,和(2)没有有缺陷的代码行。当输入包含有缺陷的代码行注释时,InCoder修复了更多的漏洞,而其他LLMs在没有有缺陷的代码行时表现更好。然后,本文其余部分报告每个模型的最佳配置。对于微调LLMs,使用的带有有缺陷的代码行注释的输入格式,遵循了表1中的格式描述。

表1:大型语言模型的输入格式

配置为:每个模型每个漏洞生成10个补丁。对于CodeT5、CodeGen、PLBART和InCoder,将它们的beam搜索大小设置为10。Codex将其参数n,即要生成的候选数,设置为10。考虑到Codex采用的采样方法的固有随机性,对每个漏洞运行25次,以获得平均结果。运行25次以控制误差边界小(≤0.3),置信水平为95%。Codex的采样温度设置为0.6,这在先前的工作中已经证明对于采样十个候选者时性能最佳。由于Codex的请求速率限制,本研究将新生成的令牌的最大数量设置为400,对于所有其他LLMs,将其设置为512。

修补程序验证。Codex插入模式生成要插入到前缀提示和后缀提示之间的代码。由于使用有缺陷的代码行注释之前和包括之后的代码作为前缀提示,将Codex生成的代码替换原有的有缺陷的代码。类似地,CodeT5生成要替换其输入中的掩码标签的代码。PLBART生成替换整个有缺陷函数的整个修复函数。CodeGen和InCoder是完成模型,生成要完成给定前缀提示的代码。采用CodeGen和InCoder生成的第一个完整函数来替换原有的有缺陷函数。对于所有微调LLMs,微调后的CodeT5、CodeGen、PLBART和InCoder直接生成要替换有缺陷代码的修复代码。对于每个LLM和APR技术,首先使用项目的测试用例验证它们生成的前10个补丁。根据先前的工作,合理的补丁是通过所有测试用例的补丁,而正确的补丁在语义上等同于开发人员的补丁,过度拟合的补丁是通过所有测试用例但不正确的补丁。手动检查每个合理的补丁,以确定它是否是正确的补丁。

RQ1 漏洞修复功能

实验设计。本研究对Codex运行了二十五次,并报告了修复漏洞的平均数量和误差范围,因为Codex的补丁生成是非确定性的。对于其他LLMs,只运行它们一次,因为它们的补丁生成是确定性的。

结果。表2显示了五种LLMs、四种微调LLMs和四种APR模型的修复能力,即每种方法正确修复的漏洞数量。我们考虑了前十个补丁,因为最近的研究表明,几乎所有开发人员最多只愿意检查十个补丁。表4中的结果报告为X/Y,其中X是每种技术正确修复的漏洞数量,Y是可能修复的漏洞数量。如果模型生成了一个合理的补丁(在第5.3节中定义),则该漏洞可能被模型合理修复。

表2:修复Java漏洞的LLM和APR模型的比较。对于单元格中的x/y,x表示正确修复的bug数量,y是合理修复的bug(至少有一个补丁通过了测试用例)。RewardR是RewardRepair。

LLMs vs. APR技术:实验结果也与最近的研究一致,在显示未经微调的LLMs具有竞争力的修复能力方面。InCoder修复了比最佳APR技术(RewardRepair)多三个漏洞。然而,虽然最近的研究表明CodeGen、PLBART和InCoder原样可以修复Java APR基准测试中18%-23%的一般错误,但本文结果显示它们只能修复Vul4J和VJBench中的4%(2/50)-10%(5/50)的漏洞。在实际应用中,只有大约1~7%的错误是漏洞,导致模型学习的数据很少。现有的大型语言模型和APR技术修复的Java漏洞很少。Codex平均修复了10.2(20.4%)个漏洞,表现出最佳的修复能力。

用APR数据微调的LLMs:表2显示,所有经过微调的LLMs修复的漏洞数量都超过了它们原始模型。具体而言,微调后的InCoder修复了9个漏洞,比其原始模型多4个。第二好的模型是微调后的CodeGen,修复了8个漏洞,比其原始模型多6个。微调后的CodeT5和微调后的PLBART各自修复了3个和2个额外的漏洞。用一般APR数据进行微调提高了所有四种LLMs的漏洞修复能力。微调后的InCoder修复了9个漏洞,表现出与Codex相竞争的修复能力。

本文还评估了编译率(即生成的补丁中能够编译的部分),以研究补丁的质量。总体而言,Codex这个最佳模型的编译率为79.7%,远高于最佳微调LLM(微调后的InCoder,55.2%)和最佳APR模型(Recoder,57.6%)的编译率。微调明显提高了CodeT5和CodeGen的编译率,分别从6.4%提高到46.8%和从35.8%提高到47.2%。另一方面,微调后的PLBART的编译率为45.2%,略低于原始PLBART的47.8%。尽管InCoder的编译率为65.2%,比其微调模型高,但它生成了82.0%的重复补丁,而微调后的InCoder生成的补丁具有更多种类的修改,导致更多的正确修复。总的来说,与修复一般错误的编译率相比,修复漏洞的编译率较低。PLBART、CodeGen和InCoder在修复一般错误时,不经微调的编译率平均为65%–73%,表现优于它们在修复漏洞时的原始和微调模型。

图2:Vul4J-12和VulJ-1的开发人员补丁和不可编译的补丁

图2a展示了Vul4J-12的无法编译的补丁示例:函数签名声明t为final,因此不允许更改t的值。然而,Codex未能捕获这个约束,即使函数签名仅在有缺陷的行上方两行。结果,它生成了代码t--来减少t的值,这使得补丁无法编译。类似地,RewardR忽略了v和vt都是int类型的事实,并在它们上调用无效的equals函数。图2b展示了Vul4J-1的另一个无法编译的补丁示例:parseArray是项目中另一个类中定义的一个方法,只接受两个或三个参数。所有四个微调LLMs都生成了相同的无法编译的补丁,它们将null作为第四个参数传递,因为它们没有parseArray不接受四个参数的信息。

RQ2 LLMS和基于学习的APR技术修复哪些类型的漏洞?

结果。表3显示了LLMs、微调LLMs和APR技术正确修复的漏洞。总共有16个漏洞(属于十个CWE类别,如列CWE中所示,其描述在列Description中),来自两个基准测试的漏洞至少被其中一个模型修复。这些漏洞的ID列在Vul下。某些漏洞不属于特定的CWE类别,被列为未知。

表3:详细描述了每个LLM、未调优的LLM和基于的APR技术所造成的漏洞

Vul4J-47是只有Codex能够修复的漏洞。图3a显示Vul4J-47的开发者补丁,属于CWE-611(不正确的XML外部实体引用限制)和CWE-918(服务器端请求伪造)类型的漏洞。正确的修复需要插入一条语句xmlIn.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE)来禁用文档类型定义(DTD)的支持,因为DTD可以用于执行服务器端请求伪造(SSRF)攻击。原始有缺陷的代码只通过将IS_SUPPORTING_EXTERNAL_ENTITIES属性设置为false来禁用对外部实体的支持,这不足以防止攻击。图3b显示微调后的CodeGen生成的不正确补丁,它将Boolean.FALSE替换为Boolean.TRUE。总的来说,除了Codex,其他LLMs和微调LLMs只修复需要简单修改的漏洞,比如删除语句或替换变量/方法名。

图3:Java漏洞Vul4J-47及其补丁

图4显示了属于CWE-611类别的Retrofit-1。没有模型修复Retrofit-1。正确的补丁是通过调用xmlInputFactory.setProperty(...)来防止XML外部实体攻击,禁用对外部实体和DTD的支持。但是,由于LLMs没有提供漏洞是关于XML外部实体攻击的信息(如CWE类型所建议的),它们只对与XML属性无关的有缺陷的代码进行更改(图4b)。图5显示了属于CWE-325(缺少加密步骤)类别的Jenkins-1,这是VJBench添加的一个新的CWE类别。该漏洞的正确修复是在for循环之前添加if条件来检查权限,以限制对NodeMonitor的访问。如图5中Codex的补丁所示,所有模型都无法修复该漏洞,因为它们只对for循环应用一般的修改,并且不知道该漏洞与权限限制相关。此外,hasPermission方法和CONNECT变量在有缺陷的函数外声明,因此模型不知道它们的使用情况。

图4:Java漏洞Retrofit-1及其补丁。

图5:Java漏洞Jenkins-1及其补丁

这反映了LLMs修复Java漏洞的两个问题:(1)只提供有缺陷的代码行,LLMs无法生成针对漏洞的补丁。这表明有必要向LLMs提供有关漏洞的更多信息,如CWE类型。(2)LLMs需要更多的项目特定信息来修复漏洞,即提供有关在有缺陷函数外声明的相关方法和变量的信息。

RQ3 转换后的漏洞修复能力

实验设计。为了减轻训练测试数据重叠的威胁,我们对基准进行了代码转换,以研究Codex和LLMs在未见数据上的泛化能力。表4显示了LLMs(原样或微调过的)、微调LLMs和APR技术在四种设置下修复漏洞的数量:(1)无转换——原始漏洞数据集,(2)仅重命名——只应用标识符重命名,(3)仅更改代码结构——只应用代码结构更改,以及(4)重命名+代码结构更改——应用了两种转换。

表4:代码转换对LLM模型和APR模型的漏洞修复能力的影响。对于Codex,x ± y: x表示正确发送的bug的平均数量,y表示误差范围(95% condence)

总的来说,代码转换使LLMs(无论是否微调)和APR技术修复的漏洞数量减少。例如,微调过的InCoder在Vul4J和VJBench中修复了九个漏洞(无转换),但仅在四个完全转换的漏洞(重命名+代码结构更改)中修复。某些模型受转换的影响较小,例如Codex和微调过的CodeT5,表明这些模型对代码转换具有稳健性和泛化学习能力。这个结果在一定程度上解决了Codex的非公开训练数据的威胁,并揭示Codex强大的学习和漏洞修复能力。许多模型在没有转换的情况下只修复两个或更少的漏洞,因此转换对这些模型的影响不大。然而,几乎所有模型都存在一个普遍趋势,即这些代码转换使模型修复的漏洞数量减少。

图6:转换前后的Halo-1

图6a展示了一个例子,Halo-1,其正确修复方法是在pathToCheck上调用normalize()来移除文件路径中的任何冗余元素。这个漏洞可以由Codex、微调后的CodeGen和微调后的InCoder正确修复。然而,在应用了两种转换之后,只有Codex能够修复它(图6b)。代码转换使大型语言模型和APR技术修复的漏洞数量减少。一些模型,如Codex和微调过的CodeT5,对代码转换更具鲁棒性。另一方面,一些转换使漏洞更容易修复。

转述:石孟雨

0 阅读:0

互联不一般哥

简介:感谢大家的关注