Large Language Model guided Protocol Fuzzing 论文翻译

大语言模型引导的协议模糊测试

摘要——如何在没有机器可读的协议规范的情况下找到协议实现中的安全漏洞?面对互联网,协议实现是特别关键的安全软件系统,其中输入必须遵循特定的结构和顺序,而这些通常在数百页的自然语言文档(RFC)中非正式地规定。如果没有这种协议的机器可读版本,就很难自动生成符合所需结构和顺序的有效测试输入。通过对一组记录的消息序列进行变异模糊测试,使用这些序列作为种子输入,部分可以缓解这一挑战。然而,可用的种子集通常非常有限,几乎无法涵盖协议状态和输入结构的多样性。

    在本文中,我们探讨了与预训练的大型语言模型(LLM)进行系统互动的机会,这些模型已经吸收了数百万页的人类可读协议规范,以提取可在协议模糊测试中使用的机器可读信息。我们利用LLM对已知协议消息类型的知识。我们还检查了LLM通过生成消息序列和预测响应代码来检测有状态协议实现中的“状态”的能力。基于这些观察,我们开发了一种LLM引导的协议实现模糊测试引擎。我们的协议模糊测试器CHATAFL为协议中的每种消息类型构建语法,然后通过与LLM的互动对消息进行变异或预测消息序列中的下一个消息。在对来自PROFUZZBENCH的广泛现实世界协议进行实验时,展示了在状态和代码覆盖率方面的显著效果。我们的LLM引导的有状态模糊测试器与最先进的模糊测试器AFLNET和NSFUZZ进行了比较。CHATAFL分别多覆盖了47.60%和42.69%的状态转换,29.55%和25.75%的状态,以及5.81%和6.74%的代码。除了增强的覆盖率外,CHATAFL还发现了九个在广泛使用和经过广泛测试的协议实现中以前未知的独特漏洞,而AFLNET和NSFUZZ分别只发现了三个和四个。

1 引言:

       开发一种用于协议实现的自动漏洞发现工具,从实践和研究的角度来看都特别有趣。

       从实践的角度来看,协议实现是每个直接或间接连接到互联网的软件系统中最暴露的组件。因此,协议实现构成了一个关键的攻击面,必须自动且持续地消除安全漏洞。在广泛使用的协议实现中,一个简单的任意代码执行漏洞就会使即使是最安全的软件系统也容易受到恶意远程攻击。

    从研究的角度来看,协议实现构成了难以测试的有状态系统。同样的输入执行两次可能每次会产生不同的输出。在特定协议状态中发现漏洞需要以正确的顺序发送正确的输入。例如,一些协议在交换其他类型的消息之前需要初始化或握手消息。为了使接收方正确解析该消息并进入下一个状态,消息必须遵循特定格式。然而,默认情况下,我们既不能假设知道这些消息的正确结构,也不能假设知道它们的正确顺序。

    基于变异的协议模糊测试通过对记录的消息序列进行模糊测试,减少了对所需消息结构或顺序的机器可读规范的依赖【36】【38】【7】【32】。简单的变异通常会保留所需的协议,同时仍然足以破坏消息序列以暴露错误。然而,基于变异的协议模糊测试器的有效性受到记录的种子消息序列的质量和多样性的限制,而现有的简单变异并不能有效覆盖丰富的输入或状态空间。

    为了促进协议在互联网参与者之间的采用,几乎所有流行、广泛使用的协议都在公开可用的文档中进行了规范,这些文档通常有数百页长,并且是用自然语言编写的。如果我们能够以编程方式查询我们正在测试的协议实现的自然语言规范呢?我们如何利用这样的机会来解决现有协议模糊测试方法的挑战?

    在本文中,我们探讨了利用大型语言模型(LLM)来引导协议模糊测试过程的实用性。通过从网站和互联网上的文档中获取许多TB的数据,LLM最近被证明能够准确回答任何主题的具体问题。像ChatGPT 4.0这样的LLM也吸收了自然语言的协议规范。LLM最近取得的巨大成功为我们提供了开发一个系统的机会,该系统将协议模糊测试器与LLM进行系统互动,模糊测试器可以向LLM发出非常具体的任务。

    我们称这种方法为LLM引导的协议模糊测试,并提出了三个具体的组件。首先,模糊测试器使用LLM提取用于结构感知变异的协议的机器可读语法。其次,模糊测试器使用LLM增加记录的消息序列中消息的多样性,这些序列被用作初始种子。最后,当覆盖率达到瓶颈时,模糊测试器使用LLM生成消息以达到新的状态,从而突破覆盖瓶颈。

    我们在PRO FUZZBENCH协议模糊测试基准【33】中的所有基于文本的协议上的结果展示了LLM引导方法的有效性:与我们的方法实现的基线(AFLNET【36】)相比,我们的工具CHATAFL覆盖了近50%的更多状态转换、30%的更多状态和6%的更多代码。CHATAFL在与最先进的NSFUZZ【38】相比时也表现出了类似的改进。在我们的消融研究中,从基线开始,我们发现启用(i)语法提取,(ii)种子丰富和(iii)饱和处理器依次使CHATAFL分别比基线在24小时内实现相同代码覆盖率的速度快2.0、4.6和6.1倍。CHATAFL在发现协议实现中的关键安全问题方面非常有效。在我们的实验中,CHATAFL在广泛使用和经过广泛测试的协议实现中发现了九个独特且以前未知的漏洞。

    总的来说,我们的论文有以下贡献:

  1. 我们构建了一个大型语言模型(LLM)引导的协议实现模糊测试引擎,以克服现有协议模糊测试器的挑战。为了更深入地覆盖这些协议的行为,需要进行即时状态推断——这是通过询问LLM(如ChatGPT)关于给定协议的状态机和输入结构来实现的。
  2. 我们提出了将LLM集成到基于变异的协议模糊测试器中的三种策略,每种策略都明确解决了协议模糊测试中发现的一个挑战。我们开发了一个扩展的灰盒模糊测试算法,并将其作为原型CHATAFL实现。该工具已公开,网址为GitHub - ChatAFLndss/ChatAFL: Large Language Model guided Protocol Fuzzing (NDSS'24)
  3. 我们进行了实验,证明我们的LLM引导的有状态模糊测试原型CHATAFL在协议状态空间和协议实现代码覆盖率方面比最先进的AFLNET和NSFUZZ更有效。除了增强覆盖率之外,CHATAFL还在广泛使用的协议实现中发现了九个以前未知的漏洞,其中大多数是AFLNET和NSFUZZ无法发现的。

2 背景和动机

    我们首先介绍协议模糊测试中的主要技术概念,并阐明我们在本文中要解决的关键开放挑战。接着,我们提供一些关于大型语言模型的背景信息以及我们的动机。

A.协议模糊测试:

    为了促进互联网信息的系统性和可靠交换,所有参与者都同意使用通用协议。许多最广泛使用的协议是由互联网工程任务组(IETF)设计并作为请求评论(RFC)发布的。这些RFC大多用自然语言编写,可能有数百页之长。例如,实时流协议(RTSP)1.0协议发布为RFC 2326,有92页长【1】。作为面向互联网的软件组件,协议实现具有安全关键性。协议实现中的安全漏洞经常被利用来实现远程代码执行(RCE)。

图1 (a)中的RTSP客户端请求结构,(b)中Live555的PLAY客户端请求结构

图2 RFC 2326中RTSP协议的状态机

RTSP(实时流协议)的状态机如图所示,描述了客户端和服务器之间的状态转换及其相关的请求方法。以下是对各个状态及其转换的详细解释:

1.INIT状态--初始状态:

  1. 在此状态下,可以发送 Describe、Options 和 Teardown 请求。
  2. Describe 请求用于描述媒体流。
  3. Options 请求用于查询服务器支持的功能。
  4. Teardown 请求用于终止会话。

2.READY状态:

  • 从 INIT 状态通过 Setup 或 Announce 请求可以进入 READY 状态。
  • Setup 请求用于初始化一个或多个媒体流。
  • Announce 请求用于在服务器上发布媒体描述。
  • 在 READY 状态下,可以发送 SetupOptionsSetParameterGetParameter 和 Teardown 请求。
  • SetParameter 和 GetParameter 请求用于设置和获取流参数。
  • 可以通过 Play 请求进入 PLAY 状态。
  • 通过 Record 请求可以进入 RECORD 状态。
  • 通过 Teardown 请求可以返回到 INIT 状态。

3.PLAY状态:

  • 在 READY 状态下发送 Play 请求可以进入 PLAY 状态。
  • 在 PLAY 状态下,可以发送 PlaySetupOptionsGetParameter 和 SetParameter 请求。
  • 通过 Pause 请求可以返回到 READY 状态。
  • 通过 Teardown 请求可以返回到 INIT 状态。

4.RECORD状态:

  • 在 READY 状态下发送 Record 请求可以进入 RECORD 状态。
  • 在 RECORD 状态下,可以发送 RecordSetupOptionsSetParameter 和 GetParameter 请求。
  • 通过 Pause 请求可以返回到 READY 状态。
  • 通过 Teardown 请求可以返回到 INIT 状态。

   

    协议规定了要交换的消息的一般结构和顺序。例如,实时流协议(RTSP)消息的结构示例如图1所示:除了指定消息类型(PLAY)、地址和协议版本的头部外,消息由键值对(key: value)组成,这些键值对由回车换行字符(CRLF;\r\n)分隔。RTSP消息的所需顺序如图2所示:从INIT状态开始,只有类型为SETUP或ANNOUNCE的消息才会导致新状态(READY)。要从INIT状态达到PLAY状态,至少需要两条特定类型和结构的消息。

    协议模糊测试器自动生成的消息序列理想情况下应该遵循协议的所需结构和顺序。我们可以区分两种类型的协议模糊测试器。生成器型协议模糊测试器【3】【25】【19】获得关于协议的机器可读信息,从头开始生成随机消息序列。然而,对于协议实现本身,手动编写生成器通常只覆盖协议规范的一小部分,其实现繁琐且容易出错【36】。

    基于变异的协议模糊器[36],[38]使用一组预录制的消息序列作为变异的种子输入。该记录确保消息结构和顺序是有效的,而变异模糊测试将轻微破坏这两个[36]。事实上,最近提出的所有协议模糊器,如AFLNET[36]和NSFUZZ[38],都采用了这种方法。

    挑战:然而,作为一种最先进的方法(SOTA),基于变异的协议模糊测试仍然面临以下挑战。

  1. (C1) 初始种子依赖性。基于变异的协议模糊测试器的有效性严重受到提供的初始种子输入的限制。预先录制的消息序列几乎无法覆盖协议规范中讨论的协议状态和输入结构的多样性。
  2. (C2) 未知的消息结构。缺乏关于消息结构的机器可读信息,模糊测试器无法对种子消息进行结构上有趣的更改,例如构造未见过类型的消息,或者删除、替换或添加完整、连贯的数据结构到种子消息中。
  3. (C3) 未知的状态空间。缺乏关于状态空间的机器可读信息,模糊测试器无法识别当前状态或被引导去探索以前未见过的状态。

B 大语言模型:

    新兴的预训练大型语言模型(LLMs)已经展示了在自然语言任务(如文本生成【11】【44】【15】和对话【43】【34】)上令人印象深刻的性能。LLMs在将自然语言规范和指令转换为可执行代码方面也被证明是有效的【20】【24】【14】。这些模型经过广泛的语料库训练,具备执行特定任务的能力,无需额外的训练或硬编码【12】。它们通过提供自然语言提示来调用和控制。LLMs理解任务的程度很大程度上取决于用户提供的提示。

    LLMs的能力对网络协议有着各种影响。网络协议根据以自然语言编写的RFCs实现,并在线提供。由于LLMs经过预训练,涵盖了数十亿的互联网样本,它们应该能够理解RFCs。此外,LLMs已经展示了强大的文本生成能力。考虑到消息以文本格式在服务器和客户端之间传输,为LLMs生成消息应该是简单的。LLMs的这些能力有潜力解决基于变异的协议模糊测试的开放挑战。此外,LLMs固有的自动化和易用性特征与模糊测试的设计理念完美契合。

    动机:在本文中,我们提议使用LLMs来引导协议模糊测试。为了减轻对初始种子(C1)的依赖,我们提议向LLM请求为给定的种子消息序列添加一个随机消息。但这是否真的增加了消息的多样性和有效性?为了应对消息结构未知(C2),我们提议向LLM请求提供每种消息类型的机器可读信息(即语法)。但这些语法与真实情况相比有多好,哪些消息类型被覆盖?为了找到未知的状态空间(C3),我们提议在模糊测试器与协议实现之间进行最近的消息交换后,向LLM请求返回一条会导致新状态的消息。但这是否真的有助于我们过渡到新状态?我们将在以下案例研究中仔细探讨这些问题。

3 案例研究:测试LLM在协议模糊测试中的能力

       在我们的研究中,我们选择了实时流媒体协议(RTSP)及其在PROFUZZBENCH中的实现LIVE5552。RTSP是一种应用层协议,用于控制具有实时特性的数据传输。LIVE555按照RFC 2326实现RTSP,作为娱乐和通信系统中的流媒体服务器来管理流媒体服务器。它包含在PROFUZZBENCH中,PROFUZZBENCH是一个广泛使用的网络协议有状态模糊测试基准。PROFUZZBENCH包括一套代表性的开源网络服务器用于流行协议,LIVE555就是其中之一。因此,对LIVE555的研究结果将是LLMs是否能有效指导协议模糊测试的有力指标。我们的研究在最先进的ChatGPT模型3中进行。在本节中,我们主要展示LLMs的能力。我们的方法及相应的提示将在第四节中更为详细地讨论。

A. 提升消息语法:质量与多样性

    我们要求LLM提供关于消息结构(即语法)的机器可读信息,并评估生成的语法的质量以及相对于真实语法的消息类型覆盖的多样性。为了建立真实语法,两位作者共花费8小时阅读RFC 2326,并手动且单独提取相应语法,最终达成完美一致。我们最终提取了10种特定于RTSP协议的客户端请求的真实语法,每种请求包含大约2到5个头字段。图3展示了PLAY消息语法,对应于图1所示的PLAY客户端请求语法。PLAY语法包括4个必需的头字段:CSeq、User-Agent、Session和Range。此外,某些请求类型有特定的头字段。例如,Transport字段特定于SETUP请求,Session字段适用于除SETUP和OPTIONS之外的所有请求类型,Range字段特定于PLAY、PAUSE和RECORD请求。

图3 RTSP PLAY客户端请求的语法

    为了获得LLM的语法进行分析,我们随机抽取了50个LLM针对RTSP协议的回答,并将它们合并成一个答案集。如图4所示,LLM为我们期望看到的全部十种消息类型生成了语法,在LLM的超过40个回答中都出现了这些类型。此外,LLM偶尔生成了2种随机类型的客户端请求,如“SET DESCRIPTION”;然而,每种随机类型在我们的答案集中只出现了一次。

图4 答案集中的客户端请求类型及每种类型的出现次数。

    此外,我们还检查了LLM生成的语法质量。在10种消息类型中,有9种类型的语法与从RFC中提取的真实语法完全一致。唯一的例外是PLAY客户端请求,LLM在某些回答中忽略了(可选的)“Range”字段。在对整个回答集中PLAY语法进行进一步检查后,我们发现LLM在35个回答中准确生成了包含“Range”字段的PLAY语法,但在15个回答中省略了该字段。这些发现表明了LLM生成高准确度消息语法的能力,这也激励我们利用语法来指导变异。

尽管存在一定的随机性,LLM 生成的所有类型的 RTSP 客户端请求结构的机器可读信息与真实数据一致。

B 丰富种子语料库:多样性与有效性

    我们要求LLM向给定的种子消息序列添加随机消息,并评估消息序列的多样性和有效性。在PROFUZZBENCH中,LIVE555的初始种子语料库仅包含真实情况中的10种客户端请求中的4种类型:DESCRIBE、SETUP、PLAY和TEARDOWN。缺少其余6种客户端请求类型使得RTSP状态机的大部分未被探索,如图2所示。虽然模糊器可能会生成这6种缺失的客户端请求类型,但其可能性相对较低。为验证这一观察结果,我们检查了由AFLNet和NSfuzz生成的种子,这些缺失的消息类型均未被生成。因此,增强初始种子至关重要。我们能否利用LLM生成客户端请求并增强初始种子语料库呢?

    LLM最理想的情况是不仅能生成准确的消息内容,还能将这些消息插入到客户端请求序列的适当位置。网络协议的服务器通常是状态响应系统,这一特性决定了客户端请求要被服务器接受,必须满足两个强制条件:(1)出现在适当的状态中,(2)消息内容准确无误。

    为了研究LLM的这一能力,我们要求它为每种客户端请求生成10条消息,共计100个客户端请求。随后,我们验证了这些客户端请求是否正确地放置在给定客户端请求序列的适当位置。为此,我们将其与图2所示的RTSP状态机进行比较,因为消息序列应基于状态机进行转换。确保一系列客户端请求根据状态机的规则是准确的后,我们将其发送到LIVE555服务器。通过检查服务器的响应码,我们可以确定消息内容是否准确,从而也对消息顺序进行了双重检查。

    我们的研究结果表明,LLM能够生成准确的消息并丰富初始种子。我们收集的客户端请求中,99%被正确地放置在相应的位置上。唯一的例外是,在“SETUP”客户端请求之后插入了一个“DESCRIBE”客户端请求。由于只有一个例外出现,我们认为LLM的性能是可以接受的。我们将客户端请求序列发送到LIVE555服务器,并在表I中显示了处理结果。大约55%的客户端请求能够直接被服务器接受,并返回成功的响应码“2xx”。然而,未成功的情况并非是LLM能力不足造成的。在未成功的集合中,20.4%的消息是因为LIVE555不支持“ANNOUNCE”和“RECORD”的功能,尽管这些功能包含在其RFC中。其余情况归因于“PLAY”、“TEARDOWN”、“GET PARAMETER”和“SET PARAMETER”请求中的会话ID不正确。会话ID由服务器动态分配,并包含在服务器的响应中。由于LLM缺乏这些上下文信息,因此无法生成正确的会话ID。然而,当我们用正确的会话ID替换时,所有这些消息都被服务器接受。

表1 客户端请求在被发送给服务器后处理的结果

    针对我们的方法,我们开发了两种方法来改进LLM在提供额外上下文信息时,以包含正确会话ID的能力。首先,我们在提示中包含了服务器的响应,然后请求LLM生成相同类型的消息。在这种情况下,生成的客户端请求直接被服务器接受。此外,我们尝试将会话ID包含在给定的客户端请求序列中,LLM也准确地将相同的值插入这些消息中,并产生了正确的结果。

C 诱导有趣的状态转换

    我们将模糊器和协议实现之间的消息交换提供给LLM,并要求其返回一个能导致新状态的消息。我们评估消息导致状态转换的可能性。具体来说,我们向LLM提供现有的通信历史,使服务器分别达到每个状态(即INIT、READY、PLAY和RECORD)。随后,我们查询LLM以确定下一个可能影响服务器状态的客户端请求。为了减少LLM随机行为的影响,我们对每个状态分别提示LLM 100次。

    图5显示了结果。每个饼图展示了每个状态的结果。每个饼图中的每个分段代表一个不同类型的客户端请求。灰色部分表示能够导致状态变化的客户端请求类型的百分比。橙色部分表示出现在适当状态但不触发任何状态转换的消息类型(因此没有状态变化)。蓝色部分表示出现在不适当状态且会直接被服务器拒绝的消息类型。从图5中可以看出,分别有81%、74%、89%和69%的客户端请求能够引发到不同状态的状态转换。此外,大约17%、16%、10%和30%的客户端请求尽管未触发状态变化,但仍然能够被服务器接受和处理。尽管这些消息未能覆盖更多的状态,它们仍然有潜力覆盖更多的代码分支。此外,在我们的案例研究中,还有一小部分不适当的消息,约占总量的2%、10%、1%和1%。这些结果表明,LLM具有推断协议状态的能力,尽管偶尔会出现错误。

图5 在每个状态下由LLM生成的下一种客户端请求类型。灰色的类型引发状态转换,橙色的类型出现在适当状态但不触发状态转换,蓝色的类型出现在不适当状态。每个分段代表一种不同的消息类型。

    此外,生成的客户端请求类型表现出多样性。LLM成功生成了涵盖每个单独状态的所有状态转换的客户端请求。此外,LLM还生成了2到5种适当类型的客户端请求。这些结果进一步展示了LLM引导模糊测试的潜力,使其能够超越覆盖瓶颈并探索广泛的状态转换。

在LLM生成的客户端请求中,有69%到89%引发了状态转换,涵盖了每个单独状态的所有状态转换。

4 LLM引导的协议模糊测试

    受到案例研究(第三节)中LLM展示的卓越能力的启发,我们开发了LLM引导的协议模糊测试(LLMPF),以解决现有基于变异的协议模糊测试(EMPF)的挑战。

    Algorithm 1概述了经典的EMPF方法的一般过程。输入包括测试中的协议服务器P0、相应的协议p、初始种子语料库C和总模糊测试时间T。输出包括最终的种子语料库C和导致服务器崩溃的种子C。在每个模糊测试迭代中(第7-34行),EMPF选择一个渐进状态s(第7行),并选择序列M(第8行)来执行s,以引导模糊器探索更大的空间。为了确保选择的状态s被执行,M被分为三个部分(第9行):M1,到达s的序列;M2,选择用于变异的部分;M3是剩余的子序列。随后,EMPF为M分配能量(第10行),确定变异次数,然后使用(结构不可知的)变异器将其变异为M'(第16行)。然后将这个变异序列发送到服务器(第23行)。EMPF保存导致崩溃的M'(第24-25行)或增加代码或状态覆盖的M'(第27-28行)。如果是后者,它更新状态机(第29行)。直到分配的能量用尽(第10行),选定下一个状态为止,整个过程重复进行。

    对于我们的LLMPF方法,我们通过加入灰色部分来增强EMPF的基线逻辑:(1) 提示LLM提取语法(第2行)并利用语法指导模糊变异(第12-14行)(第IV-A节);(2) 查询LLM以丰富初始种子(第3行)(第IV-B节);(3) 利用LLM的能力突破覆盖率平台(第4行,第19-21行,第26行,第30行和第32行)(第IV-C节)。现在我们将介绍每个组件。

A.基于语法的变异

    在本节中,我们将介绍从LLM中提取语法的方法,然后利用这些语法来指导结构感知变异。

    1)语法提取:在模糊测试工具要求LLM生成用于结构感知变异的语法之前,我们遇到了一个直接的挑战:如何为模糊测试工具获取机器可读的语法?模糊测试工具在单台机器上运行,并且只能解析预定的格式。不幸的是,LLM生成的响应通常是自然语言结构,具有相当的灵活性。如果模糊测试工具要理解LLM的响应,LLM应一致地以预定格式回答模糊测试工具的查询。另一种选择是手动将LLM的响应转换为所需的格式。然而,这种方法会削弱模糊测试工具的高度自动化特性,这是不理想的。因此,问题在于如何让LLM以所需格式回答问题。

    一种常见的解决方法是通过微调模型来实现特定任务的熟练度【27】。同样地,当涉及到LLM时,微调提示变得非常有必要。这是因为LLM可以通过简单地提供自然语言提示来执行特定任务,而无需额外的训练或硬编码。因此,模糊测试工具提示LLM生成待测试协议的消息语法。然而,提示微调的范围是广泛的。

    为了让LLM生成机器可读的语法,我们最终采用了领域内的提示工程中的上下文少样本学习【11】【42】。随着对LLM的深入理解,许多提示工程方法被提出【11】【45】【46】。上下文学习作为微调模型的有效方法,少样本学习通过提供一些所需输入和输出的示例来增强上下文。这使得LLM能够识别输入提示的语法和输出模式。通过上下文少样本学习,我们用一些示例提示LLM,以提取所需格式的协议语法。

    图6展示了用于提取RTSP语法的模型提示。在这个提示中,模糊测试工具提供了两个不同协议的语法示例,以所需格式展示。在这种格式中,我们保留了语法中的消息关键字,这些关键字被认为是不可变的,并用“〈Value〉”替换了可变区域。请注意,为了指导LLM正确生成语法,我们使用了两个示例,而不是依赖于单个示例。这有助于防止LLM严格遵循给定语法,从而可能忽略重要事实。

图6 用于提取RTSP语法的模型提示和响应响应的示例

    此外,我们的案例研究中还发现了另一个问题:LLM有时会生成随机的答案,如“SETDESCRIPTION”。幸运的是,这些情况很少见。为了应对少数样本生成的随机性,我们与LLM进行了多次对话,并将大多数一致的答案作为最终的语法。这种方法与提示工程领域的自一致性检查[45]类似,但在链式思考提示中并不存在。

    通过这些方法,模糊测试器能够有效地从LLM中获取各种协议的准确语法。图6所示的模型输出展示了从LLM中提取的一部分RTSP语法。在实践中,LLM有时对提示中的“全部”一词不敏感,导致它们仅生成部分语法类型。为了解决这个问题,我们只需再次提示LLM询问剩余的语法即可。

    在开始模糊测试活动之前(见概述中的算法1的第2行),我们的LLMPF方法与LLM进行对话以获取语法。随后,这些语法被保存到语法库G中,用于整个活动中的结构感知变异。这个设计旨在最小化与LLM交互的开销,同时确保最佳的模糊测试性能。接下来,我们详细说明了基于提取语法进行结构感知模糊测试的方法。

    2)基于语法的变异:使用从LLM中提取的语法库,LLMPF对种子消息序列进行结构感知变异。在之前的工作[23]中,研究人员利用LLM生成给定输入的变体,通过利用其理解输入语法的能力。然而,由于对话开销的限制,限制了与LLM交互的频率。在我们的方法中,我们采用了不同的策略。LLMPF利用提取的语法来指导变异。模糊测试器仅提取一次语法,使其能够在整个模糊测试活动中应用语法。在第四节C部分,我们将提供跳出覆盖率平台的机会。这里,我们继续介绍基于提取语法的变异工作流程。

    在算法1的第9行,模糊测试工具选择消息部分M2进行变异,作为算法设计的一部分。假设M2包含多个客户端请求,其中之一是RTSP协议的PLAY客户端请求。我们基于语法指导的变异方法如图7所示。它展示了变异单个RTSP PLAY客户端请求的工作流程。具体来说,当遇到PLAY客户端请求时,LLMPF首先将其与相应的语法进行匹配。为了加快匹配过程,我们将语法语料库维护为映射格式:G = {type → grammar}。其中,type表示客户端请求的类型。LLMPF使用每个语法的第一行作为消息类型的标签。语法对应于具体的消息语法。使用消息类型,LLMPF检索相应的语法。随后,我们使用正则表达式(Regex)将消息中的每个头字段与语法进行匹配,将“〈Value〉”下的区域标记为可变区域。在图7中,这些被识别出的可变区域用蓝色突出显示。在变异过程中,LLMPF只选择这些区域,确保消息保持有效格式。然而,如果没有找到语法匹配,我们将所有区域视为可变区域。

图7 使用RTSP协议的PLAY请求作为示例的基于语法变异的工作流程

    为了保留模糊测试工具探索一些边界情况的能力,我们继续采用经典EMPF中的结构无关变异方法,如算法1的第16行所示。然而,LLMPF更有可能进行结构感知变异,因为有效消息在探索更大状态空间方面具有更大的潜力。

B. 丰富初始种子

    受到LLM生成新消息并将其插入到提供的消息序列中适当位置的能力的启发(参见第III-B节),我们提出丰富用于模糊测试的初始种子语料库(算法1的第3行)。然而,我们的方法首先必须解决几个挑战:(i)如何生成带有正确上下文信息的新消息(例如,RTSP协议中的正确会话ID)?(ii)如何最大化生成序列的多样性?(iii)如何提示LLM从给定的种子消息序列生成整个修改后的消息序列?

    对于挑战 (i),我们发现LLM可以自动从提供的消息序列中学习所需的上下文信息。例如,在我们的实验中,PROFUZZBENCH已经拥有一些消息序列作为初始种子(尽管它们缺乏多样性)。PROFUZZBENCH的初始种子是通过捕获测试服务器和客户端之间的网络流量构建的。因此,这些初始种子包含了来自服务器的正确且充足的上下文信息。因此,在提示LLM时,我们包括来自PROFUZZBENCH的初始种子,以促进必要上下文信息的获取。

    对于挑战 (ii),模糊测试工具确定哪些类型的客户端请求在初始种子中缺失,即应由LLM生成哪些类型的消息以丰富初始种子。在第IV-A节中,我们已经获得了所有类型客户端请求的语法,因此识别初始种子中缺失的类型并不是一个难题。让我们重新审视图6中显示的语法提示。提示包括消息类型的名称(即PLAY和GET),相应地,消息名称也包含在模型输出中(例如,DESCRIBE和SETUP)。我们利用这些信息来维护一组消息类型:AllTypes = {messageType},以及一个从语法到相应类型的映射:G2T = {grammar → type}。

    在检测缺失的消息类型时,我们首先利用在第IV-A节中获得的语法语料库G和语法到类型的映射G2T来获取现有的消息类型,并将其维护到一个集合中(即ExistingTypes)。因此,缺失的消息类型在补集中:MissingTypes = (AllTypes - ExistingTypes)。然后我们指示LLM生成缺失类型的消息并将其插入到初始种子中;因此,我们的方法是基于现有初始种子但对其进行丰富。为了避免初始种子过长,我们在给定的消息序列中每次均匀选择并添加两种缺失类型。这样可以控制初始消息的长度和多样性。

对于挑战 (iii),为了确保生成的消息序列的有效性,我们将提示设计为连续格式(即“修改后的客户端请求序列是:”)。在实践中,获得的响应可以直接用作种子,除了移除开头的换行符(\n)或添加任何缺失的分隔符(\r\n)之外。图8展示了一个示例。在这种情况下,我们指示LLM将两种类型的消息“SET PARAMETER”和“TEARDOWN”插入到给定的序列中。修改后的序列如右图所示。

图8 丰富初始种子语料库的模型提示及响应示例(我们省略了消息的详细内容)

C. Surpassing Coverage Plateau  超过覆盖率瓶颈

    探索未见状态对状态感知模糊测试工具来说是一项挑战。为了更好地理解这一挑战,让我们回顾图2中展示的RTSP状态机。假设服务器在接受一系列客户端请求后当前处于READY状态。如果服务器希望转换到不同的状态(例如PLAY或RECORD状态),客户端必须发送相应的PLAY或RECORD请求。在模糊测试设计的背景下,模糊测试工具充当客户端。虽然模糊测试工具能够生成诱导状态转换的消息,但它需要探索大量种子。模糊测试工具很可能无法生成适当的消息顺序来覆盖所需的状态转换,因此大量代码空间仍未被探索。因此,探索额外的状态对于彻底测试状态感知服务器至关重要。不幸的是,现有的状态感知模糊测试工具在完成这项任务时面临挑战。

    在本文中,当模糊测试工具无法探索新覆盖时,我们称这种情况为模糊测试工具进入覆盖瓶颈(Coverage Plateau)。受到第III-C节研究结果的启发,我们利用LLM来帮助模糊测试工具超越覆盖瓶颈。这种情况发生在模糊测试工具在给定时间内无法生成有趣的种子时。我们根据模糊测试工具连续生成的无趣种子的数量来量化这一持续时间。具体来说,在整个模糊测试过程中,我们维护一个名为PlateauLen的全局变量,以跟踪到目前为止观察到的无趣种子的数量。在开始模糊测试之前,PlateauLen初始化为0(算法1的第4行)。在每次模糊测试迭代中,如果遇到一个导致程序崩溃的种子(第26行)或当覆盖增加时,PlateauLen会重置为0(第30行)。否则,如果种子被视为无趣,PlateauLen将增加1(第32行)。

    根据PlateauLen的值,我们判断模糊测试工具是否已进入覆盖瓶颈。如果PlateauLen没有超过MaxPlateau,即预定义的覆盖平 plateau的最大长度(第11行),我们的LLMPF将使用之前介绍的策略变异消息。MaxPlateau的值由用户指定并提供给模糊测试工具。然而,当PlateauLen超过MaxPlateau时,我们认为模糊测试工具已进入覆盖平 plateau。在这种情况下,LLMPF将利用LLM来克服覆盖瓶颈(第19至21行)。为此,我们使用LLM生成下一个合适的客户端请求,以诱导状态转换到其他状态。提示模板如图9所示。我们向LLM提供服务器和客户端之间的通信历史,即客户端请求及相应的服务器响应。为了确保LLM生成真实的消息,而非消息类型或描述,我们通过从初始种子语料库中提取任何消息来展示所需的格式。随后,LLM推断当前状态并生成下一个客户端请求M2′。该请求作为原始M2的变异,被插入到消息序列M′中,然后发送给服务器。

图9 获取下一个能够诱导服务器状态转换到其他状态的客户端请求的提示模板。

    让我们重新考虑RTSP的例子。最初,服务器处于INIT状态。收到消息序列M1 = {SETUP}后,它响应R1 = {200-OK},并转换到READY状态。随后,模糊测试工具遇到了覆盖瓶颈,无法生成有趣的种子。在注意到这一点后,我们通过提供通信历史H = {SETUP, 200-OK}来刺激LLM。作为回应,LLM很可能会回复一个PLAY或RECORD消息,正如第III-C节的研究结果所示。这些消息将导致服务器转换到不同的状态,从而克服覆盖瓶颈。

D.实行:

    我们将这种基于LLM的协议模糊测试(参见算法1)实现到了AFLNET中,称为CHATAFL,以测试用C/C++编写的协议。AFLNET是最流行的基于变异的开源协议模糊测试工具之一。它维护一个推断的状态机,并使用状态和代码反馈来指导模糊测试活动。当前状态的识别涉及解析服务器响应消息中的响应代码。如果一个种子能够增加状态或代码覆盖率,则被视为有趣。CHATAFL继续使用这种方法,同时将前面提到的三种策略无缝集成到AFLNET框架中。

5实验设计

    为了评估大型语言模型(LLMs)在应对基于变异的文本网络协议模糊测试挑战中的实用性,我们希望回答以下问题:

  1. RQ.1 状态覆盖。CHATAFL相比基线实现了多少更多的状态覆盖?
  2. RQ.2 代码覆盖。CHATAFL相比基线实现了多少更多的代码覆盖?
  3. RQ.3 消融实验。CHATAFL的每个组件对性能的影响是什么?
  4. RQ.4 新漏洞。CHATAFL在发现广泛使用和经过广泛测试的协议实现中的未知漏洞方面是否有效?

    为了回答这些问题,我们遵循模糊测试实验的推荐实验设计[26],[10]。

A. 参数配置

    为了决定饱和度,我们将覆盖瓶颈的最大长度(MaxPlateau)设置为512个不增加覆盖率的消息序列。这个值是通过启发式筛选方法确定的。在初步实验中,我们发现512是一个合理的MaxPlateau设置,约在10分钟内实现。将该值设置得过小会导致CHATAFL过于频繁地查询LLM,而设置得过大则会使CHATAFL停滞过长,无法从我们的优化中受益(参见第IV-C节)。一旦达到覆盖瓶颈,CHATAFL会提示LLM生成超越覆盖瓶颈的消息序列(第IV-C节)。为了限制LLM提示的成本,我们将无效提示的最大数量设置为MaxPlateau的四分之一。

    作为大型语言模型(LLM),我们使用了gpt-3.5 turbo模型。根据建议,为了获得准确和事实性的响应,我们使用了0.5的温度来提取语法并丰富初始种子(参见第IV-A节和第IV-B节)。为了生成新消息,J. Qiang等人[23]发现,对于灰盒模糊测试,1.5的温度是最优的。因此,我们将温度设置为1.5以突破覆盖瓶颈(参见第IV-C节)。在提取语法时,为了进行自一致性检查[45],我们使用了五次重复。正如我们在案例研究中确认的(参见第III-A节),我们发现五次重复足以过滤掉不正确的情况。

B、基准和基线

    表II展示了用于评估的被测程序。我们的基准测试包括六种基于文本的网络协议实现,其中包括五种广泛使用的网络协议(即RTSP、FTP、SIP、SMTP和DAAP)。这些被测程序涵盖了PROFUZZBENCH中的所有基于文本的网络协议,PROFUZZBENCH是用于评估状态感知协议模糊测试工具的广泛使用的基准测试【36】【32】【38】【41】。这些协议涵盖了广泛的应用,包括流媒体、消息传递和文件传输。它们的实现是成熟的,并且被企业和个人用户广泛使用。我们为每种协议选择了在实际应用中广泛使用和适用的实现。这些项目中的安全漏洞可能会产生广泛的影响。

表2 关于我们主题项目的详细信息。

    作为基线工具,我们选择了AFLNET和NSFUZZ-v。由于我们的工具CHATAFL已被实现到AFLNET中,因此CHATAFL和AFLNET之间的每一个观察到的差异都可以归因于我们实现LLM指导所做的更改。AFLNET【36】是一个流行的开源、最先进的、基于变异的、代码和状态指导的协议模糊测试工具。NSFUZZ-v【38】扩展了AFLNET,以更好地掌握协议状态空间。它通过静态分析识别状态变量,并使用状态变量值作为模糊测试工具的反馈,以最大化状态空间的覆盖率。其基本思想与大约同时发布但实现于LibFuzzer【31】中的SGFUZZ【7】非常相似。SGFUZZ也使用状态变量值的序列来隐式捕捉协议状态空间的覆盖率。其他协议模糊测试工具,如STATEAFL【32】和BooFuzz【25】,以前曾与AFLNET或NSFUZZ-v进行了(不利的)比较,即我们作为基线使用的工具。

C. 变量和测量方法

    为了评估CHATAFL相对于基线模糊测试工具的有效性,我们测量了协议模糊测试工具在协议的状态空间和协议实现代码的覆盖情况。关键思想是,如果协议模糊测试工具不能覆盖某些代码或状态,它就不能在这些地方发现漏洞。然而,覆盖率仅是模糊测试工具发现漏洞能力的一个代理测量【26】【10】。因此,我们将覆盖率结果与漏洞发现结果结合起来进行评估。

    覆盖率:我们报告了代码和状态空间的覆盖情况。为了评估代码覆盖率,我们使用基准测试平台PROFUZZBENCH提供的自动化工具来测量达到的分支覆盖率【33】。为了评估状态空间的覆盖率,我们使用基准测试平台提供的自动化工具来测量(i)不同状态的数量(状态覆盖率)和这些状态之间的转换数量(转换覆盖率)。与AFLNET和PROFUZZBENCH的作者一样,在缺乏测试协议的真实状态机的情况下,我们将消息序列遍历的不同状态定义为服务器返回的唯一响应代码的集合。为了减轻随机性的影响,我们报告了10次重复24小时测试中达到的平均覆盖率。

    漏洞:为了识别漏洞,我们在Address Sanitizer (ASAN)下执行被测试的程序。CHATAFL存储导致崩溃的消息序列,然后我们使用AFLNET提供的重放工具来重现崩溃并调试其根本原因。我们通过分析ASAN报告的堆栈跟踪来区分不同的漏洞。最后,我们将这些漏洞报告给相应的开发者以确认。

D.实验设备

    所有实验都在配备Intel(R) Xeon(R) Platinum 8468V CPU的机器上进行。该机器具有192个逻辑核心,运行频率为2.70GHz。操作系统为Ubuntu 20.04.2 LTS,主内存为512GB。

6 实验结果

RQ1 状态空间覆盖率

    状态变换:表III显示了我们的工具CHATAFL与两个基线工具AFLNET和NSFUZZ-v在状态转换覆盖率方面的平均数量。为了量化CHATAFL相对于基线工具的改进,我们报告了以下指标:

  1. 24小时内转换覆盖率的百分比改进(Improv)。
  2. CHATAFL达到基线工具相同转换覆盖率所需时间的加速比(Speedup)。
  3. CHATAFL随机实验比基线工具随机实验表现更好的概率(A12, Vargha-Delaney效应量度量【5】)。

这些指标帮助我们评估CHATAFL在状态转换覆盖率方面的性能改进,并量化其相对于现有基线工具的优势。

    与两个基线工具相比,CHATAFL实现了更多的状态转换,并显著加快了状态探索过程。平均而言,CHATAFL比AFLNET多执行了48%的状态转换。具体来说,在LIVE555测试中,CHATAFL比AFLNET增加了91%的状态转换次数。此外,CHATAFL平均比AFLNET快48倍达到相同数量的状态转换。与NSFUZZ相比,CHATAFL平均多覆盖了43%的状态转换,并且达到相同状态转换数量的速度是NSFUZZ的16倍。对于所有测试项目,Vargha-Delaney效应量 A12≥0.86 表明CHATAFL在探索状态转换方面相对于AFLNET和NSFUZZ具有显著优势。

表3 在10次24小时运行中,我们的CHATAFL与基准AFLNET和NSFUZZ的平均状态转换次数。

    状态:表IV显示了我们的工具CHATAFL与两个基准AFLNET和NSFUZZ-v覆盖的平均状态数量及其相应的百分比提升。显然,CHATAFL优于AFLNET和NSFUZZ。具体而言,CHATAFL分别比AFLNET多覆盖了30%的状态,比NSFUZZ多覆盖了26%的状态。为了将覆盖的状态数放在可达状态总数的背景中,表IV的最后一列显示了在任何一次10次24小时运行中,由任何一个工具覆盖的状态总数。我们可以看到,CHATAFL的平均模糊测试活动几乎覆盖了所有可达状态。例如,在LIVE555的情况下,CHATAFL平均覆盖14.2个状态(共15个状态),而AFLNET和NSFUZZ分别仅覆盖10个状态和11.7个状态。仅在Kamailio的情况下,CHATAFL覆盖的可达状态空间比例较小(平均17个,最大23个状态中的20个)。尽管如此,CHATAFL在状态覆盖方面仍然优于基准工具。

表4 CHATAFL相比AFLNET和NSFUZZ的平均状态数及其提升情况。

在状态覆盖方面,CHATAFL平均比AFLNET和NSFUZZ分别多覆盖了48%和43%的状态转换。与基准相比,CHATAFL覆盖相同数量的状态转换速度分别快48倍和16倍。此外,CHATAFL还探索了比AFLNET和NSFUZZ大得多的可达状态空间比例。

RQ2代码覆盖率

    表V显示了CHATAFL和基准AFLNET及NSFUZZ在10次24小时模糊测试中达到的平均分支覆盖率。为了量化CHATAFL相对于基准工具的改进,我们报告了24小时内分支覆盖率的百分比改进(改进),CHATAFL在24小时内达到与基准相同分支覆盖率的速度提升(加速),以及CHATAFL的随机测试活动优于基准随机测试活动的概率(A12)。

表5 在10次24小时运行中,我们的CHATAFL与基准AFLNET和NSFUZZ所覆盖的平均分支数量。

    正如我们所见,对于所有测试对象,CHATAFL覆盖的分支数量都超过了两个基准工具。具体而言,CHATAFL比AFLNET多覆盖了5.8%的分支,范围在2.4%到8.0%之间。与NSFUZZ相比,CHATAFL多覆盖了6.7%的分支。此外,CHATAFL覆盖相同数量分支的速度比AFLNET快6倍,比NSFUZZ快10倍。对于所有测试对象,Vargha-Delaney效应大小A12≥0.70,表明CHATAFL在代码覆盖率方面相较两个基准工具具有显著优势。

在代码覆盖率方面,CHATAFL平均比AFLNET多覆盖5.8%的分支,比NSFUZZ多覆盖6.7%。此外,CHATAFL达到相同数量的分支所需的时间比AFLNET快6倍,比NSFUZZ快10倍。

RQ3 消融研究

    CHATAFL实施了三种策略与大型语言模型(LLM)互动,以克服协议模糊测试的挑战:

  1. SA) 语法引导的变异
  2. SB) 丰富初始种子
  3. SC) 超越覆盖瓶颈

    为了评估每种策略对覆盖率提升的贡献,我们进行了消融研究。为此,我们开发了四个工具:

  1. CL0:AFLNET,所有策略都被禁用
  2. CL1:AFLNET plus,语法引导的变异(SA)
  3. CL2:AFLNET plus,语法引导的变异和丰富初始化种子(SB)
  4. CL3:AFLNET plus 包含所有策略(SA+SB+SC),CL3是CHATAFL

    表VI以类似于之前使用的格式显示了分支覆盖率的结果(改进、加速和A12)。然而,与之前的表格相比,改进、加速和A12效应大小的结果呈现为相反的方向。例如,对于ProFTPD,配置CL3(即CHATAFL)比基准配置CL0(即AFLNET)多实现了8%的分支覆盖率。两个相邻配置之间的改进差异(括号中显示)量化了所启用策略的效果。例如,对于ProFTPD,配置CL2仅实现了5.3%的改进,比CL3少了2.7个百分点(pp),这表明了从CL2到CL3启用的策略SC的有效性。

    总体而言,所有策略都有助于提高分支覆盖率,且没有任何策略对分支覆盖率产生负面影响。具体而言,CL1相比CL0实现了平均3.04%的分支覆盖率提升。CL2展现了平均3.9%的提升,而CL3则显示出最高的平均5.9%提升。此外,CL1实现相同的分支覆盖率速度比CL0快2倍,CL2快5倍,CL3则快6倍。因此,启用所有三种策略被证明是最有效的做法。

    策略SA。我们评估了策略SA(即基于语法的变异)的影响。在ProFTPD、PureFTPD、Exim和forked-daapd中,CL1提高了2.4%到6.7%的分支覆盖率。然而,在剩下的两个测试对象Live555和Kamailio中,尽管CL1也改善了分支覆盖率,但仅分别增加了0.28%和0.60%。经过对这两个对象实现的调查,我们发现它们的实现并不严格遵循消息语法。缺失或错误的头字段的消息仍然可以被其服务器接受。

    策略SB。与仅启用策略SA的CL1相比,我们观察到了策略SB的贡献。启用该策略后,平均覆盖的分支数增加了0.82%。策略SB在Live555、ProFTPD和Kamailio中显著提高了分支覆盖率,增幅在1.21%到1.64%之间,而在其他三个测试对象中,仅提高了约0.03%到0.26%。对于后面三个测试对象,PROFUZZBENCH几乎包含了所有类型的客户端请求,然而增加种子多样性的机会不多。

    策略SC。将CL3与CL2进行比较时,我们可以看到启用策略SC显著提高了分支覆盖率,增幅在0.69%到4.78%之间。具体而言,在ProFTPD和Kamailio中,策略SC分别帮助提高了2.72%和4.78%的分支覆盖率。

总体而言,每种策略对分支覆盖率的提升都有不同程度的贡献。依次启用策略SA、SB和SC,使我们实现相同的分支覆盖率的速度分别快2.0倍、4.6倍和6.1倍。

RQ4 发现新Bug

    在本实验中,我们评估了CHATAFL的实用性,检查它是否能够发现我们的测试程序中的零日漏洞。为此,我们在最新版本的测试对象上使用了CHATAFL,进行了10次24小时的重复测试。在实验过程中,CHATAFL产生了令人满意的结果,如表VII所示。

表7 CHATAFL在广泛使用且经过充分测试的协议对象中发现的9个零日漏洞的统计数据。

    尽管AFLNET和NSFUZZ进行了广泛测试,CHATAFL仍发现了9个独特且以前未知的漏洞。这些漏洞存在于测试的六个实现中的三个中,涵盖了各种类型的内存漏洞,包括使用后释放、缓冲区溢出和内存泄漏。此外,这些漏洞具有潜在的安全隐患,可能导致远程代码执行或内存泄漏。我们已将这些漏洞报告给相应的开发人员。在这9个漏洞中,已有7个被开发人员确认,并且已有3个在论文提交时已被修复。我们已为确认的漏洞请求了CVE ID。

    我们使用AFLNET和NSFUZZ来检测这9个漏洞。AFLNET和NSFUZZ都配置了相同的版本,并运行了与CHATAFL相同的时间(即10次24小时重复测试)。然而,AFLNET仅能发现其中的三个漏洞(即漏洞#5、#6和#9),NSFUZZ则能发现四个漏洞(即漏洞#5、#6、#7和#9)。此外,AFLNET和NSFUZZ没有发现任何其他漏洞。

    为了了解LLM指导的贡献,我们对漏洞#1进行了更详细的调查,这是一个堆使用后释放漏洞。当特定轨道的使用环境的已分配内存在处理PAUSE客户端请求期间被释放时,该漏洞就会发生。随后,在接收到PLAY客户端请求时,这段内存被覆盖,导致堆使用后释放问题。

    为了触发这个漏洞,需要涉及几种类型的客户端请求:SETUP、PLAY和PAUSE。然而,之前的工作中使用的初始种子中并未包含PAUSE客户端请求。虽然模糊测试工具理论上可以生成这样的客户端请求,但实际上可能性不大。我们检查了在实验中由AFLNET和NSFUZZ生成的所有种子,发现它们在任何运行中都没有生成PAUSE客户端请求。然而,CHATAFL在初始种子丰富过程中提示LLM添加了PAUSE客户端请求(参见第IV-B节)。

    一旦所需的客户端请求可用,触发此漏洞就需要向服务器发送特定的消息,以覆盖特定的状态和状态转换。具体来说,这些消息应覆盖图2所示的三个状态:INIT、READY和PLAY。此外,还需要覆盖几个状态转换:INIT → READY、READY → PLAY、PLAY → READY,然后再次READY → PLAY。模糊测试工具本身有可能通过多样化的种子覆盖这些状态和状态转换。此外,LLM可以为模糊测试工具提供指导,以便覆盖这些状态。例如,在PLAY状态期间,LLM可以生成下一个客户端请求PAUSE,以执行PLAY → READY转换(参见第IV-C节)。

    最后,我们不应忽视结构感知变异的贡献。要触发此漏洞,需要一个最小的消息序列:SETUP → PLAY → PAUSE → PLAY。省略任何一个消息都会使漏洞无法触发。现有的基于变异的模糊测试工具,由于其不具备结构感知的变异方法,很可能会破坏消息结构,使其无效。相比之下,通过利用从LLM派生的语法,结构感知变异可以有效地保持消息的有效性。

CHATAFL发现了9个不同的、以前未知的漏洞,而AFLNET和NSFUZZ分别只发现了其中的3个和4个漏洞。AFLNET和NSFUZZ也没有发现其他额外的漏洞。这9个漏洞中有7个(7/9)可能具有安全关键性。

手动工作的实验

    在使用CHATAFL的过程中,运行表II中显示的所有协议的实验都不需要手动干预。具体来说,当从LLM提取语法时,我们使用了图6中所示的提示。在协议测试期间,仅更改指令部分的协议名称(例如,RTSP)。在所需格式下,Shot-1和Shot-2作为示例,LLM打印语法,以给定的机器可读结构,使CHATAFL能够解析打印的语法。我们花费了一个小时来获取这些示例,但这种设置只需一次性完成;后续对其他协议的测试不需要额外的手动干预。利用从LLM获得的语法,结构感知变异是完全自动化的(参见第IV-A节)。

    为了丰富初始种子,我们使用了图8中的提示模板。在使用CHATAFL进行协议测试时,整个提示是从这个模板自动生成的。协议名称和现有的消息序列会自动粘贴到该模板中。此外,生成的消息类型名称来自图6中的模型输出。在请求LLM的帮助以克服覆盖瓶颈时,我们使用图9中的模板生成完整的提示。因此,使用CHATAFL不需要任何手动工作。

    CHATAFL旨在测试基于文本的协议,这些协议有公开的RFC可供参考。大多数协议的规范都记录在这些公开的RFC中,这些RFC也被包含为LLM的训练数据。然而,对于某些专有协议,其RFC未包含在LLM的训练数据中,CHATAFL在测试这些协议时可能无法发挥最佳性能。

7 相关工作

    基于语法的模糊测试:生成型模糊测试根据手动构建的规范从头生成消息【29】, 【19】, 【3】, 【25】, 【1】, 【8】。这些规范通常包括数据模型和状态模型。数据模型描述消息语法,而状态模型指定服务器和客户端之间的消息顺序。然而,构建这些规范可能是一项繁琐的任务,需要大量的人工努力。相比之下,大型语言模型(LLMs)在数十亿份文档上进行了预训练,具备广泛的协议规范知识。在CHATAFL中,我们直接利用LLMs获取规范信息,从而消除了额外的人工工作需求。

    动态消息推断:为了减少模糊测试前对先验知识和手动工作的依赖,已有几项工作提出了动态推断消息结构的方法,包括黑盒模糊测试【22】、【35】和白盒模糊测试【13】、【16】、【30】。例如,黑盒模糊测试工具TREEFUZZ【35】利用机器学习技术对种子语料库进行处理,以构建概率模型,随后用于输入生成。而白盒模糊测试工具,如POLYGLOT【13】,则通过对被测系统进行动态分析(如符号执行和污点跟踪)来提取消息结构。然而,这些方法只能基于观察到的消息推断消息结构。因此,推断的结构可能会与实际的消息结构有显著偏差。

    动态状态推断:基于变异的模糊测试是协议实现模糊测试中的主要类别之一。基于变异的模糊测试工具【47】、【9】、【37】、【31】、【21】、【40】、【4】通过随机变异从种子输入语料库中选出的现有种子生成新输入,并利用覆盖信息系统地演变这个语料库。在分支覆盖反馈的指导下,它们在模糊测试无状态程序方面被证明是有效的。然而,在模糊测试有状态程序时,单靠分支覆盖是一个有用但不足够的指导模糊测试活动的指标,如现有研究【6】所述。因此,状态覆盖反馈被用来与分支覆盖一起指导模糊测试活动。然而,识别状态是一个显著的挑战。一系列工作【7】、【36】、【32】、【38】提出了各种状态表示方案。AFLNET【36】利用响应码作为状态,在模糊测试活动期间构建状态机,并将其用作状态覆盖指导。STATEAFL【32】、SGFUZZ【7】和NSFUZZ【38】则基于程序变量提出了不同的状态表示方案。在本文中,我们并不试图回答什么是状态。相反,我们将这一任务委托给LLM,让它来推断状态。事实证明,这种方法是有效的。

    基于大型语言模型的模糊测试:继预训练大型语言模型(LLMs)在各种自然语言处理任务中取得显著成功后,研究人员开始探索其在不同领域的潜力,包括模糊测试。例如,CODAMOSA【28】是第一个将LLMs应用于模糊测试(即自动生成Python模块的测试用例)的项目。随后,TITANFUZZ【17】和FUZZGPT【18】专门使用LLM自动生成深度学习软件库的测试用例。这些工作采取了生成型的模糊测试方法,而CHATFUZZ【23】则采取了变异的方法,通过请求LLM修改人工编写的测试用例。Ackerman等人【2】利用格式规范的模糊性,使用LLM递归检查自然语言格式规范以生成实例,作为变异模糊测试器的强种子示例。与这些技术不同,CHATAFL将信息提取与模糊测试分离开来。CHATAFL首先从LLM中以机器可读格式(即通过语法和状态机)提取输入结构和顺序的信息,然后运行一个高效的模糊测试器,该模糊测试器利用这些信息。为了提高效率,CHATAFL仅在模糊测试期间覆盖饱和时才使用LLM进行变异(类似于CHATFUZZ)。

8 总结

    协议模糊测试本质上是一个非常困难的问题。与文件处理应用程序相比,文件处理应用程序的输入是给定的文件,而协议通常是涉及系统与环境之间持续交互的反应性系统。这带来了两个相关但独立的挑战:一是为了探索导致崩溃的不常见的深层行为,我们可能需要生成复杂的有效事件序列;二是由于协议是有状态的,这还隐含着在模糊测试过程中动态推断状态(因为并非所有操作在每个状态下都是启用的)。此外,模糊测试的有效性在很大程度上依赖于初始种子的质量,这些种子作为模糊测试生成的基础。

    在本研究中,我们证明了对于具有公开RFC的协议,LLMs在丰富初始种子、实现结构感知变异以及辅助状态推断方面是有效的。我们在广泛使用的PROFUZZBENCH套件中的各种协议上评估了CHATAFL。结果非常令人鼓舞:CHATAFL在显著减少时间的情况下,覆盖了更多代码并探索了更大的状态空间,与基准工具相比具有明显优势。此外,CHATAFL发现了9个零日漏洞,而基准工具仅发现了3到4个。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值