安全路透社
当前位置:安全路透社 > 安全客 > 正文

【技术分享】黑科技:看我如何利用多个漏洞黑掉一台机器人系统


在我们看来传统的工业机器人是很无趣的。通常情况下,它们独自或者在人类的指导下在制造和生产环境中执行重复性的,程序化的任务。它们经常被用来执行危险或不适合人类去干的任务,因此,它们的工作环境往往与人类或者其他有价值的机器隔离开来。

但是最新一代的协同机器人(“cobots”)并非如此。在符合安全标准的同时,他们与人类或者其他机器在共同的环境中工作。这一代机器人与人类携手并进,协助人类完成工作,而不仅仅是执行自动化的,危险性的操作。 Cobots可以学习移动,通过高清摄像机“看”,或通过麦克风“听到”来完成工作。

http://p7.qhimg.com/t018a1a9484a164f502.png

http://p6.qhimg.com/t01dbafc93cee331d4c.png

因此,Cobots比传统的工业机器人呈现出了更为有趣的攻击研究。但是,Cobots只限于工业应用?不,他们也可以被集成到其他装置中!

http://p5.qhimg.com/t0192b5253c9dcf40a6.png

http://p4.qhimg.com/t013c090820d23f6283.png

去年二月,Cesar Cerrudo和我发表了一篇非技术论文“Hacking Robots Before Skynet”,在这篇论文中我们对来自多家知名厂商的几款家用,商用以及工业机器人进行了研究,在这些机器人中我们发现了近50个关键的安全漏洞。在Cobots这部分机器人部分,我们对包括来自Rethink Robotics的Baxter / Sawyer和Universal的UR机器人进行了研究,这些都是工业机器人行业的领导者。

Baxter / Sawyer:针对这款机器人,我们发现其存在身份验证漏洞,采用不安全的协议传输和默认的部署配置,易受到物理攻击以及使用了一个存在多个安全漏洞的框架-ROS,该公司已经在2017年2月修复了我们报告的主要问题。

UR:我们在许多控制协议中发现了身份验证问题、易受到物理攻击、内存破坏漏洞以及不安全的通信传输等安全漏洞。所有这些问题在最新版本(3.4.2.65,2017年5月)的系统中中仍未修补。

根据IOActive网络安全公司漏洞披露的政策,我们已经在去年1月份与供应商取得了联系,所以他们有足够的时间来修复这些漏洞并通知客户。我们的目标是使cobots机器人更安全,防止攻击者利用漏洞对企业,员工和周围环境造成严重伤害。我真的希望这篇文章可以推动cobots机器人的安全性能够向前发展,使得我们可以安全地使用现在的这些机器人以及后续更多代的机器人。

在这篇文章中,我将讨论攻击者如何通过cobot(例如UR3,UR5,UR10 – Universal Robots)机器人的多个漏洞来远程修改安全设置,违反适用的安全准则,通过移动机器人对其周围的工作人员造成身体上的伤害。通过这个例子我们可以看到如果这些系统被黑客攻击或者控制可能会给人类造成多么严重的后果,操纵安全限制和禁用紧急按钮可能直接威胁到人的生命。在这个例子中,我们利用了cobot机器人的六个漏洞来改变其安全限制,并通过远程网络禁用安全面板和紧急按钮/传感器,演示视频可以在下面这个url中看到:

问:这些机器人真的可以伤害一个人吗?

答:是的,加拿大蒙特利尔(ETS)技术研究所的控制和机器人实验室的一项研究清楚地表明,即使是较小的UR5模型,其强大到足以严重伤害一个人。即使是在慢速移动中,他们的力量也足以造成颅骨骨折

问:等等,他们有没有安全功能,防止他们伤害附近的人类?

A:是的,但是黑客可以远程入侵,我将在下一个技术部分告诉你黑客是如何入侵机器人系统的。

问:这些机器人部署在哪里?

A:世界各地,每天在多个生产环境中都有机器人在工作。


集成商定义所有安全装置


Universal Robots公司是UR机器人的制造商,但是在特定应用中安装UR机器人的公司是集成商,一个机器人只有集成和安装之后才被认为是一个完整的机器。 UR机器人的集成商负责确保消除整个机器人系统的任何重大危险,这包括但不限于:

1. 对整个系统进行风险评估,在许多国家,这是法律规定的的必要流程。

2. 如果风险评估认为安全,则连接其他机器和其他安全装置

3. 在Polyscope软件(控制面板)中设置相应的安全设置,确保用户不会使用“安全密码”来修改任何安全措施。

4. 验证整个系统的设计和安装是否正确

Universal Robots公司已经意识到集成商必须考虑机器人存在的潜在的重大危害例如:

1. 机器人工具或者工具连接器上的锋利的刀边或者刀尖有可能刺伤皮肤;

2. 机器人轨道附近的障碍物上的锋利刀边或者刀尖有可能刺伤皮肤;

3. 由机器人的碰撞引起的瘀伤;

4. 由机器人沉重的机器零件或者材料表面之间的碰撞而产生的扭伤或骨折;

5. 由于未经授权更改安全配置参数而导致的错误

一些安全相关功能是专为cobot应用而设计的,这些功能包括:

1. 力和功率限制:用于在机器人和操作员之间碰撞的情况下,减少机器人在运动方向上施加的夹紧力和压力;

2. 动量限制:通过降低机器人的速度,用于在机器人和操作者之间碰撞的情况下减少高瞬态能量和冲击力;

3. 刀具定向限制:避免锋利的刀边指向操作者;

4. 速度限制:用于确保机器人手臂低速运行;

5. 安全边界:用于限制机器人的工作空间,强制其停留在定义的虚拟平面的正确一侧,而不能通过它们。

http://p1.qhimg.com/t018dab51e670dbdc30.png

6. 安全I/O:当触发此输入安全功能(通过紧急按钮,传感器等)时,向输入端发送低信号,并使安全系统转换到“减小”模式。

http://p7.qhimg.com/t016cf9f55111d10597.png

安全设置可以有效防止许多潜在危险事件。但是,如果恶意攻击者绕过这些安全措施,操纵机器人来威胁人类生命,那可能会发生些什么呢?

http://p9.qhimg.com/t01f22107a7c93ffcb1.png

UR用户指南的声明


远程更改安全配置


“安全配置只能根据集成商进行的风险评估进行更改。如果改变了安全参数,机器人的整个系统应当被认为是新的,这意味着包括风险评估在内的整个安全审批流程应该相应的更新“。

远程更改安全配置的过程如下所示:

步骤1.通过在UR Dashboard Server上利用身份验证漏洞来确认远程机器人系统的版本信息;

步骤2.通过在UR Modbus TCP服务中利用基于堆栈的缓冲区溢出漏洞获得对系统的控制权限,并以root身份执行命令;

步骤3.修改security.conf文件,该文件将覆盖所有的通用安全限制,接头限制,边界和安全I/O值限制;

步骤4.强制绕过计算校验和值,并上传新文件。我们需要伪造这个校验和值,因为通常集成商很可能在硬件上写入当前的校验和值;

步骤5.重新启动机器人,以便更新安全配置;

步骤6.通过利用UR控制服务上的认证问题,以任意危险的方式操作机器人。

通过逆向分析ursys-CB3.1-3.3.4-310.img这个系统镜像,我知道了机器人的入口点以及允许网络上的其他机器与操作系统进行交互的服务程序。对于此演示,我使用供应商提供的URSim模拟器,该模拟器包含了机器人镜像中大部分核心的二进制文件。尽管这个示例使用模拟器可以更为清楚展示攻击效果,但我还是修改了这个二进制文件,修改后的文件部分代码可以在Linux机器上正常运行。URControl这个二进制文件中导出了很多不同的网络服务,这些网络服务的私有协议在实现上都没有使用强大的认证机制。例如,网络上的任何用户都可以向其中一个服务发出命令,并获取正在运行的进程的远程操作系统的版本(步骤1):

http://p0.qhimg.com/t01d011c4ace42cc776.png

现在我已经验证了远程目标运行着一个易受攻击的系统ursys-CB3.1-3.3.4-310(UR3,UR5或UR10),下一步我准备利用网络服务漏洞来破坏这个机器人系统(步骤2)。由于UR Modbus TCP服务(端口502)不支持对命令源的认证机制,因此,网络攻击者可能会在控制的过程中破坏机器人系统。与机器人IP连接的攻击者可以发出Modbus读/写请求,并部分更改机器人的状态或向操作人员发送请求,以更改控制链接的状态。发送Modbus写请求并不能改变机器人的任何安全设置,然而,我们在在UR Modbus TCP接收器(URControl内核的一个二进制文件)中发现了一个基于堆栈的缓冲区溢出。

UR Modbus TCP服务程序的recv函数存在堆栈缓冲区溢出漏洞,攻击者通过该函数可以向程序的缓冲区写入超出其长度的内容,造成缓冲区的溢出,从而破坏程序的堆栈,使程序转而执行其他的指令,以达到攻击的目的,这是一个很常见的堆栈缓冲区漏洞。

http://p9.qhimg.com/t01126b1abf9e7541de.png

在进行漏洞利用之前,我们先来看一下漏洞利用的将要面临的阻碍。机器人的Linux内核被设置为堆栈随机化(randomize_va_space = 1 => ASLR),VDSO(virtual dynamic shared object page)和内存区域共享。此外,由于内核中的"No eXecute" (NX) 被置位,因此该内核文件是不可写以及不可执行的。

当对目标缓冲区进行溢出操作时,我们也需要要对指向函数参数的指针执行溢出操作。在函数返回之前,这些参数在其他函数调用中被使用,所以我们必须要为这些函数调用提供有效的实参。否则,我们永远不能找到函数的返回点以及控制函数的执行流程。

http://p5.qhimg.com/t01e57e895cc881467d.png

如上图所示,edx + 0x2c内存地址中的值作为一个参数传递给了0x82e0c90函数,另一个就是EBX寄存器(从我们以前的EDX控制指针计算出来)也需要指向一个与文件描述符相关的结构体变量。

http://p7.qhimg.com/t01f31f40e44dfea7d2.png

在实现上,需要选择符合上述两个要求的静态地址,我使用以下静态区域,因为ASLR技术会使内存中其他地址都可能发生变化。

http://p4.qhimg.com/t01e7559a536e29bba4.png

我写了一些脚本用来找到一个合适的内存地址,通过这些脚本我发现0x83aa1fc这个地址是完美的,因为它适合这两个条件:

0x83aa1fc + 0x2c指向有效内存 – > 0x831c00a(“INT32”)

0x83aa1fc + 0x1014包含0(所有这个区域几乎都为零)

现在我已经找到满足上述两个条件的解决方法,可以继续执行代码直到函数返回,并且通过溢出堆栈上保存的寄存器,我能够得到EIP的控制权:

http://p0.qhimg.com/t0163c71f0ac0303284.png

现在,我控制了大部分的寄存器,所以我需要将我的shellcode放到机器内存中的某个地方,并将函数的执行流重定向到shellcode那里。为此,我在实现上使用了面向返回的编程(ROP),遇到的难题是需要合适的EXP代码来执行漏洞利用。自动ROP链工具不能很好地满足我的需求,所以我决定自己手动进行此操作。

现在,我最终目的是希望在目标系统中执行一个反弹shell以连接到我的攻击机器上。在Linux系统中构建基于远程ROP漏洞利用的一个关键点是系统调用,在这些可靠的系统调用函数中,我可以使用诸如write或dup2之类的系统函数去重用已经创建的套接字来反弹一个shell。

在这个二进制文件中,我只找到一个int 0x80指令,该指令用于在支持x86指令集的Linux系统中调用系统调用。使用该指令我只能执行一个系统调用:我将使用execve系统调用来执行一个程序。int 0x80指令需要使用设置在一个寄存器中的一个系统调用号(EAX,在本例中为0xb),然后设置一个指向特殊结构的寄存器(EBX)。这个结构包含一个指针数组,每个指针指向要执行的命令的参数。

想要触发这个漏洞,就不能在请求缓冲区上使用空字节(0x00)。这是碰到的另一个难题,因为我们需要发送命令和参数,并创建一个以空字节结尾的指针数组。为了克服这个难题,在请求中我先发送一个占位符(像0xFF这样的字节块),之后利用ROP在运行时将占位符0xFF替换成0x00。

伪代码中如下图所示(通过TCP链接来反弹一个Shell):

http://p1.qhimg.com/t017d4bfd39cb9b699c.png

由于所有的受控数据都位于堆栈中,所以首先我将尝试将堆栈指针(ESP)与我的最大控制区段(STAGE 1)对齐。我将最大的受控部分分为两个阶段,因为它们都可能包含许多ROP代码。

http://p5.qhimg.com/t012b7a557dcc388900.png

正如前面所叙述的那样,此时我控制了EBX和EIP这两个寄存器。接下来,我必须将ESP与任何控制的区段对齐,以便我可以开始执行ROP代码。

以下代码片段(ROP1 0x8220efa)用于调整ESP:

http://p7.qhimg.com/t013893fd3c5c87843d.png

这样ESP = ESP + EBX – 1,上面的代码将ESP与我的STAGE 1部分的代码对齐。 EBX应该将ESP减少0x137字节,所以我使用数字0xfffffec9(4294966985),因为当把该数字添加到ESP时,我们就能够得到所需的值。

当代码的retn指令执行时,STAGE 1的ROP代码将会开始执行。漏洞利用的第1阶段将执行以下操作:

1. 将结构体变量的末尾字节置0。这样处理器就会知道EXECVE参数只是这三个指针。

2. 在我们的结构体参数中保存指向我们第一个命令的指针。

3. 跳到STAGE 2,因为这里没有太多的空间。

http://p1.qhimg.com/t014aee58369b7fb057.png

漏洞利用的第2阶段将执行以下操作:

1. 将cmd []数组中的每个参数末尾的\ xff \ xff \ xff \ xff删除。

2. 在我们的结构体参数中保存一个指向cmd []数组中第二和第三个参数的指针。

3. 为EXECVE准备寄存器。如前所述,我们需要

EBX = * ARGS []
EDX = 0
EAX = 0XB

4.调用int 0x80代码并执行反弹shell。

http://p9.qhimg.com/t01248290ddf17103f8.png

一旦TCP反弹shell的有效载荷被执行,机器人系统便会发送一个请求用来和我的攻击电脑建立链接。现在我可以执行命令,并可以使用sudo在机器人控制器中以root身份执行命令。

安全设置保存在security.conf文件中(步骤3),Universal 机器人在系统中实现了CRC(STM-32)算法,使用此算法为二进制文件提供完整性校验,并将计算的校验值保存在磁盘上。但是该算法不会为安全配置提供任何真正的完整性校验,因为对新配置计算产生的新校验值,可能会与文件系统上的某个特殊文件的校验值产生冲突。我逆向分析了对每个安全配置进行计算的算法,并用代码实现了该算法。在视频演示中,尽管伪造一个新的CRC校验值可能会使攻击变得更容易,但我并没有这样做,而是保持该CRC校验值不变(位于屏幕的右上角)(步骤4)。

在修改机器人上的任何安全配置之前,我创建了一个进程,该进程会在25秒后自动启动一个机器人控制器的新实例,这将给我足够的时间来下载,修改和上传一个新的安全设置文件。以下命令创建了一个新的URControl进程。命令中我使用的是Python语言,因为它允许我在执行forking操作时关闭当前正在运行的所有进程文件描述符。因为我正在从反弹shell的对象中执行fork操作,所以我需要创建一个不继承任何文件描述符的新进程,以便在父进程URControl被关闭时,从该进程fork的子进程也都会被关闭。

http://p1.qhimg.com/t01d83256b7c3696f24.png

现在我有25秒下载当前文件,修改它,计算新的CRC,重新上传它,并关闭正在运行的URControl进程(它具有较旧的安全设置配置),我可以通过使用kill命令来关闭当前的URControl进程(步骤5)。

http://p9.qhimg.com/t01c9235f7032870d51.png

最后,我将此命令发送到URControl服务,以加载我们上传的新配置文件,同时我也关闭可能会出现在用户界面上的任何弹出窗口。

http://p8.qhimg.com/t016000a53ab13e4b0e.png

最后,攻击者可以简单地调用URControl服务中的movej函数,以自定义速度和加速度远程移动被攻击者控制的机器人(步骤6)。


后记


本文我向大家展示了先进的机器人系统中存在的安全漏洞以及被利用的整个过程,这些其实都是非常技术性的安全漏洞,如其中一个协议的缓冲区溢出漏洞,将整个机器人系统的安全性暴露给了远程的攻击者。 我们已经在一月份向供应商报告了漏洞的整个流程,但是该漏洞还没有被修补。


原文链接:http://blog.ioactive.com/2017/08/Exploiting-Industrial-Collaborative-Robots.html

未经允许不得转载:安全路透社 » 【技术分享】黑科技:看我如何利用多个漏洞黑掉一台机器人系统

赞 (0)
分享到:更多 ()

评论 0

评论前必须登录!

登陆 注册