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

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

缺陷编号:wooyun-2013-024984

漏洞标题:PHPCMS最新版(V9)SQL注入一枚

相关厂商:phpcms

漏洞作者: blue

提交时间:2013-06-02 04:46

修复时间:2013-08-31 04:48

公开时间:2013-08-31 04:48

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

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

简要描述:

比较有意思的一个SQL注入点,代码分析是个体力活,唿~

详细说明:

存在于在线充值功能,直接上代码分析,建议先看漏洞证明:

/phpcms/phpcms/modules/pay/deposit.php 96行起的pay_recharge方法
...
$trade_sn = param::get_cookie('trade_sn'); //约110行位置,如果可以控制$trade_sn,即可注入,事实自然是可以的
$usernote = $_POST['info']['usernote'] ? $_POST['info']['name'].'['.$trade_sn.']'.'-'.new_html_special_chars(trim($_POST['info']['usernote'])) : $_POST['info']['name'].'['.$trade_sn.']';

$surplus = array(
'userid' => $this->_userid,
'username' => $this->_username,
'money' => trim(floatval($_POST['info']['price'])),
'quantity' => $_POST['quantity'] ? trim(intval($_POST['quantity'])) : 1,
'telephone' => preg_match('/[0-9\-]+/', $_POST['info']['telephone']) ? trim($_POST['info']['telephone']) : '',
'contactname' => $_POST['info']['name'] ? trim($_POST['info']['name']).L('recharge') : $this->_username.L('recharge'),
'email' => is_email($_POST['info']['email']) ? trim($_POST['info']['email']) : '',
'addtime' => SYS_TIME,
'ip' => ip(),
'pay_type' => 'recharge',
'pay_id' => $payment['pay_id'],
'payment' => trim($payment['pay_name']),
'ispay' => '1',
'usernote' => $usernote,
'trade_sn' => $trade_sn,
);
$recordid = $this->handle->set_record($surplus); //直到这里,也没有对$trade_sn进行处理吧?接下来看set_record方法
/phpcms/phpcms/modules/pay/classes/pay_deposit.class.php 12行起
/**
* 生成流水记录
* @param unknown_type
*/
public function set_record($data){
$require_items = array('userid','username','email','contactname','telephone','trade_sn','money','quantity','addtime','paytime','usernote','usernote','pay_type','pay_id','payment','ip','status');
if(is_array($data)) {
foreach($data as $key=>$item) {
if(in_array($key,$require_items)) $info[$key] = $item;
}
} else {
return false;
}
$trade_exist = $this->account_db->get_one(array('trade_sn'=>$info['trade_sn'])); //这里
if($trade_exist) return $trade_exist['id'];
$this->account_db->insert($info); //还有这里
return $this->account_db->insert_id();
}


好了,关键是控制$trade_sn的值,看param::get_cookie和param::set_cookie方法

/phpcms/phpcms/libs/classes/param.class.php
public static function set_cookie($var, $value = '', $time = 0) {
$time = $time > 0 ? $time : ($value == '' ? SYS_TIME - 3600 : 0);
$s = $_SERVER['SERVER_PORT'] == '443' ? 1 : 0;
$var = pc_base::load_config('system','cookie_pre').$var;
$_COOKIE[$var] = $value;
if (is_array($value)) {
foreach($value as $k=>$v) {
setcookie($var.'['.$k.']', sys_auth($v, 'ENCODE'), $time, pc_base::load_config('system','cookie_path'), pc_base::load_config('system','cookie_domain'), $s);
}
} else {
setcookie($var, sys_auth($value, 'ENCODE'), $time, pc_base::load_config('system','cookie_path'), pc_base::load_config('system','cookie_domain'), $s); //cookie加密了,而且方法很给力,sys_auth是有auth_key的,基本上可以说破解这个值不容易
}
}
......
public static function get_cookie($var, $default = '') {
$var = pc_base::load_config('system','cookie_pre').$var;
return isset($_COOKIE[$var]) ? sys_auth($_COOKIE[$var], 'DECODE') : $default; //这里是解密方法,咱也用不上
}


1.png


看来想自己更改cookie值很难,不知道加密的auth_key值嘛,可是...如果利用一个能set_cookie($value)的点,并且咱们能控制$value呐?这个点自然是有的~

/phpcms/phpcms/modules/attachment/attachments.php 228行起
public function swfupload_json() {
$arr['aid'] = intval($_GET['aid']); //这个不行,intval了
$arr['src'] = trim($_GET['src']); //这个可以,虽然$_GET会addslashes,但下面的json_encode会帮上忙(此时' => \',这里是一个反斜线 )
$arr['filename'] = urlencode($_GET['filename']); //这个不行,urlencode了
$json_str = json_encode($arr); (此时 \' => \\' 这里是两个反斜线)所以单引号可以用了
$att_arr_exist = param::get_cookie('att_json');
$att_arr_exist_tmp = explode('||', $att_arr_exist);
if(is_array($att_arr_exist_tmp) && in_array($json_str, $att_arr_exist_tmp)) {
return true;
} else {
$json_str = $att_arr_exist ? $att_arr_exist.'||'.$json_str : $json_str;
param::set_cookie('att_json',$json_str); //这里
return true;
}
}

漏洞证明:

1.在COOKIE att_json为空时(当然可以手动清空),访问以下链接生成att_json
http://localhost/test/phpcms/index.php?m=attachment&c=attachments&a=swfupload_json&src=1%27&filename=a%27 (当然,你可以干点别的)
2.提交在线充值时,更改COOKIE trade_sn为att_json的值

2.png


3.png


修复方案:

对$trade_sn进行addslashes

版权声明:转载请注明来源 blue@乌云


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:15

确认时间:2013-06-03 16:52

厂商回复:

感谢反馈!

最新状态:

2013-06-03:@blue请提供下联系方式,或者联系我们网站在线客服!我们确认身份后,赠送您精美礼品!