我们继续分析工业交换机的漏洞:我们执行没有密码的任意代码



在实证研究2019中,我们回顾了Moxa工业交换机管理协议。这次我们将继续本主题,并详细分析我们的专家确定的FL SWITCH 3xxx,FL SWITCH 4xxx和FL SWITCH 48xx系列模型的Phoenix Contact交换机中的漏洞CVE-2018-10731。在设备的Web界面中检测到此漏洞,可以在不知道设备凭据的情况下执行任意代码,在CVSS版本3等级中,该漏洞的等级为10分之9。

第一眼


上面提到的设备正在运行Linux,您可以使用Web界面对其进行配置。与许多其他家用和工业IoT设备一样,Web界面由许多处理用户HTTP请求的CGI应用程序组成。在我们的案例中,CGI应用程序积极使用cgic库,该库有助于处理HTTP请求,并且该库的功能内置libipinfusionweb.so在设备文件系统中的共享库中。

在处理HTTP请求时,Web服务器将用户请求数据作为一组环境变量传递给CGI应用程序。它们的初始处理由main函数执行libipinfusionweb。接下来,该函数main调用cgiMainCGI应用程序的函数,在该函数中对请求进行进一步处理。



图1.处理HTTP请求

在其工作过程中,库的主要功能会libipinfusionweb调用一个函数get_login_user该函数根据传递的Cookie值确定用户是否已通过系统中的身份验证。



图2.主

函数的伪代码片段该函数使用该函数get_login_user接收Cookie参数c_session的值cookies_get_value并将其存储在变量中local_e0。变量本身local_e0是一个长度为0x80的单字节字符数组,并且距离堆栈的开头距离为0xE0。



图3. get_login_user函数的伪代码片段

但是,在函数代码cookies_get_value中可以看出,cgiCookieString函数接收的Cookie参数值的最大长度为0x400字节。



图4. cookies_get_value函数的伪代码的一部分

因此,当传递长度超过0xE0(224)个字符的Cookie参数时,该函数会get_login_user将此参数的值保存到其堆栈中,结果local_e0将覆盖该变量后面的堆栈上的所有信息,包括地址返回函数。

注意:当一个函数调用另一个函数时,返回地址存储在堆栈中。当被调用函数完成其工作时,控制权将转移到该地址。因此,如果重写此地址,则可以控制程序执行过程。例如,攻击者可以使用位于程序地址空间中的恶意shellcode的地址替换此地址。

请注意,返回地址的重写是在验证身份验证之前进行的,这使得有可能利用此漏洞的攻击者不知道设备的凭据。

开发


我们研究了几种方法来证明利用此漏洞的可能性。最简单的方法是将有效载荷代码写到堆栈上(0x400-0xE0 =剩下800字节,对于代码来说足够了),然后用代码地址重写返回地址。从理论上讲,此选项是可行的,因为易受攻击的交换机的处理器不支持NX位功能(也就是说,它允许执行位于包括堆栈在内的任何位置的代码),但实际上存在严重限制。

易受攻击的交换处理器具有MIPS架构;该体系结构中的许多处理器指令都以包含零字节的字节序列进行编码。缓冲区内容被写到第一个零字节(由于使用了该功能)strcpy),因此仅需要使用不包含空字节的操作数,这是不可能的,因为任何有效载荷都将使用这些字节中的至少几个字节。

同样,在构建ROP链时,我们将不得不面对空字节的限制:ROP小工具的地址不应包含零,这会使它们的搜索变得非常复杂。总的来说,我们只能使用由strcpy函数复制的一个零。这限制了完整ROP链的创建,此外,我们所需的小工具非常少。但是,在libipinfusionweb库中搜索期间,发现以下代码片段:



图5. libipinfusionweb库的可执行代码片段

假设寄存器$ s0的内容受到控制,此代码片段使您可以使用一个函数执行OS命令mysystem(该函数最初没有名称,但是我们将其重命名,因为它与Linux中的系统功能非常相似)。

由于我们正在重写get_login_user函数的返回地址,因此该函数将执行到最后。在get_login_user函数的结尾中,您可以看到寄存器$ s0的值从堆栈上先前保存的值中恢复(从堆栈顶部偏移0xD8)。但是,在这一点上,堆栈的这个区域已经在我们的控制之下,也就是说,实际上,我们可以实现对寄存器$ s0内容的控制,从而可以使用函数执行任意OS命令mysystem



图6. get_login_user函数可执行代码的片段

因此,为了成功演示此漏洞的利用,我们需要将Cookie c_session包含以下内容长行作为参数发送

  • OS字符串命令,该命令随后将传递给mysystem函数;
  • 该命令在堆栈上的地址;
  • 新的返回地址(图5中所示代码段的地址)。

最终的有效负载应如下所示:



图7.有效负载

至此,我们已经在设备上安装了一个外壳,该外壳使用了需要管理员权限才能运行的漏洞。因此,我们能够获得有助于我们运营的其他信息:

  • 被研究设备上的ASLR被禁用-因此,所使用的小工具的地址和OS命令将始终相同。



图8.被调查设备上的ASLR状态

  • 堆栈可能位于的内存地址范围。为了计算确切的地址,我们遍历了该范围内的所有地址。

作为有效负载,我们实现了Web外壳的加载,这是具有以下内容的CGI应用程序:

#!/bin/sh
eval $HTTP_CMD 2>&1

由于根据CGI协议,HTTP头的内容以名称为HTTP_ <Header Name>的环境变量的形式传输到CGI应用程序,因此此shell eval使用命令执行CMD HTTP头的内容。下图显示了使用已加载的shell成功执行和执行ls命令的结果。



图9.成功执行和执行ls命令的结果

结论


我们已经展示了利用此漏洞的能力。正如我们已经提到的,其操作不需要知道密码,因此即使未经身份验证的攻击者也可以执行该操作。

入侵工业网络交换机可能会损害整个生产。违反网络交互可能会对过程产生不利影响,直到过程完全停止。

有关漏洞和PoC的信息已转移到发布了更正的固件版本1.34的供应商,并且将标识符CVE-2018-10731分配给了漏洞本身。

寻找一个人


如果您希望这样做,我们只是在寻找我们团队中的专家。我们从事过程控制系统(大型工业/能源/运输设施等)的安全性分析。在每个项目中,我们都在寻找停止或破坏这些对象运行的方法。每次我们找到许多影响制造过程的方法,探索工业硬件和软件,分析专有网络协议。我们发现并报告了许多zirodey,编写了报告(不是根据GOST的报告),并且做得更多。有时间时,我们不仅在会议上在IB上演讲。链接到空缺:hh.ru/vacancy/36371389

Vyacheslav Moskvin 发布,Positive Technologies

All Articles