dtls-fuzzer 是一个Java工具,用于对DTLS服务器执行协议状态模糊测试。具体而言,它支持以下功能:
dtls-fuzzer 使用 [TLS-Attacker][tlsattacker] 来生成/解析DTLS消息以及维护状态。
为此,TLS-Attacker 已扩展了对DTLS的支持。
dtls-fuzzer 依赖于 [版本 3.0b][tlsattackerver] 的 TLS-Attacker,该版本实现了DTLS增强功能。
该制品包含:
dtls-fuzzer 根目录中最重要的文件夹有:
'experiments/results' 包含实验结果,这是工作的主要输出。具体而言
输出文件夹根据实验配置命名,即:
例如,文件夹名称 'jsse-12_rsa_cert_none_rwalk_incl' 表示对JSSE 12 DTLS实现进行的实验,使用的字母表包含用于执行RSA握手的输入,客户端证书认证被禁用,测试算法为随机游走,且包含重传。
一个输出文件夹包含:
评估者可以检查(例如)'included' 中的实验结果是否与表4中显示的一致,或者表2中测试的配置是否也出现在 'all_ciphers' 中。 请注意,论文中出现的模型经过了大量修剪/精简,而输出文件夹中出现的模型是未经修改的。
为了评估 dtls-fuzzer,需要执行以下步骤:
本评估部分之后是一份关于使用 dtls-fuzzer 的指南,介绍其主要用例。
dtls-fuzzer 已在 Ubuntu 18.04 和 Debian 9 Linux 发行版上测试过。 它应该能在任何最新的Linux发行版上工作。 对其他平台的支持尚未测试。 本指南假设使用的是基于Debian的发行版(具有 'apt-get')。
需要Java 8 JDK(Java开发工具包)虚拟机(VM)。 运行实验使用的版本是1.8.0_222,但后续的Java 8版本也应该可以工作。 请注意,该工具无法在Java 9或更高版本上构建。 我们还依赖maven('mvn' 工具)进行依赖管理/部署。
我们建议使用性能足够强大的机器,否则敏感的时序参数(如响应等待时间)可能变得过低,导致与论文中不同的输出。 更糟糕的是,它们可能导致学习实验失败。 原始实验是在一个多核服务器上运行的,但预计(尽管未进行充分测试)在配备i7处理器的桌面上也应该能够进行学习。 如果在较弱的系统上进行学习,需要相应地调整时序参数。 最后,通过将 .dot 模型导出为 .pdf 进行可视化需要安装 [graphviz库][graphviz]。 假设 graphviz 提供的 'dot' 工具位于系统PATH中。
简而言之,建议的先决条件包括:
dtls-fuzzer 需要Java 8 JDK(Java开发工具包)。 如果未安装Java,我们安装OpenJDK实现(在Ubuntu上通过 'apt-get'),并可以跳过本小节的其余部分。
> sudo apt-get install openjdk-8-jdk
如果已安装Java,可以通过运行以下命令检查其版本:
> java -version
版本代码应以1.8开头(例如1.8.0_242),并且虚拟机应为 "Server VM"(表示安装了完整的JDK,而不仅仅是运行时环境)。 如果是这样,Java部分就完成了。 如果不是,可以检查是否已安装Java 8 JDK但当前未选择,通过列出已安装的Java VM:
> update-java-alternatives --list
如果Java 8 JDK确实出现,可以使用相同的命令将Java 8 JDK配置为默认Java实现。
> sudo update-java-alternatives --set java-1.8.0-openjdk-amd64
否则,需要像开头所示那样执行完整安装。 不幸的是,'update-java-alternatives' 有时不成功,表现为 "error" 消息。 如果出现这种情况,可以使用 'update-alternatives' 以交互方式配置由 'java'(解释器)和 'javac'(编译器)选择的Java VM。
> sudo update-alternatives --config java
> sudo update-alternatives --config javac
设置好Java 8后,我们继续安装其他依赖项:maven、graphviz以及一些常见的SUT依赖项。 然后我们将 dtls-fuzzer 的仓库克隆到所选文件夹,切换到制品分支。 最后,将该文件夹设为当前目录。
> sudo apt-get install maven graphviz autotools-dev automake libtool
> git clone -b usenix20-artifact https://github.com/assist-project/dtls-fuzzer.git ~/dtls-fuzzer
> cd ~/dtls-fuzzer
我们首先运行 'prepare.sh' 脚本,该脚本安装 dtls-fuzzer 依赖的库,即两个本地 .jar 文件和 TLS-Attacker 3.0b。 然后我们安装工具本身。 在POSIX系统上,生成的命令如下:
> bash prepare.sh
> mvn clean install
完成这些步骤后,应该构建了一个名为 'target' 的目录,其中包含 'dtls-fuzzer.jar'。 这是我们的可执行库。 从现在开始,假设所有命令都是从 dtls-fuzzer 的根目录运行的。
假设我们想仅使用PSK(预共享密钥)为OpenSSL 1.1.1b生成一个模型。 dtls-fuzzer 的快速运行如下。
首先,我们设置SUT,这由 'setup_sut.sh' 脚本自动完成。
> bash setup_sut.sh openssl-1.1.1b
然后,我们从 'args/openssl-1.1.1b' 文件夹中选择一个参数文件。 我们注意到有几个参数文件可供选择,即:
learn_openssl-1.1.1b_all_cert_none_rwalk_incl
learn_openssl-1.1.1b_all_cert_nreq_rwalk_incl
learn_openssl-1.1.1b_all_cert_req_rwalk_incl
learn_openssl-1.1.1b_psk_rwalk_incl
感兴趣的是参数文件 'learn_openssl-1.1.1b_psk_rwalk_incl',因为其文件名表明是PSK。 因此我们选择它,并在其上运行模糊测试器。 我们额外将测试数量上限设为200,以缩短学习时间。 最后,对于OpenSSL,需要将 LD_LIBRARY_PATH 设置为实现的目录('suts/openssl-1.1.1b/')。 在运行学习之前,我们可能希望执行一个简单测试来检查设置是否正常。 一个好的测试就是完成一次握手。 我们提供参数文件以及来自 'examples/tests' 的相应测试作为参数。 得到:
> LD_LIBRARY_PATH=suts/openssl-1.1.1b/ java -jar target/dtls-fuzzer.jar @args/openssl-1.1.1b/learn_openssl-1.1.1b_psk_rwalk_incl -test examples/tests/psk
如果一切顺利,服务器应输出 "This is a hello message",这是在完成握手后发送的消息。 知道设置正常后,我们现在可以通过运行以下命令开始学习:
> LD_LIBRARY_PATH=suts/openssl-1.1.1b/ java -jar target/dtls-fuzzer.jar @args/openssl-1.1.1b/learn_openssl-1.1.1b_psk_rwalk_incl -queries 200
我们注意到已为实验创建了一个输出目录 'output/openssl-1.1.1b_psk_rwalk_incl/'。 我们可以 'ls' 这个目录来检查实验的当前状态(生成的假设数量等)。
> ls output/openssl-1.1.1b_psk_rwalk_incl/
如果一切顺利,20-30分钟后,输出目录应包含一个 'learnedModel.dot' 文件。 我们可以使用 graphviz 的 'dot' 工具将该文件可视化,通过导出为 .pdf 并用喜欢的 .pdf 查看器打开。
> dot -Tpdf output/openssl-1.1.1b_psk_rwalk_incl/learnedModel.dot > output/openssl-1.1.1b_psk_rwalk_incl/learnedModel.pdf
> evince output/openssl-1.1.1b_psk_rwalk_incl/learnedModel.pdf
最后,我们可以使用 'trim_model.sh' 生成一个更好/更精简的模型版本。 可以按如下方式操作:
> bash trim_model.sh --output output/openssl-1.1.1b_psk_rwalk_incl/nicerLearnedModel.dot output/openssl-1.1.1b_psk_rwalk_incl/learnedModel.dot
> dot -Tpdf output/openssl-1.1.1b_psk_rwalk_incl/nicerLearnedModel.dot > output/openssl-1.1.1b_psk_rwalk_incl/nicerLearnedModel.pdf
> evince output/openssl-1.1.1b_psk_rwalk_incl/nicerLearnedModel.pdf
我们现在可以通过对照规范检查模型来确定系统的一致性...
当 'ls' 输出目录时,我们可能会发现 'error.msg'。 这表明实验失败,学习突然终止。 在这种情况下,显示其内容可以揭示失败的原因
> cat output/openssl-1.1.1b_psk_rwalk_incl/error.msg
请注意,仍然可以对最后生成的假设进行一致性检查,只要潜在发现是针对系统验证过的(无论如何都应该这样做)。
我们提供了一个设置SUT的脚本。 该脚本下载源文件,安装一些依赖项(jvm)并构建SUT。 要查看提供自动设置的SUT,运行:
> bash setup_sut.sh
例如,要设置Contiki-NG的tinydtls实现,运行:
> bash setup_sut.sh ctinydtls
该脚本将在 dtls-fuzzer 的根目录中生成两个文件夹。
不幸的是,自动化SUT设置是一个复杂的过程,因此我们采取以下捷径。 对于Java SUT(JSSE、Scandium),我们不构建实现,而是使用来自 'experiments/suts' 目录的已编译 .jar 文件。 请注意,这些Java SUT(服务器应用程序)的源代码可在线公开获取,请参见 [Scandium][scandium] 和 [JSSE][jsse],[PionDTLS][piondtls] 也是如此。 自动安装依赖项可能会提示 'sudo' 权限。 对于依赖外部库(如nettle)的GnuTLS和依赖autoconf的Eclipse TinyDTLS,会发生这种情况。 最后,由于NSS和PionDTLS的设置非常复杂,我们不提供自动设置/参数文件。
如果设置过程中的某些步骤停止工作,删除 'suts' 文件夹(或特定于SUT的 'suts/SUT' 文件夹)并重新运行设置脚本可能会解决问题。 另外,如果构建失败,实现的源代码仍应已下载到 'suts' 目录。 一种解决方法是手动构建实现。 只要实现构建成功,我们的设置就应该能工作。
以下我们给出各个SUT所依赖的不完整依赖树。 斜体的是 'setup_sut.sh' 尝试使用 'sudo' 权限安装的依赖项。
我们现在准备学习一个SUT配置。 在 dtls-fuzzer 主目录的 'args' 目录中提供了各种SUT配置的参数文件。 每个参数文件名描述了实验设置(SUT、字母表、认证),如 'experiments/results/' 中输出文件夹名称所描述的那样。 要使用参数文件开始学习某个SUT,运行:
> java -jar target/dtls-fuzzer.jar @args/sut_name/arg_file
输出文件夹将存储在生成的 'output' 目录中。