CVE-2019-13954 之MikroTik RouterOS memory exhaustion
字数 1410 2025-08-27 12:33:54

MikroTik RouterOS CVE-2019-13954内存耗尽漏洞分析与复现指南

1. 漏洞概述

CVE-2019-13954是MikroTik RouterOS中存在的一个内存耗尽漏洞。该漏洞允许经过认证的用户通过构造特殊的POST请求,使服务程序陷入死循环,导致内存耗尽,最终使服务程序崩溃或系统重启。

受影响版本

  • 漏洞存在于6.42.11及更早版本
  • 在6.42.11之后的版本中已修复

2. 漏洞原理分析

漏洞位置

漏洞位于/jsproxy/upload接口的处理函数JSProxyServlet::doUpload中。

漏洞代码分析

补丁前版本(6.40.5):

int __cdecl JSProxyServlet::doUpload(int a1, int a2, Headers* a3, Headers* a4)
{
    //...
    while (1) {
        sub_77464E9F(v27, (char*)s1); // 读取POST请求数据
        if (!LOBYTE(s1[0])) break;
        string::string((string*)&v36, (const char*)s1);
        v11 = Headers::parseHeaderLine((Headers*)&v37, (const string*)&v36);
        string::freeptr((string*)&v36);
        if (!v11) {
            string::string((string*)&v36, "");
            Response::sendError(a4, 400, (const string*)&v36);
            string::freeptr((string*)&v36);
            LABEL_56:
            tree_base::clear(v13, v12, &v37, map_node_destr<string, HeaderField>);
            goto LABEL_57;
        }
    }
    //...
}

补丁后版本(6.42.11):

int __cdecl JSProxyServlet::doUpload(int a1, int a2, Headers* a3, Headers* a4)
{
    //...
    while (1) {
        sub_51F7(v37, &s1); //读取POST请求
        if (!s1) break;
        v14 = -1;
        v15 = &s1;
        do {
            if (!v14) break;
            v16 = *v15++ == 0;
            --v14;
        } while (!v16);
        if (v14 != 0x100u) //数据长度限制
        {
            v36 = 0;
            string::string((string*)&v46, &s1);
            v17 = Headers::parseHeaderLine((Headers*)&v47, (const string*)&v46);
            string::freeptr((string*)&v46);
            if (v17) continue;
        }
        string::string((string*)&v46, "");
        Response::sendError(a4, 400, (const string*)&v46);
        string::freeptr((string*)&v46);
        LABEL_60:
        tree_base::clear(v19, v18, &v47, map_node_destr<string, HeaderField>);
        goto LABEL_61;
    }
    //...
}

漏洞触发条件

  1. 调用sub_51F7函数读取POST数据时未读取到有效数据
  2. 调用Headers::parseHeaderLine()解析失败

漏洞利用方法

在补丁后版本中,虽然增加了对数据长度的检查(超过0x100字节会退出循环),但可以通过在payload中插入多个\x00字符来绕过这个检查:

  • 单个\x00会被getline识别为终止符
  • 多个\x00会被识别为\\字符,不会终止读取
  • 这样既能绕过长度检查,又能保持数组大小超过0x100

3. 漏洞复现环境搭建

所需工具

  1. MikroTik RouterOS 6.42.11镜像
  2. Ubuntu虚拟机
  3. busybox和gdbserver.i686
  4. Chimay-Red工具(用于提取固件文件)
  5. PoC代码(来自Tenable)

环境搭建步骤

1. 安装RouterOS

  1. 从MikroTik官网下载6.42.11版本镜像
  2. 使用VMware创建虚拟机并安装RouterOS
  3. 安装时按'a'选择所有组件,然后按'i'安装,后续选项默认'y'

2. 网络配置

  1. 将RouterOS虚拟机设置为NAT模式
  2. 在RouterOS中获取IP地址:
    ip dhcp-client add interface=ether disabled=no
    ip dhcp-client print detail
    

3. 获取完整shell

  1. 下载busybox和gdbserver.i686
  2. 关闭RouterOS,在VMware中添加其磁盘到Ubuntu虚拟机
  3. 挂载RouterOS磁盘并将busybox和gdbserver复制到/rw/disk
  4. 创建/rw/DEFCONF脚本开启telnet后门:
    ok; /rw/disk/busybox-i686 telnetd -l /bin/bash -p 1270;
    
  5. 通过telnet连接RouterOS:
    telnet <routeros_ip> 1270
    

4. 获取漏洞相关文件

  1. 使用find命令定位wwwjsproxy.p
    find / -name www
    find / -name jsproxy.p
    
  2. 或使用Chimay-Red工具从官网提取:
    ./tools/getROSbin.py 6.42.11 x86 /nova/bin/www www_binary_1
    ./tools/getROSbin.py 6.42.11 x86 /nova/lib/www/jsproxy.p www_binary_2
    

4. 漏洞复现步骤

1. 编译PoC

  1. 从Tenable获取PoC代码
  2. 安装依赖:
    sudo apt-get install libboost-dev cmake
    
  3. 确保gcc版本高于6
  4. 编译PoC:
    cd cve_2019_13954
    mkdir build
    cd build
    cmake ..
    make
    

2. 运行PoC

./cve_2019_13954_poc -i <routeros_ip> -u admin

3. 调试验证

  1. 关闭ASLR(方便调试):
    sudo sh -c "echo 0 > /proc/sys/kernel/randomize_va_space"
    
  2. 在RouterOS上附加gdbserver到www进程:
    ./gdbserver.i686 localhost:1234 --attach <www_pid>
    
  3. 在Ubuntu上使用gdb连接:
    gdb
    set architecture i386
    target remote <routeros_ip>:1234
    
  4. 设置断点(需要计算jsproxy基地址+函数偏移):
    b *0x774f9000+0x8D08
    
  5. 运行PoC观察系统行为

5. 漏洞修复建议

  1. 升级到最新版本的RouterOS
  2. 如果无法立即升级,可以限制对/jsproxy/upload接口的访问

6. 参考资源

  1. CVE-2018-1158分析
  2. Finding and Exploiting CVE-2018-7445
  3. Tenable Techblog on MikroTik
  4. POCs and Slides
  5. Bug Hunting in RouterOS
MikroTik RouterOS CVE-2019-13954内存耗尽漏洞分析与复现指南 1. 漏洞概述 CVE-2019-13954是MikroTik RouterOS中存在的一个内存耗尽漏洞。该漏洞允许经过认证的用户通过构造特殊的POST请求,使服务程序陷入死循环,导致内存耗尽,最终使服务程序崩溃或系统重启。 受影响版本 漏洞存在于6.42.11及更早版本 在6.42.11之后的版本中已修复 2. 漏洞原理分析 漏洞位置 漏洞位于 /jsproxy/upload 接口的处理函数 JSProxyServlet::doUpload 中。 漏洞代码分析 补丁前版本(6.40.5): 补丁后版本(6.42.11): 漏洞触发条件 调用 sub_51F7 函数读取POST数据时未读取到有效数据 调用 Headers::parseHeaderLine() 解析失败 漏洞利用方法 在补丁后版本中,虽然增加了对数据长度的检查(超过0x100字节会退出循环),但可以通过在payload中插入多个 \x00 字符来绕过这个检查: 单个 \x00 会被getline识别为终止符 多个 \x00 会被识别为 \\ 字符,不会终止读取 这样既能绕过长度检查,又能保持数组大小超过0x100 3. 漏洞复现环境搭建 所需工具 MikroTik RouterOS 6.42.11镜像 Ubuntu虚拟机 busybox和gdbserver.i686 Chimay-Red工具(用于提取固件文件) PoC代码(来自Tenable) 环境搭建步骤 1. 安装RouterOS 从MikroTik官网下载6.42.11版本镜像 使用VMware创建虚拟机并安装RouterOS 安装时按'a'选择所有组件,然后按'i'安装,后续选项默认'y' 2. 网络配置 将RouterOS虚拟机设置为NAT模式 在RouterOS中获取IP地址: 3. 获取完整shell 下载busybox和gdbserver.i686 关闭RouterOS,在VMware中添加其磁盘到Ubuntu虚拟机 挂载RouterOS磁盘并将busybox和gdbserver复制到 /rw/disk 创建 /rw/DEFCONF 脚本开启telnet后门: 通过telnet连接RouterOS: 4. 获取漏洞相关文件 使用find命令定位 www 和 jsproxy.p : 或使用Chimay-Red工具从官网提取: 4. 漏洞复现步骤 1. 编译PoC 从Tenable获取PoC代码 安装依赖: 确保gcc版本高于6 编译PoC: 2. 运行PoC 3. 调试验证 关闭ASLR(方便调试): 在RouterOS上附加gdbserver到www进程: 在Ubuntu上使用gdb连接: 设置断点(需要计算jsproxy基地址+函数偏移): 运行PoC观察系统行为 5. 漏洞修复建议 升级到最新版本的RouterOS 如果无法立即升级,可以限制对 /jsproxy/upload 接口的访问 6. 参考资源 CVE-2018-1158分析 Finding and Exploiting CVE-2018-7445 Tenable Techblog on MikroTik POCs and Slides Bug Hunting in RouterOS