前言
实际上goahead是个漏洞高发区,学习一下有很多好处
只搞到了D-Link DIR-823G v1.02 B03
没有搞到D-Link DIR-823G v1.02 B05的固件,不过大差不差
漏洞详情
固件解包
惯例binwalk
可以看到有个Squashfs文件系统,漏洞存在于web文件夹内:
开放服务情况
查看/etc/init.d/rcS
watchdog应该是一种进程的监控程序,启动1000秒
紧接着,启动了goahead,是一种嵌入式设备使用的web服务器
使用find等方法,找到squashfs-root/bin/下的goahead文件,这就是负责网络服务的文件,已经被编译为bin文件了
固件分析
main
首先看main部分
重点关注方法423F90,
(下次可以关注一下if 方法<0 则return -1 的方法,这其实一般是比较关键的部分)
sub_423F90
以上其实并不是很重要,仅仅是一些用户管理的操作,在没有用户的时候会添加一个账户密码为admin:1234的账户,可以看出这其实也是没有什么安全意识的做法
实际上,41BC40也是通往system函数的,后面可以看看,但存在漏洞的其实是:
这里有对不同的请求类别(Handler,cgi等)进行处理的函数
在此之前先了解一下goahead的开发文档https://www.embedthis.com/goahead/doc/users/routing.html
HNAP实际上是代表这个
实际上,跟类似的goahead项目是类似的,可以去参考源代码(即使是废弃的部分),比如https://github.com/AcceleratedLinux/accelerated-linux/blob/e7dd913826d9c00e658c520ff81fe11e0042b87e/user/goahead/src/.%23goahead.c.1.120#L455
sub_40B1F4其实是websUrlHandlerDefine这个东西,
那么,可以参考一下websUrlHandlerDefine的源代码,看看是怎么对web的url的句柄进行define的,链接在https://github.com/AcceleratedLinux/accelerated-linux/blob/e7dd913826d9c00e658c520ff81fe11e0042b87e/user/goahead/src/handler.c#L84
//暂且看前四个参数,就能明白了,第一个是urlPrefix,第二个是webDir,第三个是arg,第四个是一个int格式的handler指针,也就是指向某个执行的函数
int websUrlHandlerDefine(char_t *urlPrefix, char_t *webDir, int arg,
int (*handler)(webs_t wp, char_t *urlPrefix, char_t *webdir, int arg,
char_t *url, char_t *path, char_t *query), int flags)
{
websUrlHandlerType *sp;
int len;
a_assert(urlPrefix);
a_assert(handler);
/*
* Grow the URL handler array to create a new slot
*/
len = (websUrlHandlerMax + 1) * sizeof(websUrlHandlerType);
if ((websUrlHandler = brealloc(B_L, websUrlHandler, len)) == NULL) {
return -1;
}
sp = &websUrlHandler[websUrlHandlerMax++];
memset(sp, 0, sizeof(websUrlHandlerType));
sp->urlPrefix = bstrdup(B_L, urlPrefix);
sp->len = gstrlen(sp->urlPrefix);
if (webDir) {
sp->webDir = bstrdup(B_L, webDir);
} else {
sp->webDir = bstrdup(B_L, T(""));
}
sp->handler = handler;
sp->arg = arg;
sp->flags = flags;
/*
* Sort in decreasing URL length order observing the flags for first and last
*/
qsort(websUrlHandler, websUrlHandlerMax, sizeof(websUrlHandlerType),
websUrlHandlerSort);
return 0;
}
事实上,直接从IDA读sub_40B1F4源代码,我不是很能看懂,但这样对比着看,就明白了两件事:
那个sub_40B1F4其实就是websUrlHandlerDefine
然后它定义了一个句柄(handler),具体功能就是只要用户访问HNAP1,然后post数据,就会被后面那个sub_42383c处理,按第七个参数(上文的query)传入
OK!搞清楚以后,跟进sub_42383C,这个函数第七个参数a7就是用户可控的
sub_42383C
这部分是作者自己实现的一个句柄处理函数,我猜测在源码里的命名类似于:websHNAP1Handler,有机会可以找找类似源码,当然这不重要,我们记住第七个参数a7是可控点即可
其实还是很好看懂的,首先是定义了一个包含header头的字符串,暂且称呼其为web_request
当然,这并么有什么问题
但是这里:
使用snprintf格式化字符串的%s,把a7赋值给 web_request的27位置 ,但是,这个赋值是没有任何过滤的
那么,如果使用单引号闭合,然后使用“把我们需要执行的东西括起来,就等于命令注入了,这就是这个漏洞的原理
rce复现
payload构造
对于echo ‘%s’ >/var/hnaplog
可以post数据如下,单引号’用于闭合,`反引号则用于命令执行
‘`echo 114514>/web_mtn/abc.txt`’
手工构造即可
拓展
搜索了一下goahead造成的惨案,实在太多了
后记
作为第一个复现的漏洞,发现当时的自己并没有彻底搞懂,后面经由朋友一起学习的时候,发现自己并没有彻底搞懂,现在才算搞懂了
话说,这种asp的其实没有符号的话分析起来会有些烦,因为一般的漏洞,都是走xxx_asp这样的函数,这样我们就能知晓漏洞点在哪,没有符号就巨烦了
幸好这个比较特殊,HNAP1定义在鉴权部分的句柄里,所以免去了这种烦恼,实在不行可以动态调试起来