漏洞挖掘从黑盒到白盒

admin 2026-06-14 04:33:56 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 文档分析某设备固件漏洞挖掘过程,发现多个命令注入漏洞。核心问题包括:1)xxxxxxxcmd.php文件存在无回显命令注入,通过socket传递ECMD指令触发system执行;2)时区设置功能TSE参数未过滤直接拼接进system命令;3)用户创建功能存在命令注入但需鉴权绕过配合利用。漏洞涉及2.x/3.x版本差异,提供具体代码分析和复现方法。 综合评分: 85 文章分类: 漏洞分析,代码审计,WEB安全,渗透测试,红队


cover_image

漏洞挖掘从黑盒到白盒

只会看监控的实习生

2026年6月13日 08:00 广东

在小说阅读器读本章

去阅读

因为在检索关键字的时候,发现虽然system函数在php代码里出现的很频繁,但是实际上可控的几乎没有,但是在最新版固件里发现了一个奇葩的东西,问题存放在xxxxxxxcmd.php文件里

在2.x和1.x版本中,这块是没有下面的exec()的,这也导致了更新后,反而这块出现了一个新的问题

所以这块复现也非常的简单粗暴,因为这个接口实际上还存在一个有回显的命令注入,但是这一处是没有回显的,所以需要把输出结果打印出来,方便我们进行查看

而后直接访问是否有东西输出出来,发现也是真实存在的

刚刚有提到过,除了这一处,其实还存在一个命令注入,这里是一接口双注入

跟踪代码xxxxxxxcmd.php可以看见,通过前端传入xxxxxug_cmd参数后,连接本地socket服务,利用eachMsg(“ECMD$DBGCMD”)进行消息传送而后执行

查看socket.php发现,eachMsg仅用来socket消息传递,里面并没有核心实现

所以其实还是要看二进制文件xxxxxonitor

继续追踪代码

核心代码如下

if&nbsp;( !strncmp(s_1,&nbsp;"ECMD",&nbsp;4uLL) ) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;strcpy((char *)s_5,&nbsp;"/usr/local/apache/htdocs/ExecCmd.txt"); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sub_423458(6LL,&nbsp;"recv commond(%s)", s_1); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;strcpy(s_3,&nbsp;"ECMDCB"); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if&nbsp;( sendto(fd, s_3,&nbsp;6uLL,&nbsp;0, (const&nbsp;struct sockaddr *)&addr_,&nbsp;0x10u) <&nbsp;0&nbsp;) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;v200 = sub_421704(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sub_423458(4LL,&nbsp;"send data to %s failed,ErrCode = %d!", s_2, v200); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;memset(s_4,&nbsp;0,&nbsp;0x800uLL); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if&nbsp;( !strncmp(&src__2,&nbsp;"cd",&nbsp;2uLL) ) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;n32 = src__3; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;path = (const&nbsp;char *)&src__3; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;do&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if&nbsp;( n32 !=&nbsp;32&nbsp;) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;n32_1 = *(unsigned __int8 *)++path; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;n32 = n32_1; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;while&nbsp;( n32_1 ); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if&nbsp;( chdir(path) == -1&nbsp;) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;nptrh = *__errno_location(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;v216 = strerror(nptrh); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sprintf( &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(char *)s_4, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;"nohup echo \"change current work dir failed(errno(%d): %s)\" > %s 2>&1 &", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;nptrh, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;v216, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(const&nbsp;char *)s_5); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;else&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sprintf((char *)s_4,&nbsp;"nohup echo \"change current work dir succeed\" > %s 2>&1 &", (const&nbsp;char *)s_5); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;system((const&nbsp;char *)s_4); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;else&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sprintf((char *)s_4,&nbsp;"nohup %s > %s 2>&1 &", &src__2, (const&nbsp;char *)s_5); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;system((const&nbsp;char *)s_4); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}

首先 !strncmp(s_1, “ECMD”, 4uLL)检查s_1的前4字节是否是”ECMD”,此处对应eachMsg(“ECMD$DBGCMD”),因为传入的是ECMD,所以会进入到后面的条件分支

此时发现进入后续判断 !strncmp(&src__2, “cd”, 2uLL),判断传入的参数是不是cd指令,当输入的不是cd指令的时候,就会执行sprintf((char *)s_4, “nohup %s > %s 2>&1 &”, &src__2, (const char *)s_5);

假设传入的参数为ls指令,那么指令构造为 nohup ls > ExecCmd.txt 2>&1 & ,而后将此指令存储在s_4变量后,经过system((const char *)s_4)执行,因此造成此处的命令执行漏洞

可以看到,这里也是利用

strcpy((char *)s_5, “/usr/local/apache/htdocs/ExecCmd.txt”);

进行写入,将执行结果最终写入到ExecCmd.txt里面,实现命令回显

查看执行结果,也是如愿所偿的执行成功了

继续挖掘,我们发现,在一个设置时令的功能里,出现了如下的代码

直接去ida里看一下对应的位置

核心代码如下

if&nbsp;( !strncmp(s_1,&nbsp;"TSE",&nbsp;3uLL) ) &nbsp; &nbsp; &nbsp; &nbsp;{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sub_423458(6LL,&nbsp;"recv commond(%s)", s_1); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;s_4[0] =&nbsp;0LL; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;strcpy((char *)s_4, &src__2); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sprintf(s_6,&nbsp;"/root/timezone.shell %s &", (const&nbsp;char *)s_4); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;system(s_6);

后端传入”TSE:$TIMEZONE” 后,进入此步骤,而后将s_6 赋值为“/root/timezone.shell TIMEZONE &”,最后经过system(s_6);执行

/root/timezone.shell文件内容没什么东西,与本次漏洞无关,就不展示了,其实这个接口还有一个位置也存在这个问题,但是因为漏洞原理是一样的,所以不进行展示

然后查看执行效果

后续在审计的时候,发现了一个比较有意思的现象,在2.x和3.x固件版本中,系统在创建用户的时候,调用了一个不应该出现的代码

调用了一下系统的另一个用来创建用户的二进制文件,也就是说,创建用户和密码这块居然存在命令注入漏洞,只不过在3.x版本,这个接口做了鉴权,但是可以配合认证绕过和其他没鉴权的RCE去读密码然后解密,然后正常模拟登录拿到cookie后来执行

因为主要针对的还是认证的绕过以及密码的获取、命令的执行,所以以上就是这个设备主要的问题了

首发:https://forum.butian.net/share/4569


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:只会看监控的实习生 《漏洞挖掘从黑盒到白盒》

    评论:0   参与:  0