1. 漏洞概述:一个被忽视的“后门”
如果你负责过学校、园区或者大型工厂的安防广播系统,那你很可能接触过海康威视(或者说,其关联品牌“世邦通信”)的IP网络对讲广播系统。这套系统用起来确实方便,纯数字传输,一根网线就能把对讲和广播功能覆盖到每个角落,管理也都在网页后台完成。但就在2023年底,安全研究人员在这套系统的一个非常早期的版本(3.0.3_20201113_RELEASE)里,发现了一个堪称“致命”的漏洞,编号CVE-2023-6895。
这个漏洞简单来说,就是攻击者不需要任何用户名密码,只要他能访问到这套系统的管理页面,就能直接让服务器执行任意系统命令。想象一下,你公司的广播系统突然开始对外发送奇怪的声音,或者更糟糕,攻击者通过它窃取了服务器上所有的监控录像、人员名单,甚至用它作为跳板,攻击内网的其他核心服务器。这绝不是危言耸听,我见过太多因为这类物联网设备漏洞而引发的安全事件了。
问题的根源出在一个看似不起眼的功能上:网络诊断。系统有一个 /php/ping.php 的文件,本意是让管理员在网页上点点按钮,就能测试设备到某个IP地址的网络连通性(ping)或者路由追踪(traceroute)。这个功能本身没问题,但实现它的代码,却犯了一个安全开发中最低级的错误——直接将用户输入拼接到了系统命令中,而且没有做任何过滤和检查。
2. 漏洞原理深度拆解:代码里的“陷阱”
要真正理解这个漏洞为什么危险,我们不能停留在“有个命令执行漏洞”这句话上,得钻进代码里看看。网上公开的漏洞分析已经给出了关键代码片段,我这里结合我多年的代码审计经验,给你掰开揉碎了讲。
2.1 漏洞触发点:/php/ping.php
这个文件是整个漏洞的入口。它接收前端页面发来的POST请求,请求里包含一个叫 jsondata 的数组,里面有两个我们关心的参数:type 和 ip。
header("Content-type: text/html; charset=GB2312");
$postData = $_POST['jsondata'];
if(isset($postData['ip']) && isset($postData['type'])){
$type = $postData['type']; //类型
$ip = $postData['ip']; //IP地址
$arr = systemopr($type, $ip);
// ... 后续处理 ...
}
代码逻辑很清晰:检查参数是否存在,存在就传给一个叫 systemopr 的函数去处理。问题就出在这个 systemopr 函数里。
2.2 核心漏洞函数:systemopr()
这个函数是真正执行系统命令的地方。它的设计初衷是根据不同的 $type 值,执行不同的网络诊断命令。
function systemopr($type, $ip, $times=4){
$info = array();
if (PATH_SEPARATOR==':' || DIRECTORY_SEPARATOR=='/'){ //linux
if($type == "0"){
exec("ping -c $times $ip", $info);
}else if($type == "1"){
exec("traceroute -m $times -w 1 $ip", $info);
}else{
exec($ip, $info); // 危险!!!
}
}else{ //windows
if($type == "0"){
exec("ping $ip -n $times", $info);
}else if($type == "1"){
exec("tracert -h $times -w 1000 $ip", $info);
}else{
exec($ip, $info); // 危险!!!
}
}
return $info;
}
关键来了! 我们仔细看这个逻辑:
- 当
$type等于"0",它执行ping -c 4 用户输入的$ip。 - 当
$type等于"1",它执行traceroute -m 4 -w 1 用户输入的$ip。 - 当
$type不等于"0"或"1"时,它竟然直接执行exec($ip, $info);!
这意味着,攻击者只要把 type 参数设置为 "2"、"3"、"99" 或者任意非0非1的值,那么 $ip 参数的内容就会被原封不动地丢给 exec() 函数去执行。此时,$ip 不再是一个IP地址,而是一个可以完全由攻击者控制的操作系统命令</


1325

被折叠的 条评论
为什么被折叠?



