模糊测试与漏洞利用实战:MikroTik无需认证的远程代码执行漏洞(CVE-2018–7445)(上)

41yf1sh 漏洞 2019年3月17日发布
Favorite收藏

导语:希望这篇文章能为正在进行的MikroTik RouterOS漏洞研究做出一点贡献……

一、总览

1. CVE-2018-7445是SMB服务二进制文件中存在的栈缓冲区溢出漏洞,存在于MikroTik RouterOS 6.41.3/6.42rc27之前的所有版本和体系结构中。

2. 该漏洞使用Cisco Talos的Mutiny模糊测试工具通过Dumb Fuzzing的方式发现,并在大约1年前报告和修复。

3. 易受攻击的二进制文件没有使用栈金丝雀保护(Stack Canaries)实现编译。

4. 在漏洞利用中,使用ROP将堆标记为可执行文件,并跳转到堆中的固定位置。堆基址不是随机的。

5. 在2018年,使用Dumb Fuzzing测试方法,发现了目标中的漏洞,但我确定在2019年已经不存在此类漏洞。

6. 本文主要描述了从目标选择到漏洞发现再到漏洞利用的一个完整过程。

二、简介

在过去几年中,安全研究人员在MikroTik RouterOS设备中发现并报告的漏洞数量呈现出猛增的趋势。从CIA Vault 7泄露的内部Web服务器远程缓冲区溢出漏洞,到Kirils Solovjovs(来自Possible Security)和Jacob Baines(来自Tenable)报告的导致实现远程攻击的大量其他漏洞。

近期,在Zerodium的漏洞利用收购计划中,MikroTik被加入到符合条件的路由器品牌列表之中。该计划将在1个月的时间内,收集远程代码执行(RCE)漏洞,并给予发现者10万美元的奖励。这可能反映出,安全研究人员对MikroTik产品及其安全态势越来越感兴趣。

我们希望这篇文章能为正在进行的MikroTik RouterOS漏洞研究做出一点贡献。我将详细描述我与我在Core Security的同事Juan共同寻找并利用CVE-2018-7445漏洞的全过程,这是MikroTik RouterOS的SMB服务中的一个远程缓冲区溢出漏洞,可以被未经身份认证的攻击者触发。

我们知道,漏洞很容易被找到,漏洞的利用也很简单。因此,我们发布本文的目的是为大家提供详细的发现漏洞与编写漏洞利用的心路历程,希望能对一些内存损坏漏洞研究者,或者其他漏洞挖掘的入门者有所帮助。我们将尝试在实际场景中,通过网络服务发现漏洞,并为其编写漏洞利用程序。

原始通告可以在这里找到。

声明:目前我已不再就职于Core Security,因此本文的观点不代表公司的观点。

三、准备工作

在所有运行着6.41.3/6.42rc27之前版本RouterOS的体系结构和设备中,都存在此漏洞。因此,我们准备工作的第一步,就是找到一个易受攻击的系统环境。

MikroTik会维护以前发布的所有版本,并对它们进行存档,这使得我们创建环境的过程更加容易。当然,也可以下载RouterOS的Cloud Hosted Router版本,该版本可以作为具有完整RouterOS功能的虚拟机提供。这样一来,就允许研究人员在x86-64架构中运行RouterOS,而无需实际的硬件设备。

我们从这里获得6.40.5版本的Cloud Hosted Router,并在VirtualBox上创建虚拟机。

1.png

2.png

3.png

默认管理员帐户是admin,其默认密码为空。

4.png

RouterOS控制台是一个受限制的环境,不允许用户在预先定义的配置选项集之外执行任何命令。

如果要进行漏洞的发现,需要启用SMB服务,可以通过ip smb set enabled=yes命令来实现。

5.png

请注意,该服务在默认情况下是没有启用的,这就使得该漏洞被利用的可能性降低很对。此外,我们不建议将SMB服务暴露在公网上。但是,也不排除内部网络中存在内部攻击者,可能有权访问此服务。

受限制的控制台非常不适合于我们的漏洞研究工作,因此在挖掘漏洞之前,我们最好能拥有完整的Shell访问权限。Kirils Solovjovs发表了针对RouterOS越狱的广泛研究,并发布了可以针对6.40.5版本实现越狱的工具。在本文中,重复一些基本的细节是没有意义的,建议各位读者可以前往Kirils的网站查看,或者阅读Jacob Baines发表的关于最新版本的文章。需要提醒的是,6.40.5的入口点目前已经被修补。

对RouterOS 6.40.5版本进行越狱的过程非常简单,只需要克隆mitrotik-tools存储库,并在我们的虚拟机中运行交互式的exploit-backup/exploit_full.sh漏洞利用即可。

6.png

最后,可以从这里下载预编译版本的GDB,并使用FTP将其上传到系统。

7.png

我们通过Telnet方式连接到设备,从而允许附加到正在运行的进程中,并对其进行正确调试。

8.png

现在,我们准备开始寻找网络服务中的漏洞。

四、目标选择

在RouterOS中运行了许多服务,其中包含一些例如HTTP、FTP、SSH和Telnet在内的常见服务,以及一些特定于RouterOS的服务,例如端口2000上运行的带宽测试服务。

9.png

Jacob Baines指出,通过使用Winbox协议,可以访问90多种实现网络服务的不同二进制文件。详细请参考他博客中记载的真实攻击面

当我们开始对RouterOS进行漏洞挖掘的过程中,如果没有花费时间对Winbox的二进制文件进行逆向工程,那么就无法发现所有可以实现的功能,仅仅是可以查看在网络上明显属于监听中的几个二进制文件。

RouterOS中的大多数(可能是全部?)二进制文件似乎都是从头开始实现的,因此我们有数千行自定义的低级代码要去审计。

我们的目标是实现未经身份验证的远程代码执行,初看起来,FTP或Telnet等常见服务的二进制文件在没有提供凭据的情况下,无法提供太多可以访问的功能。这使得我们开始转向其他默认情况下可能未启用的服务,但需要实现丰富的功能集。默认情况下未启用这些服务,也就意味着它们可能会被其他攻击者忽略,因为这些攻击者可能希望最大限度地提升RouterOS上漏洞的ROI,希望发现的漏洞更有价值。

遵循上面的基本原理,通过检查一系列可用服务,我们将目标瞄准了SMB,准备看看SMB的实现。

五、发现漏洞

目前,我们已经设置好了虚拟机,掌握了正在运行的服务,对设备具有完全的Shell访问权限,并且可以调试任何进程。那么,我们如何找到漏洞呢?
一种选择是对二进制文件进行反汇编,并找到其中存在的不安全编码。我们将重点识别一些值得注意的操作,例如strcpy、memcpy等,并查看这些位置是否正确地进行了大小检查。然后,我们将查看是否可以通过用户控制的输入来访问这些代码路径,我们可以将其与动态分析相结合,并利用我们通过GDB连接到正在运行的进程的能力,从而在运行时、内存位置等方面来检查寄存器。但是,这一过程可能会非常耗时,如果我们没有充足的经验,在进行逆向分析时非常容易感到崩溃,特别是在分析大型二进制文件的时候。

另一个选择是,对网络服务进行模糊测试。具体而言,包括将特定数据发送至远程服务,并检查它是否导致意外行为或发生崩溃。这里的数据将包含格式错误的信息、无效的大小、非常长的字符串等。

进行模糊测试时,可以采用不同的方法。目前,有两种比较流行的策略,一种是基于生成的模糊测试,另一种是基于变异的模糊测试。前者需要预先具有一些知识,来构建符合协议规定格式的测试用例,并且(很可能)会导致全面的覆盖。更多的覆盖也就意味着有更多的机会命中存在漏洞的代码路径,当然也就更有可能发现漏洞。而后者无需实现具备模糊化的先验知识,可能具有较差的代码覆盖效果,特别是在需要计算校验值以确保数据完整性的协议中变得格外困难。

我们决定使用一个Dumb Fuzzer试试运气,我们选取了几个月前Cisco Talos团队发布的Mutiny Fuzzer工具。Mutiny根据合法网络流量采集样本,并使用变异模糊器对其重放。特别是,Mutiny使用Radamsa来对流量实现变异。

10.png

执行这种模糊测试的好处在于,可以非常快速的开始运行,并且正如我们所看到的那样,如果我们有一系列包含各种功能的测试用例,可能会产生非常好的结果。

综上所述,我们对网络服务进行模糊测试的步骤分为:

1. 捕获合法流量

2. 从生成的PCAP文件中创建Mutiny模糊器的模板

3. 运行Mutiny,对流量进行变异,并将其重放到服务

4. 观察正在运行的服务会出现什么异常

Mutiny确实提供了一个监控脚本,可以用于监控服务,并识别出其中的异常。这一过程可以通过实现monitorTarget函数来完成,在这里有所描述。样本检查的过程,可能会通过Ping远程服务器,或连接到远程服务以评估其可用性、监视进程、日志或者其他可能表现出异常的信号。

在实际案例中,SMB服务在崩溃后需要经过一段时间才能重新启动,并记录栈跟踪消息,因此我们认为,没有必要去编写任何监控操作的脚本。相反,我们刚刚使用了WireShark来捕获整个模糊过程中的流量,并依赖于Mutiny的默认行为,当因连接拒绝的错误而出现请求失败时会退出,这就意味着服务已经关闭。这是非常简陋的功能,具有很大的后续改进空间,但对于我们的测试来说,已经足够了。

在我们启动模糊测试过程之前,启用完整日志记录非常重要。这可能会对跟踪可能发生的崩溃来说非常有用,因为完整的栈跟踪将被记录在/rw/logs/backtrace.log日志中,可以在RouterOS的Web界面上进行配置。

11.png

另一件被证明非常有用的事,就是在交互式控制台中运行二进制文件,以实时获得调试输出。我们可以通过终止正在运行的进程,并从完全控制的终端重新启动进程来实现。这样一来,将会打印错误和已处理请求的常规状态。

12.png

现在,我们已经对过程中所涉及的步骤进行了完整的概述。接下来,我们回顾一下,并着手对SMB服务进行模糊测试。

首先,我们克隆mutiny-fuzzer,并按照说明进行操作。

13.png

我们计划的下一步,是生成一些网络流量。为此,我们打开WireShark,并尝试使用smbclient访问路由器上的资源。

14.png

Smbclient将向端口445/TCP发送协商协议请求,并收到响应(我们不关注响应)。这些通信,可以在WireShark中观察到。

15.png

我们希望使用此请求,来作为变异的起点。我们停止WireShark捕获,并保存所有请求数据包。具体的方法是:选择“File” – “Export Specified Packets”,并选择请求数据包,随后将会输出PCAP格式的文件。

16.png

一旦我们获得了包含模糊请求的PCAP,我们就可以使用mutiny_prep.py交互式脚本来生成Mutiny所需的.fuzzer文件。

17.png

我们最好事先检查一下生成的文件,以防止在转换过程中可能出现的任何异常情况。

18.png

在这里,我们可以将Mutiny配置为仅模糊消息中的一部分。如果我们想要将工作重点放在个别领域,这将是非常有用的。在实际案例中,我们要模糊整个消息。值得一提的是,Mutiny还可以处理多消息交换。

如果我们用作初始模板的测试用例中包含不会导致程序采用不同路径的部分,那么我们对该数据进行的所有修改,都不会增加代码覆盖率,这样会使模糊测试的效率变低。

我们观察到,该请求包含大约12个Requested Dialect的列表,其中每一个都对应于一组特定的支持命令。

提供一个或两个Dialect的较短列表,就可以使Radamsa创建出更有意义的变异,并发送出更多种类的SMB请求类型。改变一种Dialect不会使应用程序再耽搁消息对话中采用截然不同的路径,因此我们就按照这种方式编辑模板,如下所示:

outbound fuzz ‘\x00\x00\x00\xbe\xffSMBr\x00\x00\x00\x00\x18C\xc8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfe\xff\x00\x00\x00\x00\x00\x9b\x00\x02NT LANMAN 1.0\x00\x02NT LM 0.12\x00’

有了模板,就可以开始模糊测试了。过程中,要记得使用WireShark捕获完整的会话。Mutiny还可以记录发送的每个数据包,但我们发现当服务器在崩溃后停止响应时,会更容易查看WireShark。

我们使用devel帐户,打开与路由器的Telnet连接,并运行pkill smb; /nova/bin/smb,以启动新的SMB进程,并观察其输出。

下面的命令将指示Mutiny在两个数据包之间休眠半秒,并记录所有请求:

./mutiny.py -s 0.5 — logAll negotiate_protocol_request-0.fuzzer HOST

在得到的详细输出中,展示正在发送的不同大小的数据包,以及每个数据包的数字标识符。该值可以用于重复完全相同的变异序列,以提供复现崩溃的方法。这非常重要,因为即使我们发现了崩溃,以前的请求也可能已经损坏了某些内容,或者崩溃发生时更改了应用程序的状态。如果我们无法在崩溃之前重新创建状态,即使确定了哪个特定请求最终导致崩溃,最终也可能一无所获。

如果模糊测试的会话终端,并且我们不想重播之前的变异,那么可以使用-r参数指示Mutiny从这次循环开始发送变异(例如:-r 1500将发送变异1500、1501,以此类推)。

19.png

如果我们在模糊器运行过程中查看WireShark,将看到并非所有数据包都符合预期的格式,这对我们来说是件好事。当应用程序无法以正确的方式处理意外数据时,往往会出现漏洞。

20.png

我们运行SMB二进制文件的终端还包含有用的数据,从而确认我们实际上正在向该服务提供格式错误的请求。

21.png

现在,我们可以运行模糊器。通过使用不同的延迟值,能够证明服务器是否可以快速地处理请求,在本示例中,每秒2个请求是可以实现的。

几分钟后,Mutiny在尝试连接服务后,无法成功运行。

22.png

查看运行二进制文件的终端,我们看到一条段错误(Segmentation Fault)消息。

23.png

如前所述,backtrace.log文件中包含寄存器转储以及有关导致崩溃的更多信息。

24.png

最后,通过检查WireShark,我们可以看到发送到服务器的最后一个数据包被描述为“对非法NetBIOS名称的会话请求”。

25.png

在上文中,我们已经详细讲述了目标选择和漏洞发现的过程。在下篇中,将侧重于深入分析漏洞,并详细介绍漏洞利用的探索过程。

本文翻译自:https://medium.com/@maxi./finding-and-exploiting-cve-2018-7445-f3103f163cc1如若转载,请注明原文地址: https://www.4hou.com/vulnerable/16701.html
点赞 0
  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论