导语:本文讨论了我们的项目,该项目涉及在OPC UA协议的实现中搜索漏洞。希望这篇文章能够帮助软件供应商实现对现代网络攻击的更高级别的保护。
本文讨论了我们的项目,该项目涉及在OPC UA协议的实现中搜索漏洞。在发布这些材料时,我们希望引起开发用于工业自动化系统和工业物联网软件的供应商的注意,以解决与使用这种广泛可用技术相关的问题,这些技术结果相当普遍。我们希望这篇文章能够帮助软件供应商实现对现代网络攻击的更高级别的保护。我们还讨论了一些技术和发现,这些技术和发现可能有助于软件供应商控制其产品的质量,也可能对其他软件安全研究人员有用。
为什么选择OPC UA协议用于研究
IEC 62541 OPC统一架构(OPC UA)标准由OPC基金会联盟于2006年开发,用于可靠和重要的工业网络中不同系统之间的数据安全传输。该标准是其前身-OPC协议的改进版本,在现代工业环境中无处不在。
基于不同供应商产品的监控系统通常使用互不兼容的,通常是专有的网络通信协议。OPC网关或服务器用作不同工业控制系统与遥测,监控和遥控系统之间的接口,统一工业企业的控制流程。
该协议的以前版本基于Microsoft DCOM技术,并具有该技术固有的一些重大限制。为了摆脱DCOM技术的限制并解决使用OPC时发现的一些其他问题,OPC基金会开发并发布了新版本的协议。
由于其新特性和设计良好的架构,OPC UA协议在自动化系统供应商中迅速普及。OPC UA网关由遍布全球的越来越多的工业企业安装。该协议越来越多地用于建立工业物联网组件与智能城市系统之间的通信。
卡巴斯基实验室ICS CERT最重要的研究领域之一是许多自动化系统开发人员所使用的技术的安全性,并有可能在全球各地的工业设施中无处不在。这是我们对OPC UA进行分析的主要原因。
另一个原因是卡巴斯基实验室是OPC基金会联盟的成员,我们认为这个联盟开发的技术是安全的。在讲述故事之前,我们可以说,根据我们的研究结果,我们收到了加入OPC基金会安全工作组的邀请,并感激的接受了它。
OPC UA的安全性分析
本文讨论了在、OPC UA协议在实现中的一些漏洞,另外,卡巴斯基实验室ICS CERT(工控系统计算机应急响应小组)发布本文的目的也是希望引起厂商的注意。因为他们会把此协议,运用到新开发的工业自动化系统软件和工业物联网中。ICS CERT希望这篇文章能够帮助软件供应商在最新的网络攻击中获得更高效的保护。另外,ICS CERT还讨论了我们的一些新的技术和发现,这些技术和发现可以帮助软件供应商控制他们的产品质量,并可能并其他软件安全研究人员所应用。
为什么ICS CERT选择OPC UA协议进行研究?
IEC 62541 OPC统一架构(OPC UA)标准是由OPC基金会联盟于2006年开发的,OPC UA是在传统OPC技术取得很大成功之后的又一个突破,让数据采集、信息模型化以及工厂底层与企业层面之间的通讯更加安全、可靠。OPC UA的几大优势:
· 与平台无关,可在任何操作系统上运行
· 为未来的先进系统做好准备,与保留系统继续兼容
· 配置和维护更加方便
· 基于服务的技术
· 可见性增加
· 通信范围更广
· 通信性能提高
OPC通信标准的核心是互通性和标准化问题,传统的OPC技术在控制级别很好地解决了硬件设备间的互通性问题,OPC UA之前的访问规范都是基于微软的COM/DCOM技术,这会给新增层面的通信带来不可根除的漏洞。加上传统OPC技术不够灵活、平台局限等问题的逐渐凸显,OPC基金会 (OPC Foundation)才发布了最新的数据通讯统一方法——OPC统一架构 (OPC UA),涵盖了OPC 实时数据访问规范 (OPC DA)、OPC历史数据访问规范 (OPC HDA)、 OPC报警事件访问规范(OPC A&E)和OPC安全协议(OPC Security)的不同方面。
OPC协议在现代工业环境中无处不在,OPC网关或服务器作为不同工业控制系统和遥测、监控和遥控系统之间的接口,统一了工业企业的控制流程。
由于OPC UA的新特性和设计良好的体系结构,该协议正在自动化系统供应商中迅速普及。OPC UA网关正在被全球越来越多的工业企业安装,该协议越来越多地被用于在工业物联网和智能城市系统之间建立通信。
另外,许多自动化系统所使用的技术安全,以及在全球范围内的工业设施的安全进行研究,是卡巴斯基实验室ICS CERT(工控系统计算机应急响应小组)的任务之一,这是他们对OPC UA进行分析的主要原因。
另一个原因是卡巴斯基实验室是OPC基金会的成员之一,因此有义务对该联盟所开发的技术的安全性进行讨论。
OPC UA协议
最初,OPC UA是为支持两种数据类型的数据传输而设计的,即传统的二进制格式(用于以前版本的标准)和SOAP/XML。今天,SOAP/XML格式的数据传输已被安全界认为是过时的,在现代产品和服务中几乎没有人再使用了。由于它在工业自动化系统中被广泛应用的前景是模糊的,因此我们决定将研究重点放在二进制格式上。
如果在主机上运行的服务交换的数据包被拦截,它们的结构很容易被破解。通过OPC UA协议传输的消息有四种:
· HELLO
· OPEN
· MESSAGE
· CLOSE
第一个消息总是HELLO (HEL),它作为客户端和服务器之间数据传输开始的标志。服务器通过向客户机发送应答(ACK)消息来响应。在最初的消息交换之后,客户端通常会打开消息,这意味着使用客户机提出的加密方法的数据传输通道现在是打开的。服务器通过发送消息OPEN (OPN)响应,其中包含数据通道的惟一ID,并显示服务器同意所提议的加密方法(或不加密)。
在客户端和服务器可以开始交换消息(MSG)后,每个消息包括数据通道ID、请求或响应类型、时间戳、发送的数据数组等。在会话结束时,将发送消息CLOSE (CLO),然后终止连接。
OPC UA是一个多方面的综合标准,在我们的研究中,我们只研究了OPC基金会开发的协议的具体实施情况。
最初,当卡巴斯基实验室ICS CERT团队在几家工业企业进行安全审计和渗透测试时,他们首先对分析OPC UA协议感兴趣。所有这些企业都使用了相同的工业控制系统(ICS)软件。在客户的批准下,他们把分析了软件的漏洞作为测试的一部分。
测试结果显示,他们分析的系统中的部分网络服务通过OPC UA协议进行了通信,而大多数可执行文件使用了名为“uastack.dll”的库。
作为分析协议实现安全性的一部分,ICS CERT团队决定做的第一件事是开发一个基于突变的fuzzing。
基于突变的fuzzing通常被称为“dumb fuzzing”,因为它的作用是执行输入的随机突变并且把被破坏的数据作为结果。然而,不要被它的名字所欺骗:“dumb fuzzing”是非常高效的,据称应用该技术在通用流行软件中已发现了大量的错误。
开发一个基于其逻辑和算法的特定程序的智能“dumb fuzzing”是非常耗时的。不过手动“dumb fuzzing”也可以帮助我们快速识别很难获得的微小漏洞,尤其是当需要分析的代码量很大时。
OPC UA Stack的架构使得内存中的模糊化变得困难,而要检查函数是否能够正确地工作,模糊过程必须包括将正确形成的参数传递给函数并初始化全局变量,这些变量是具有大量字段的结构。因此,该团队决定不直接在内存中测试函数,而是利用编写的“dumb fuzzing” 通过网络与正在分析的应用程序进行分析。
“dumb fuzzing”算法的结构如下:
1.读取输入数据序列;
2.对它们执行伪随机转换;
3.通过网络将结果序列发送到程序作为输入;
4.接收服务器的响应;
5.重复。
在开发了一组基本的突变(bitflip,byteflip,算术变异,插入幻数,重置数据序列,使用长数据序列)之后,研究人员成功地识别了uastack.dll中的第一个漏洞。它是一个堆损坏的漏洞,成功地利用它,可以使攻击者执行远程代码执行(RCE),在这种情况下,他们就可以使用NT权限/系统特权。研究人员识别的漏洞是由处理数据的函数造成的,这些数据是从一个套接字中读取的,这些函数错误地计算了数据的大小,然后将数据复制到堆上创建的缓冲区中。
经过仔细检查,可以确定uastack.dll库的易受攻击版本是由产品开发人员编译的。显然,这个漏洞是在修改它的过程中引入到代码中的。目前,研究人员还无法在OPC基金会发布的版本库中找到这个漏洞。
第二个漏洞是在使用UA . net堆栈的. net应用程序中发现的,在分析wireshark中应用程序的流量时,研究人员注意到一些数据包有一个is_xml位字段,其值为0。在分析应用程序的过程中,研究人员发现它使用了XmlDocument函数,该函数很容易被net版本4.5和之前的XXE攻击所攻击。这意味着, 如果我们将is_xml位字段的值从0更改为1并将特制的XML数据包添加到请求主体(XXE攻击), 我们将能够读取远程计算机上的任何具有NT权限/系统特权的文件,并且在某些情况下还可以执行远程代码执行(RCE)。
根据元数据判断,虽然该应用程序是研究人员分析的ICS软件包的一部分,但它是由OPC基金会联盟开发,而不是供应商,且是一个普通的发现服务器。这意味着OPC基金会使用OPC UA技术的其他产品可能包含该服务器,使其容易受到XXE攻击。这使得这个漏洞从攻击者的角度来看更有价值。
接着,研究人员将决定继续分析使用OPC UA的产品。
OPC UA分析
为了找出OPC基金会联盟实施OPC UA协议的漏洞,研究必须包括:
1.OPC UA栈(ANSI C, .NET, JAVA);
2.使用OPC UA栈的OPC Foundation应用程序(例如上述的OPC UA .NET Discovery Server);
3.其他使用OPC UA栈应用程序的软件开发人员;
作为研究的一部分,我们为自己设定了寻找以下三类漏洞的最佳方法。
将UA ANSI C栈进行Fuzzing测试化处理
先要说明一下,在OPC UA栈中寻找漏洞是有前提条件的。OPC基金会的开发人员提供的库基本上是一组基于规范的导出函数,类似于API。在这种情况下,通常很难确定已发现的潜在安全问题是否真正是一个漏洞。为了给出确定性答案,我们必须了解潜在的易受攻击的的脆弱函数是如何被使用的,以及使用它的目的是什么?在本文的案例中,很难在脱离实际的应用程序环境下,就OPC UA协议栈中的漏洞作出什么确定性结论。
在GitHub上的OPC基金会存储库中的开源代码,它包括一个使用UA ANSI C栈的示例服务器。在分析ICS组件的过程中,我们通常不能访问产品源代码。由于大多数ICS应用程序都是商业产品,主要针对Windows开发,并通过许可协议发布,而其中的条款则不包括对源代码的访问。在本文的示例中,源代码的可用性可以帮助研究人员发现服务器本身和库中的漏洞。UA ANSI C栈源代码有助于对代码进行手工分析并进行Fuzzing测试化处理,它还可以帮助我们了解是否已将新功能添加到UA ANSI C栈的特定实现中。
与OPC基金会联盟的几乎所有其他产品一样,UA ANSI C栈定位为不仅是出于安全考虑,而且还是一个跨平台的解决方案。这有助于研究人员在GitHub帐户中,使用二进制源代码工具在Linux系统上构建UA ANSI C栈以及示例服务器代码,并使用Fuzzing测试代码AFL。
为了加速Fuzzing测试,研究人员重载了网络函数–socket/sendto/recvfrom/accept/bind/select/… –,以从本地文件读取输入的数据,而不是连接到网络。另外研究人员还使用AddressSanitizer(内存问题的排查工具和方法)编译了程序。
为了将刚开始发现的一组示例集合在一起,我们使用了与第一个“Dumb” fuzzing测试器相同的技术,即使用抓包工具tcpdump从任意客户端从应用程序中捕获流量。另外,研究人员还为将fuzzing测试器作了一些改进,专门为OPC UA和特殊突变创建了字典。
从OPC UA中的二进制数据传输格式的规范可以看出,对于AFL来说,从OPC UA(“\xff\xff\xff”)中的一个空字符串的二进制转变为一个包含4个随机字节的字符串(例如,“\x04\x00\x00\x00AAAA”),是非常困难的。因此,研究人员开发了自己的转变机制,它与OPC UA内部结构一起工作,根据它们的类型随时转变。
在构建了包含所有改进功能的Fuzzing测试器之后,研究人员可以在几分钟内就发现了程序的崩溃情况。
对崩溃时创建的内存转储的分析使我们能够识别UA ANSI C栈中的一个漏洞,如果该漏洞被利用,可能会导致DoS攻击。
如何利用Fuzzing分析使用OPC UA的应用程序
由于在前一阶段中,研究人员已经对UA ANSI C栈进行了Fuzzing测试处理,并且由OPC基金会进行了一个示例应用程序,因此为了避免在分析联盟现有产品的过程中重新测试OPC UA栈,就需要了解OPC UA体系结构以及使用OPC UA 栈的应用程序之间的差异。
任何使用OPC UA协议栈的应用程序的两个主要函数都是OpcUa_Endpoint_Create和OpcUa_Endpoint_Open。OpcUa_Endpoint_Create函数为应用程序提供有关服务器和客户端之间可用的数据通信通道以及可用服务列表的信息。OpcUa_Endpoint_Open则定义了可用的网络和它将提供的加密模式。
可用服务列表使用服务表来定义,该表列出了数据结构并提供了每个服务的详细信息。每一个结构都包含所支持的请求类型、响应类型以及在请求预处理和后处理期间将调用的两个回调函数。另外,预处理函数在大多数情况下都表示为“stubs”。研究人员将转换器代码包含在请求预处理函数中。该函数使用突变数据进行输入、输出与请求类型匹配的正确结构。这样,研究人员就可以跳过应用程序启动阶段,直接启动一个事件循环来创建一个单独的线程来读取伪套接字等。这使得研究人员能够将他们的Fuzzing测试从50个exec/s的数量级加速到2000个exec/s。
由于研究人员使用以这种方式改进的“Dumb” fuzzing测试器,他们还在OPC基金会应用程序中发现了另外8个漏洞。
分析使用OPC UA 栈的第三方应用程序
在对OPC基金会产品完成了分析后,研究人员开始分析使用OPC UA 栈的商业产品。卡巴斯基实验室的的研究人员利用渗透测试中使用的ICS系统,分析了一些他们客户的设备安全状况,他们选择了不同厂商的几种产品,其中包括全球领先的解决方案。在得到客户的批准后,研究人员就开始分析这些产品中OPC UA协议的实现过程。
在搜索二进制漏洞时,Fuzzing测试是最有效的技术之一。在以前的案例中,当分析Linux系统上的产品时,研究人员使用的就是源代码二进制检测技术和AFL Fuzzing测试器。但是,本文分析时使用的OPC UA 栈的商业产品由于是在Windows上运行,对此,要用一种称为WinAFL的AFLFuzzing测试器。简而言之,WinAFL是移植到Windows的AFLFuzzing测试器。但是,由于操作系统的不同,两个Fuzzing测试器在一些关键功能方面,还是有所不同的。由于WinAFL不是使用来自Linux内核的系统调用,所以它是使用WinAPI函数而不是静态源代码工具,它使用DynamoRIO动态检测二进制文件。总体而言,这些差异意味着WinAFL的性能显着低于AFL。
如果要以标准方式使用WinAFL,就必须编写一个程序,该程序将从专门创建的文件中读取数据,并从可执行文件或库调用函数。然后,WinAFL将使用二进制工具将该进程置入循环模式中,并且会多次调用该函数,从正在运行的程序获取反馈,并以变量数据作为参数重新启动该函数。这样,每次使用新的输入数据时都不必重新启动程序,这样在Windows中创建新进程就会占用大量处理器的运行时间。
不幸的是,这种Fuzzing测试的方法不适用于本文的情况。由于OPC UA协议栈的异步架构,通过网络接收和发送的数据处理被现为回调函数。因此,根据WinAFL Fuzzing测试器的要求,不可能为每种类型的请求标识一个数据处理函数,此时,该函数将接受指向包含数据和数据大小的缓冲区的指针。
在WinAFL fuzzer的源代码中,我们发现了开发者留下的Fuzzing测试网络应用程序的评论。于是研究者按着这些评论,对网络Fuzzing测试进行了一些修改。具体来说,我们在模糊测试的代码中包含了与本地网络应用程序通信的功能。因此,Fuzzing测试器不会执行程序,而是通过网络将有效载荷发送到已在DynamoRIO下运行的应用程序。
但是,通过努力,研究人员只能达到5 exec /s数量级的Fuzzing测试率。这太慢了,即使使用像AFL这样的智能Fuzzing测试器也会花费太长时间才能发现漏洞。因此,研究人员决定还是使用 “dumb” Fuzzing测试器,不过要对它进行改进。
1.具体就是改进了突变机制,根据研究人员对传输到OPC UA栈的数据类型来修改了数据生成算法。
2.研究人员为每种支持的服务创建了一组示例(python-opcua库,其中包含了与几乎所有可能的OPC UA服务交互的功能)。
3.当使用带有动态二进制工具的Fuzzing测试器来测试像这样的多线程应用程序时,在应用程序代码中搜索新程序是一项非常复杂的任务,因为很难确定哪些输入数据会导致应用程序的不正当行为。由于Fuzzing测试器是通过网络与应用程序通信的,并且研究人员可以在服务器的响应和发送给它的数据之间建立清晰的连接(因为通信是在一个会话的范围内进行的),所以研究人员不需要解决这个问题,而是利用一种算法,该算法可以在从服务器接收到之前尚未观察到的新响应时,简单地识别出新的执行路径。
经过这样的改进,我们的“dumb”Fuzzing测试器不再是“dumb”,每秒执行次数从1次或2次增加到70次,这对于网络Fuzzing测试来说就非常好。这样,研究人员就发现了另外两个无法使用智能Fuzzing测试识别的新漏洞。
测试结果
截至2018年3月底,卡巴斯基实验室的研究人员已在包括OPC基金会的产品中包含17个零日漏洞,这些漏洞已被识别和关闭,另外还发现了使用这些产品的商业应用程序中的几个漏洞。目前,研究人员已经向易受攻击软件产品的开发人员报告了所有发现的漏洞。
在整个研究过程中,来自OPC基金会的专家和开发商团队的代表都及时回应了所发现的漏洞信息,并且进行了及时处理。
在大多数情况下,使用OPC UA 栈的第三方软件中的漏洞是由于开发人员未正确使用OPC 基金会的 uastack.dll库中实现的API的功能而导致的,例如,传输的数据结构中的字段值被错误地解释。
另外,在某些情况下,产品漏洞是由商业软件开发商对 uastack.dll库所做的修改引起的。例如,从套接字读取数据的函数的不安全实现。值得注意的是,OPC基金会最初计划实施的功能并未包含此漏洞。虽然研究人员并不知道为什么商业软件开发人员要修改数据读取逻辑,但显然开发人员并没有意识到OPC基金会在其中包含的附加检查是多么的重要,因为一切安全功能是建立在附加检查之上的。
在分析商业软件的过程中,研究人员还发现了开发人员已经从OPC UA 栈实施示例中借用了代码,并将该代码逐字复制到其应用程序中。显然,他们认为OPC基金会确保这些代码片段的安全性与确保库中使用的代码安全性的方式相同。不幸的是,这个假设是错误的。
以上这些漏洞会导致黑客发起DoS攻击和远程执行代码。重要的是,在工业系统中,DoS攻击漏洞比任何其漏洞造成的威胁都大。例如,遥测和遥控系统中的拒绝服务可能导致企业遭受重大经济损失,并且在某些情况下甚至会导致施工过程中断和关闭。
总结
OPC基金会的开放源代码表明其发布的协议是开放的,并致力于让使用它的商业产品更加安全。
同时,本文的分析表明,目前OPC UA协议栈的实施不仅不普及,而且还存在一系列重大的基础问题。
首先,使用OPC UA 栈的商业开发人员对OPC UA 栈的设计意图不是很了解。该协议的当前实现中存在着有大量的指针计算,不安全的数据结构,变化常量,函数之间复制的参数验证代码以及在代码中分散的其他过时特性。由于软件开发人员为了使他们的产品更安全,倾向于从代码中清除这些功能。但由于被删改的代码没有很好的记录机制,这使得在使用或修改过程中更容易引入其他错误。
其次,利用OPC UA的商业开发人员显然低估了OPC基金会联盟提供的所有代码的信任软件供应商。研究人员认为,尽管API使用示例未包含在OPC基金会认证的产品列表中,但在API使用示例代码中留下漏洞是完全错误的。
最后,即使OPC基金会认证的产品也存在安全问题。
根据研究人员的推测,OPC UA开发人员在进行产品安全测试时,并未使用类似于本文所描述的模糊测试技术。
由于开放的源代码不包括单元测试或任何其他自动测试的代码,这就使得产品的开发人员在修改代码产品时,更加难以利用模糊测试技术来测试OPC UA栈的安全。
所以最后的结果就是,尽管OPC UA的开发人员试图使他们的产品安全,但他们仍然忽视了安全编码的一些前提和技术。
根据卡巴斯基实验室的评估,当前的OPC UA栈实现不仅不能保护开发人员免受一些小漏洞的影响,而且还容易引发更多的漏洞。考虑到现实情况,研究人员认为目前商业产品还是慎用OPC UA。