首页
社区
课程
招聘
[原创] CNVD-2018-01084 漏洞复现报告(service.cgi 远程命令执行漏洞)
发表于: 2022-4-7 15:38 19862

[原创] CNVD-2018-01084 漏洞复现报告(service.cgi 远程命令执行漏洞)

2022-4-7 15:38
19862

CNVD平台上,关于CNVD-2018-01084的详细信息:D-Link DIR 615/645/815 service.cgi远程命令执行漏洞

固件包下载地址:D-Link (Downloads)

笔者复现的环境是Ubuntu 20.04

阅读本文前,请先安装qemu / binwalk / sasquatch / gdb-multiarch等工具,并对mips架构下的汇编语法有一定的了解。

官方公告:

先用binwalk -Me DIR815A1_FW102b06.bin命令解压固件包,再根据“漏洞描述”中的关键词service.cgi进行查找:

找到了所匹配的二进制文件htdocs/cgibin,将其拖进IDA中先进行静态分析。

首先进入main函数,很容易找到关键词service.cgi

这里是和传入的第一个参数v3进行的判断:

然后,当传入的第一个参数是service.cgi,比对成功后,会进入servicecgi_main函数。

我们先对servicecgi_main这个函数整体的调用路线进行一个宏观的分析:

我们猜测漏洞点存在于这里的system函数处,它是由lxmldbc_system函数调用的:

lxmldbc_system函数中,会先进行一个格式化字符串的拼接,再将拼接好的字符串作为system的参数调用,因此,这里的确可能存在一个可被利用的点:

接着,我们对servicecgi_main函数的流程进行一个分析:

(1)先获取环境变量REQUEST_METHOD进行判断

当请求方式为GET的时候,会跳到标签10,而这个标签10在调用lxmldbc_system函数的下面:

所以,为了利用到lxmldbc_system中的漏洞,我们的请求方式只能为POST

(2)分析cgibin_parse_request函数

然后,会调用到cgibin_parse_request函数,这个函数会先调取环境变量REQUEST_URI,并对其先以?进行字符串分割:

再进到sub_402B40函数中,发现这里会再以=进行一次字符串分割,对=后的内容再以&进行分割:

这其实就是对一个URL字符串的解析过程,分割后的字符串,都会被存放进内存中,具体存放在哪里,不太好直接通过静态分析看出。

之后,在cgibin_parse_request函数中,对CONTENT_TYPE这个环境变量进行了一个判断:

这里先对环境变量CONTENT_TYPE中的内容的前v17位与v18进行一个比对,比对正确后就会调用一个未知的函数,这里的v18其实是off_42C014中的内容,而v17就是其后四个字节的内容:

也就是说,我们CONTENT_TYPE的前12位得是application/才能过这个判断。

之后调用到的那个未知的函数也不方便直接通过静态分析看出,在之后动态调试的时候可以很清楚地看到,不过,这里需要注意一下传入这个未知函数的第三个参数v7,其实就是CONTENT_LENGTH这个环境变量:

这个函数大体就分析到这里了,更具体的,在之后动态分析的时候会写到。

servicecgi_main主函数中可以看到,若cgibin_parse_request函数的返回值是负数的话,会报错。

笔者注:

之前复现的时候是直接看汇编的,感觉上面说的未知函数不好看出来(我太菜了),其实我们看反编译后的代码,直接静态分析就很容易得出来:如果CONTENT_TYPE的前12位是application/,那么此时v16=1,所以(&off_42C014)[3 * v16 - 1] = (&off_42C014)[2],也就是下图圈出的数据,即跳转到了0x403B10处。

(3)分析sess_ispoweruser函数

在之后,会需要绕过sess_ispoweruser函数,不然无法通过认证:

这个函数会调用到sess_validate函数,其中会再调用到sess_get_uid函数,在里面有对HTTP_COOKIEREMOTE_ADDR这两个环境变量的获取,这里就不作具体分析了。

接着,在sess_validate函数中会继续调用到sub_407660这个函数,其中会打开/var/session/...的文件:

这个文件显然我们用qemu模拟的环境中是没有的,因此我们需要将sess_ispoweruser这个函数的相关判断给patch(直接将跳转命令改成nop空指令),不然就不便于进行后续利用了(会在这里卡住):

修改:

完成:

保存:

这样就直接跳过sess_ispoweruser函数的认证检验了,patch过的二进制文件替换htdocs目录下原有的文件即可

(4)一些静态分析看不出来的操作

再然后,会调用sub_40A1C0函数进行一些判断:

显然,判断的结果若是满足v6!=0是最好的,因为这里if分支其实大体上都是对v9格式化字符串进行赋值,而v6!=0分支中的内容最简单,下面else分支中的内容会很复杂,当经过这个判断之后,有了v9这个格式化字符串作为参数,就可以直接走到lxmldbc_system函数进行漏洞利用了。

不过,这里sub_40A1C0函数中具体判断的内容不太好直接通过静态分析看出:

这里的a1就是传进去的EVENT / ACTION / SERVICE这些参数,但是后面的v3[2]应该是用户可控的一个字符串,但是并不知道指向内存的何处。

同样地,lxmldbc_system函数中,vsnprintf函数的参数va(也就是拼接到前面format格式化字符串中的内容)不知道指向内存的何处,va_start函数同样不知道指向哪里:

这些都不好通过静态分析直接得出,但是可以猜测都是用户可控的,再联想到之前的REQUEST_URI环境变量分割出的字符串被存放在了内存中,我们也并不知道具体的存放位置,因此,可以猜测这里取的内存就是在之前存放的,为了验证这一观点,我们需要进行动态分析来调试。

checksec检查一下二进制文件:

这是一个mips架构下32位的小端序程序,得用qemu-mipsel启动,没开任何保护。

首先,我们需要知道如何向main函数传递参数argv和设置环境变量:

我们可以用-0选项传递第一个参数,用-E选项设置环境变量,用-L选项做到类似于更改根目录的效果,用-strace选项追踪程序执行时进程系统调用和所接收的信号,方便调试。

我们按顺序,先来调试一下CONTENT_TYPE环境变量中application/后应该设置成什么,也就需要知道这里进入的未知函数是什么:

看到对应的汇编:

最后的跳转命令在0x40346C处,因此,我们在这里下一个断点。

先用下面的命令启动qemu用户模式:

再用gdb-multiarch设置架构并连接上1234端口,最后停在了断点处:

可以很清晰地看到,那个我们静态分析不好看出来的未知函数就是0x403b10

IDA里找到0x403b10的位置,并创建函数,方便反编译:

可见,CONTENT_TYPE环境变量的后面应该是x-www-form-urlencoded,匹配成功后,就会进入sub_402FFC函数,在其中会有一个read函数,需要我们读入数据:

这里的v7也就是a3,是我们在cgibin_parse_request函数中传入的环境变量CONTENT_LENGTH,根据之前的分析,我们需要这个函数的返回值v4大于零,只要读入合法的数据即可。

这一部分就分析到这,接下来再验证之前的猜想:sub_40A1C0函数中所取的内存是否为之前REQUEST_URI环境变量所分割出的字符串?

我们已经知道了REQUEST_URI大体的分割模式,因此可以设REQUEST_URI="aaa?bbb=ccc"的形式,启动命令如下:

sub_40A1C0strcmp的地方对应的汇编处(0x40A200)下一个断点:

在之前随便输入十个字符,最后停止了断点处:

由此可知,strcmp的第二个参数就是环境变量REQUEST_URI?=之间的字符串

用同样的方法,可以得到:lxmldbc_system中拼接入格式化字符串的va参数就是环境变量REQUEST_URI=之后的字符串

至此,我们完成了对/htdocs/cgibin这个二进制文件中的漏洞分析,显然,我们将;{cmd};拼接进格式化字符串,由于;可连接两个独立语句并执行,这样就能执行我们的cmd命令了

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2022-4-7 17:25 被winmt编辑 ,原因:
收藏
免费 10
支持
分享
打赏 + 150.00雪花
打赏次数 1 雪花 + 150.00
 
赞赏  Editor   +150.00 2022/05/23 恭喜您获得“雪花”奖励,安全圈有你而精彩!
最新回复 (1)
雪    币: 214
活跃值: (147)
能力值: ( LV3,RANK:35 )
在线值:
发帖
回帖
粉丝
2
学习一下
2022-4-7 21:45
0
游客
登录 | 注册 方可回帖
返回
//