Security Risks in Deep Learning Implementations论文笔记
原文地址:https://arxiv.org/abs/1711.11008
0 摘要
深度学习算法的进步掩盖了其在软件实现中的安全风险。本文公开了流行的深度学习框架(包括Caffe,TensorFlow和Torch)中的一组漏洞。与深度学习模型的较小代码体积相反,这些深度学习框架很复杂,并且依赖于大量的开源软件包。本文通过研究这些漏洞对常见的深度学习应用程序(如语音识别和图像分类)的影响,来考虑这些漏洞所带来的风险。通过利用这些框架的实现,攻击者可以发起击溃或挂起深度学习应用程序的”拒绝服务攻击”,或者发起导致系统受损或识别逃避的控制流劫持攻击。本文的目的是引起人们对软件实现的关注,并呼吁人们努力提高深度学习框架的安全性。
作者研究了三种流行的深度学习框架的实现:Caffe,TensorFlow和Torch,并根据与框架一起发布的示例应用程序收集了它们的软件依赖性。这些框架的实现非常复杂(通常需要成千上万行代码),并且通常建立在众多的第三方软件(例如图像和视频处理,科学计算库)上。
软件行业的一个共同挑战是,实现的复杂性经常会导致软件漏洞。深度学习框架也面临同样的挑战。通过检查,我们发现了许多实现的缺陷。其中,有15个被分配了CVE(Common Vulnerabilities and Exposures)编号。缺陷的类型包括软件缺陷的多种常见类型,例如堆溢出,整数溢出,use-after-free等。
作者对这些漏洞造成的威胁和风险进行了初步研究。在这些框架上构建了各种各样的深度学习应用程序之后,我们考虑了一系列攻击面,包括应用程序输入畸形,训练数据畸形和模型畸形。这些漏洞的潜在后果包括拒绝服务攻击,逃避分类,甚至破坏系统。本文简要概述了这些漏洞以及我们预期在这些框架之上构建的深度学习应用程序的潜在风险。
通过对三个深度学习框架的初步研究,本文有以下贡献:
1.揭示了流行的深度学习框架的依赖复杂性。
2.本文提出了针对深度学习应用的攻击面的初步研究。
(输入畸形,训练数据畸形,模型畸形)
3.我们证明了在这些框架的实现中存在多个漏洞。
4.我们还研究了这些漏洞的影响,并描述了基于这些易受攻击框架的应用程序的潜在安全风险。
1.揭示了流行的深度学习框架的依赖复杂性。
基于深度学习框架的app通常由三层软件组成:
顶层包含应用程序逻辑,深度学习模型和训练阶段得出的相应数据。这些是通常对开发人员可见的组件。
中间层是深度学习框架的实现,例如张量组件和各种过滤器。最上面两层之间的接口通常用实现中间层的编程语言来指定。例如,编程语言接口的选择分别包括C++,Python和Lua(分别对应Caffe,TensorFlow和Torch)。
底层是框架使用的构建模块。这些构建块是完成诸如视频和音频处理以及模型表示(例如protobuf)之类的任务的组件。构建模块的选择取决于框架的设计。例如,TensorFlow包含自己的视频和图像处理实现,这些实现基于librosa和numpy等第三方软件包构建,而Caffe选择直接使用开源库(例如OpenCV和Libjasper)来解析媒体输入。
虽然深度学习应用程序的开发人员通常看不见底层和中间层,但这些组件是深度学习应用程序必不可少的部分。
表一提供了深度学习框架实现的一些基本统计数据。在我们的研究中,我们分析的TensorFlow和Caffe的版本是1.2.1和1.0。该研究还包括Torch7。由于默认的Torch软件包仅支持有限的图像格式,因此我们选择研究结合了OpenCV的Torch7版本,该版本支持各种图像格式,例如bmp,gif和tiff。
我们通过两个指标(代码行数和软件依赖包的数量)来衡量深度学习框架的复杂性。我们使用Linux上的cloc工具计算代码行数。如表I所述,这些已实现的代码库都不小。Tensorflow有88.7万行代码,Torch有59万行代码,而Caffe有127K以上。此外,它们都依赖于众多的第三方包装。Caffe基于130多个依赖的库(由Linux ldd utility测量),Tensorflow和Torch分别依赖于97个Python模块和48个Lua模块,这些模块由import或require模块计算。
分层方法是软件工程的一种常见做法。分层不会直接引入缺陷,但是复杂性会增加漏洞的风险。框架或其构建组件中的任何缺陷都会影响在其上构建的应用程序。本文的下一部分介绍了一些实现缺陷的初步发现。
2.本文提出了针对深度学习应用的攻击面的初步研究
攻击面(attack surface),指软件环境中可以被未授权用户(攻击者)输入或提取数据而受到攻击的点位(攻击矢量),即应用程序可能受到怎样的攻击
这里以MNIST手写数字识别为例,来考虑深度学习应用程序的攻击面。可以从以下三个角度利用(exploit)像MNIST这样的图像识别应用程序
攻击面1——输入图像畸形:
许多当前的深度学习应用程序被训练后,通常就可以对输入数据进行分类和识别。对于从文件或网络读取输入的应用程序,攻击者可能会构造畸形的输入。这适用于MNIST图像识别应用程序,该应用程序从文件中读取输入。对于从传感器(例如直接连接的摄像机)获取输入的应用程序,攻击面明显减少。但是,在这种情况下,仍无法消除输入格式错误的风险,我们将在下一部分中进行讨论。
攻击面2——训练数据畸形:
图像识别应用程序会提取训练样本,如果训练数据来自外部来源,则样本可能被污染或标签错误。这通常称为数据中毒攻击。
投毒攻击不需要依靠软件漏洞。但是,实现中的缺陷会使投毒更容易(或更难检测)。例如,我们已经发现框架和常见桌面应用程序(例如图像查看器)中的图像解析过程存在不一致。这种不一致就会导致不被察觉的数据污染,不会引起管理训练过程的人的注意。
攻击面3——模型畸形:
如果开发人员使用他人开发的模型,则深度学习应用程序也可能受到攻击。尽管许多开发人员从头开始设计和构建模型,但是也有许多模型是供机器学习知识浅薄的开发人员使用。在这种情况下,这些模型是攻击者操纵应用的潜在来源。与投毒攻击类似,攻击者可以不利用任何漏洞,来威胁利用外部模型的应用程序。但是,实现缺陷(例如模型解析代码中的漏洞)可帮助攻击者隐藏畸形模型,并使威胁更加真实。个人理解:numpy中存在的bug会导致城市声音分类应用程序,在输入特制的声音文件时将死机。
3.证明了在这些框架的实现中存在多个漏洞
我们研究了几种深度学习框架,发现了许多实施缺陷。表II总结了这些缺陷的一部分,这些缺陷已分配CVE编号。这些实施缺陷使应用程序容易受到各种威胁的攻击。由于篇幅所限,这里我们仅介绍由输入畸形所引起的威胁,并假设应用程序从文件或网络中获取输入。
威胁1——DoS攻击:在深度学习框架中发现的最常见的漏洞是导致程序崩溃,进入无限循环或耗尽所有内存的软件错误。由此类错误引起的直接威胁是对在框架顶部运行的应用程序的拒绝服务攻击。下面的列表展示了对numpy python包中发现的错误补丁,该包是TensorFlow框架的构建模块。numpy包用于矩阵乘法和相关处理。TensorFlow上构建的应用程序经常使用它。特定的bug发生在pad()函数中,该函数包含while循环,该循环不会因开发人员未预期的输入而终止。由于从调用者传递空向量时,在循环条件下将变量safe-pad设置为负值,从而导致出现bug。由于存在此错误,我们证明了流行的示例TensorFlow应用程序(例如城市声音分类),在输入特制的声音文件时将死机。
威胁2——逃避攻击:当攻击者可以构建被深度学习应用误分类为错误类的输入时,就会发生逃避攻击。机器学习研究人员已经花费了大量的研究工作来通过对抗性学习方法来产生逃避输入。当面对脆弱的深度学习框架时,攻击者可以利用软件bug来达成逃避目标。我们在深度学习框架中发现了多个内存损坏bug,可能会导致应用程序生成错误的分类输出。攻击者可以通过两种方式利用这些bug来实现逃避攻击:
1)通过漏洞来覆盖分类结果,这些漏洞赋予攻击者修改特定内存内容的能力;
2)劫持应用程序控制流以跳过或重新排序模型执行。
下面的列表显示了越界写入漏洞和相应的补丁程序。可以在readData函数中将数据指针设置为任何值,然后可以将指定的数据写入数据所指向的地址。因此,它可能会覆盖分类结果。
威胁3——系统威胁:对于允许攻击者劫持控制流的软件bug,攻击者可能会利用软件错误并远程破坏托管深度学习应用程序的系统。当深度学习应用程序作为云服务运行以输入来自网络的数据时,就会发生这种情况。
下面的列表显示了OpenCV库中简单缓冲区溢出的补丁。OpenCV库是一个计算机视觉库,旨在提高计算效率,并特别关注实时应用程序。OpenCV支持深度学习框架,例如TensorFlow,Torch/PyTorch和Caffe。缓冲区溢出发生在grfmt_bmp.cpp的readHeader函数中。变量m_palatte表示大小为256*4字节的缓冲区,但是clrused的值来自输入图像,攻击者可以将其设置为任意值。因此,畸形的BMP图像可能会导致调用getBytes()时的缓冲区溢出。通过我们的调查,此漏洞提供了在任意内存写入的能力,并且我们已经成功地迫使样本程序(例如Caffe中的cpp_classification [2])根据我们精心制作的图像输入生成了一个远程shell。
4.研究了这些漏洞的影响,并描述了基于这些易受攻击框架的应用程序的潜在安全风险
A.封闭环境中应用程序的安全风险
许多示例深度学习应用程序被设计为在封闭环境中使用,在封闭环境中,应用程序直接从与应用程序紧密耦合的传感器获取输入。例如,在摄像头上运行的机器学习实现仅从内置摄像头传感器输出数据。在这种情况下,畸形输入的风险低于应用程序从网络或用户控制的文件获取输入的风险。但是,紧密耦合的传感器不能完全消除畸形输入的威胁。例如,存在与传感器完整性相关的风险,这些风险可能会受到损害。如果传感器与运行深度学习应用程序的云服务器进行通信,攻击者就可以逆转通信协议并直接攻击后端。
B.检测深度学习应用程序中的漏洞
我们应用了传统的bug发现方法(尤其是模糊测试fuzzing)来发现本文提出的软件漏洞。我们希望所有常规的静态和动态分析方法都适用于深度学习框架的实现。但是,我们发现coverage-based fuzzing tools并不是测试深度学习应用程序的理想选择,尤其是对于发现模型执行中的错误而言。以MNIST图像分类器为例,几乎所有图像都覆盖相同的执行路径,因为所有输入都经过相同的计算层。因此,coverage-based fuzzing tools将不容易发现诸如零除等简单错误,因为在这种情况下路径覆盖反馈的有效性较低
C.由于逻辑错误或数据操纵造成的安全风险
我们的初步工作重点是导致程序崩溃,控制流劫持或拒绝服务的“传统”软件漏洞。有趣的是,是否存在深度学习框架独有的bug类型,有什么方法可以检测出这些bug。躲避攻击或投毒攻击不必依靠常规软件漏洞(例如缓冲区溢出)。如果存在错误导致应用程序需要更多的数据进行训练和分类,那么就足以发起evasion(躲避)攻击了。
5.总结
这项工作的目的是提高对软件实现错误引起的安全威胁的认识。深度学习框架是复杂的软件,因此几乎不可避免地包含实现错误。本文概述了流行的深度学习框架中的实现bug和相应的风险。我们在流行的深度学习框架以及它们使用的库中发现了多个漏洞。潜在风险的类型包括拒绝服务,逃避检测和系统危害。尽管就输入控制而言,封闭式应用程序的风险较小,但它们并不能完全不受这些攻击的影响。考虑到深度学习应用程序的不透明特性在其训练数据中隐藏了隐式逻辑,因此可能难以检测到由实现缺陷引起的安全风险。作者希望本文的初步结果能够提醒研究人员不要忘记常规威胁,并积极寻找方法来检测深度学习应用程序的软件实现中的缺陷。