微擎微赞系统BUG漏洞解决方法汇总
弄了微擎系统来玩玩,发觉这个系统BUG还不少,阿里云的提醒都一大堆,主要是没有针对SQL注入做预防,处理的办法基本都是用转义函数。
汇总:
1、
漏洞名称:
微擎任意文件下载
漏洞文件路径:/framework/function/global.func.php
解决方法:
修复方法: 打开/framework/function/global.func.php文件 搜索 if (strexists($t, 'http://') 复制代码 找到 if (strexists($t, 'http://') || strexists($t, 'https://') || substr($t, 0, 2) == '//') { return $src; } 复制代码 替换为 if((substr($t, 0, 7) == 'http://')||(substr($t, 0, 8) == 'https://')||(substr($t, 0, 2) == '//')){ return $src; } 复制代码 搞定 保存文件,上传到服务器,去安骑士上验证一下就过了。
2、
漏洞名称:
微擎SQL注入漏洞
漏洞描述:
微擎的/web/source/mc/fans.ctrl.php中,对$_GPC['nickname']未进行SQL转义就带入数据库查询中,导致SQL注入的发生。
解决方法:
漏洞在web/source/mc/fans.ctrl.php,修复方法(代码在148行左右) 搜索 $nickname = trim($_GPC['nickname']); 修改为 $nickname = addslashes(trim($_GPC['nickname']));
3、
漏洞名称:
微擎文件编辑SQL注入
漏洞描述:
微擎的/web/source/site/article.ctrl.php中对$_GPC['template']、$_GPC['title']、$_GPC['description']、$_GPC['source']、$_GPC['author']参数未进行正确转义过滤,导致SQL注入的产生。
解决方法:
搜索代码 message(‘标题不能为空,请输入标题!‘); 如下图:
在 82 行 前添加代码
- mysql_set_charset("gbk");
- $_GPC[‘template‘] = mysql_real_escape_string($_GPC[‘template‘]);
- $_GPC[‘title‘] = mysql_real_escape_string($_GPC[‘title‘]);
- $_GPC[‘description‘] = mysql_real_escape_string($_GPC[‘description‘]);
- $_GPC[‘source‘] = mysql_real_escape_string($_GPC[‘source‘]);
- $_GPC[‘author‘] = mysql_real_escape_string($_GPC[‘author‘]);
修改后如图:
4、
漏洞名称:
微擎SQL注入漏洞
漏洞描述:
微擎CMS的/web/source/paycenter/wxmicro.ctrl.php中,对$post['member']['uid']输入参数未进行严格类型转义,导致SQL注入的发生
解决方法:
红色部分为新增和修改的
<?php /** * [WeEngine System] Copyright (c) 2014 WE7.CC * WeEngine is NOT a free software, it under the license terms, visited http://www.we7.cc/ for more details. */ defined('IN_IA') or exit('Access Denied'); uni_user_permission_check('paycenter_wxmicro_pay'); $_W['page']['title'] = '刷卡支付-微信收款'; $dos = array('pay', 'query', 'checkpay'); $do = in_array($do, $dos) ? $do : 'pay'; load()->model('paycenter'); if($do == 'pay') { if($_W['isajax']) { $post = $_GPC['__input']; $fee = trim($post['fee']) ? trim($post['fee']) : message(error(-1, '订单金额不能为空'), '', 'ajax'); $body = trim($post['body']) ? trim($post['body']) : message(error(-1, '商品名称不能为空'), '', 'ajax'); $code = trim($post['code']); $uid = intval($post['member']['uid']); if($post['cash'] > 0 && empty($post['code'])) { message(error(-1, '授权码不能为空'), '', 'ajax'); } $total = $money = floatval($post['fee']); if(!$total) { message(error(-1, '消费金额不能为空'), '', 'ajax'); } $log = "系统日志:会员消费【{$total}】元"; if($uid > 0) { $user = pdo_get('mc_members', array('uniacid' => $_W['uniacid'], 'uid' => $uid)); if(empty($user)) { message(error(-1, '用户不存在'), '', 'ajax'); } $user['groupname'] = $_W['account']['groups'][$user['groupid']]['title']; load()->model('card'); $card = card_setting(); load()->model('card'); $member = pdo_get('mc_card_members', array('uniacid' => $_W['uniacid'], 'uid' => $user['uid'])); if(!empty($card) && $card['status'] == 1 && !empty($member)) { $user['discount'] = $card['discount'][$user['groupid']]; if(!empty($user['discount']) && !empty($user['discount']['discount'])) { if($total >= $user['discount']['condition']) { $log .= ",所在会员组【{$user['groupname']}】,可享受满【{$user['discount']['condition']}】元"; if($card['discount_type'] == 1) { $log .= "减【{$user['discount']['discount']}】元"; $money = $total - $user['discount']['discount']; } else { $discount = $user['discount']['discount'] * 10; $log .= "打【{$discount}】折"; $money = $total * $user['discount']['discount']; } if($money < 0) { $money = 0; } $log .= ",实收金额【{$money}】元"; } } $post_money = strval($post['fact_fee']); if($post_money != $money) { message(error(-1, '实收金额错误'), '', 'ajax'); } $post_credit1 = intval($post['credit1']); if($post_credit1 > 0) { if($post_credit1 > $user['credit1']) { message(error(-1, '超过会员账户可用积分'), '', 'ajax'); } } $post_offset_money = trim($post['offset_money']); $offset_money = 0; if($post_credit1 && $card['offset_rate'] > 0 && $card['offset_max'] >= 0) { if ($card['offset_max'] == '0') { $offset_money = $post_credit1/$card['offset_rate']; } else { $offset_money = min($card['offset_max'], $post_credit1/$card['offset_rate']); } if($offset_money != $post_offset_money) { message(error(-1, '积分抵消金额错误'), '', 'ajax'); } $credit1 = $post_credit1; $log .= ",使用【{$post_credit1}】积分抵消【{$offset_money}】元"; } } $credit2 = floatval($post['credit2']); if($credit2 > 0) { if($credit2 > $user['credit2']) { message(error(-1, '超过会员账户可用余额'), '', 'ajax'); } $log .= ",使用余额支付【{$credit2}】元"; } } else { $post['cash'] = $post['fee']; } $cash = floatval($post['cash']); $sum = strval($credit2 + $cash + $offset_money); $money = strval($money); if($sum != $money) { message(error(-1, '支付金额不等于实收金额'), '', 'ajax'); } $realname = $post['member']['realname'] ? $post['member']['realname'] :$post['member']['realname']; if($cash <= 0) { $data = array( 'uniacid' => $_W['uniacid'], 'uid' => $member['uid'], 'status' => 0, 'type' => 'wechat', 'trade_type' => 'micropay', 'fee' => $total, 'final_fee' => $money, 'credit1' => $post_credit1, 'credit1_fee' => $offset_money, 'credit2' => $credit2, 'cash' => $cash, 'body' => $body, 'nickname' => $realname, 'remark' => $log, 'clerk_id' => $_W['user']['clerk_id'], 'store_id' => $_W['user']['store_id'], 'clerk_type' => $_W['user']['clerk_type'], 'createtime' => TIMESTAMP, 'status' => 1, 'paytime' => TIMESTAMP, 'credit_status' => 1, ); pdo_insert('paycenter_order', $data); load()->model('mc'); if($post_credit1 > 0) { $status = mc_credit_update($member['uid'], 'credit1', -$post_credit1, array(0, "会员刷卡消费,使用积分抵现,扣除{$post_credit1积分}", 'system', $_W['user']['clerk_id'], $_W['user']['store_id'], $_W['user']['clerk_type'])); } if($credit2 > 0) { $status = mc_credit_update($member['uid'], 'credit2', -$credit2, array(0, "会员刷卡消费,使用余额支付,扣除{$credit2}余额", 'system', $_W['user']['clerk_id'], $_W['user']['store_id'], $_W['user']['clerk_type'])); } message(error(0, '支付成功'), url('paycenter/wxmicro'), 'ajax'); } else { $log .= ",使用刷卡支付【{$cash}】元"; if(!empty($_GPC['remark'])) { $note = "店员备注:{$_GPC['remark']}"; } $log = $note.$log; $isexist = pdo_get('paycenter_order', array('uniacid' => $_W['uniacid'], 'auth_code' => $code)); if($isexist) { message(error(-1, '每个二维码仅限使用一次,请刷新再试'), '', 'ajax'); } $data = array( 'uniacid' => $_W['uniacid'], 'uid' => $member['uid'], 'status' => 0, 'type' => 'wechat', 'trade_type' => 'micropay', 'fee' => $total, 'final_fee' => $money, 'credit1' => $post_credit1, 'credit1_fee' => $offset_money, 'credit2' => $credit2, 'cash' => $cash, 'remark' => $log, 'body' => $body, 'nickname' => $realname, 'auth_code' => $code, 'clerk_id' => $_W['user']['clerk_id'], 'store_id' => $_W['user']['store_id'], 'clerk_type' => $_W['user']['clerk_type'], 'createtime' => TIMESTAMP, ); pdo_insert('paycenter_order', $data); $id = pdo_insertid(); load()->classs('pay'); $pay = Pay::create(); $params = array( 'tid' => $id, 'module' => 'paycenter', 'type' => 'wechat', 'fee' => $cash, 'body' => $body, 'auth_code' => $code, ); $pid = $pay->buildPayLog($params); if(is_error($pid)) { message($pid, '', 'ajax'); } $log = pdo_get('core_paylog', array('plid' => $pid)); pdo_update('paycenter_order', array('pid' => $pid, 'uniontid' => $log['uniontid']), array('id' => $id)); $data = array( 'out_trade_no' => $log['uniontid'], 'body' => $body, 'total_fee' => $log['fee'] * 100, 'auth_code' => $code, 'uniontid' => $log['uniontid'] ); $result = $pay->buildMicroOrder($data); if ($result['result_code'] == 'SUCCESS') { if(is_error($result)) { message($result, '', 'ajax'); } else { $status = $pay->NoticeMicroSuccessOrder($result); if(is_error($status)) { message($status, '', 'ajax'); } message(error(0, '支付成功'), url('paycenter/wxmicro'), 'ajax'); } } else { message($result, '', 'ajax'); } } exit(); } $paycenter_records = pdo_fetchall("SELECT * FROM " .tablename('paycenter_order') . " WHERE uniacid = :uniacid AND clerk_id = :clerk_id ORDER BY id DESC LIMIT 0,10", array(':uniacid' => $_W['uniacid'], ':clerk_id' => $_W['user']['clerk_id'])); $today_credit_total = pdo_fetchall("SELECT credit2 FROM " . tablename('paycenter_order') . " WHERE uniacid = :uniacid AND clerk_id = :clerk_id AND paytime > :starttime AND paytime < :endtime AND credit2 <> ''", array(':uniacid' => $_W['uniacid'], ':clerk_id' => trim($_W['user']['clerk_id']), ':starttime' => strtotime(date('Ymd')), ':endtime' => time())); $today_wechat_total = pdo_fetchall("SELECT cash FROM " . tablename('paycenter_order') . " WHERE uniacid = :uniacid AND clerk_id = :clerk_id AND paytime > :starttime AND paytime < :endtime AND cash <> ''", array(':uniacid' => $_W['uniacid'], ':clerk_id' => trim($_W['user']['clerk_id']), ':starttime' => strtotime(date('Ymd')), ':endtime' => time())); foreach ($today_wechat_total as $val) { $wechat_total += $val['cash']; } foreach ($today_credit_total as $val) { $credit_total += $val['credit2']; } $wechat_total = $wechat_total ? $wechat_total : '0'; $credit_total = $credit_total ? $credit_total : '0'; load()->model('card'); $card_set = card_setting(); $card_params = json_decode($card_set['params'], true); $grant_rate = $card_set['grant_rate']; unset($card_set['params'], $card_set['nums'], $card_set['times'], $card_set['business'], $card_set['html'], $card_set['description'], $card_set['card_id']); $card_set_str = json_encode($card_set); } if($do == 'query') { if($_W['isajax']) { $post = $_GPC['__input']; $uniontid = trim($post['uniontid']); load()->classs('pay'); $pay = Pay::create(); $result = $pay->queryOrder($uniontid, 2); if(is_error($result)) { message($result, '', 'ajax'); } if($result['trade_state'] == 'SUCCESS') { $status = $pay->NoticeMicroSuccessOrder($result); if(is_error($status)) { message($status, '', 'ajax'); } message(error(0, '支付成功'), '', 'ajax'); } message(error(-1, '支付失败,当前订单状态:' . $result['trade_state']), '', 'ajax'); } } if ($do == 'checkpay') { if($_W['isajax']) { $post = $_GPC['__input']; $uniontid = trim($post['uniontid']); load()->classs('pay'); $pay = Pay::create(); $result = $pay->queryOrder($uniontid, 2); if(is_error($result)) { message($result, '', 'ajax'); } if($result['trade_state'] == 'SUCCESS') { $status = $pay->NoticeMicroSuccessOrder($result); if(is_error($status)) { message($status, '', 'ajax'); } message($result, '', 'ajax'); } message($result, '', 'ajax'); } } template('paycenter/wxmicro');
5、
漏洞名称:
微擎SQL注入
漏洞描述:
微擎/web/source/extension/menu.ctrl.php文件中,对输入参数id未进行严格过滤,导致SQL注入的发生
解决方法:
红色部分为新增的地方
<?php defined('IN_IA') or exit('Access Denied'); $dos = array('display', 'del', 'ajax', 'module', 'view', 'switch', 'del_bind', 'edit-bind'); $do = in_array($do, $dos) ? $do : 'display'; load()->model('frame'); if($do == 'display') { $menus = frame_lists(); if(checksubmit('submit')) { foreach($_GPC['id'] as $k => $v) { $v = intval($v); $update = array(); $menuid = intval($v); $k=intval($k); $title = trim($_GPC['title'][$k]); $is_system = intval($_GPC['is_system'][$k]); if($menuid && $title) { $update = array( 'title' => $title, 'displayorder' => intval($_GPC['displayorder'][$k]), ); if(!$is_system) { $update['url'] = trim($_GPC['url'][$k]); $update['append_title'] = trim($_GPC['append_title'][$k]); $update['append_url'] = trim($_GPC['append_url'][$k]); } pdo_update('core_menu', $update, array('id' => $menuid)); } } if(!empty($_GPC['add_parent_name'])) { $exist_names = array(); foreach($_GPC['add_parent_name'] as $k1 => $v1) { $insert = array(); $add_parent_title = trim($_GPC['add_parent_title'][$k1]); $add_parent_name = trim($_GPC['add_parent_name'][$k1]); $name_exist = pdo_get('core_menu', array('name' => $add_parent_name, 'pid' => 0)); if (!empty($name_exist)) { $exist_names[] = $add_parent_name; continue; } if($add_parent_title && $add_parent_name) { $insert = array( 'pid' => 0, 'title' => $add_parent_title, 'name' => $add_parent_name, 'append_title' => trim($_GPC['add_parent_append_title'][$k1]), 'displayorder' => intval($_GPC['add_parent_displayorder'][$k1]), 'is_system' => 0 ); pdo_insert('core_menu', $insert); } } } if(!empty($_GPC['add_pid'])) { foreach($_GPC['add_pid'] as $k1 => $v1) { $insert = array(); $v1 = intval($v1); $add_title = trim($_GPC['add_title'][$k1]); $add_name = trim($_GPC['add_name'][$k1]); if($v1 && $add_title && $add_name) { $insert = array( 'pid' => $v1, 'title' => $add_title, 'name' => $add_name, 'displayorder' => intval($_GPC['add_displayorder'][$k1]), 'is_system' => 0 ); pdo_insert('core_menu', $insert); } } } if(!empty($_GPC['add_child_pid'])) { foreach($_GPC['add_child_pid'] as $k2 => $v2) { $insert = array(); $v2 = intval($v2); $add_child_title = trim($_GPC['add_child_title'][$k2]); $add_child_name = trim($_GPC['add_child_name'][$k2]); $add_child_url = trim($_GPC['add_child_url'][$k2]); if($v2 && $add_child_title && $add_child_name && $add_child_url) { $insert = array( 'pid' => $v2, 'title' => $add_child_title, 'name' => $add_child_name, 'url' => $add_child_url, 'type' => 'url', 'displayorder' => intval($_GPC['add_child_displayorder'][$k2]), 'is_system' => 0, 'permission_name' => trim($_GPC['add_child_permission'][$k2]), ); $add_child_append_title = trim($_GPC['add_child_append_title'][$k2]); $add_child_append_url = trim($_GPC['add_child_append_url'][$k2]); if($add_child_append_title && $add_child_append_url) { $insert['append_title'] = $add_child_append_title; $insert['append_url'] = $add_child_append_url; } pdo_insert('core_menu', $insert); } } } if(!empty($_GPC['add_permission_pid'])) { foreach($_GPC['add_permission_pid'] as $k1 => $v1) { $insert = array(); $v1 = intval($v1); $add_permission_title = trim($_GPC['add_permission_title'][$k1]); $add_permission_name = trim($_GPC['add_permission_name'][$k1]); $add_permission_flag = trim($_GPC['add_permission_flag'][$k1]); $isexist = pdo_fetchcolumn('SELECT id FROM ' . tablename('core_menu') . ' WHERE permission_name = :permission_name', array(':permission_name' => $add_permission_name)); if(!empty($isexist)) { continue; } if($v1 && $add_permission_title && $add_permission_name && $add_permission_flag) { $insert = array( 'pid' => $v1, 'title' => $add_permission_title, 'name' => $add_permission_flag, 'permission_name' => $add_permission_name, 'type' => 'permission', 'displayorder' => intval($_GPC['add_permission_displayorder'][$k1]), 'is_system' => 0, 'is_display' => 0, ); pdo_insert('core_menu', $insert); } } } cache_build_frame_menu(); if (!empty($exist_names)) { $exist_names = implode(',', $exist_names); message($exist_names."标识已存在", referer(), 'info'); } message('更新菜单成功', referer(), 'success'); } template('extension/menu'); } if($do == 'del') { $id = intval($_GPC['id']); $menu= pdo_fetch('SELECT * FROM ' . tablename('core_menu') . ' WHERE id = :id', array(':id' => $id)); if($menu['is_system']) { message('系统分类不能删除', referer(), 'error'); } $ids = pdo_fetchall('SELECT id FROM ' . tablename('core_menu') . ' WHERE pid = :id', array(':id' => $id), 'id'); if(!empty($ids)) { $ids_str = implode(',', array_keys($ids)); pdo_query('DELETE FROM ' . tablename('core_menu') . " WHERE pid IN ({$ids_str})"); pdo_query('DELETE FROM ' . tablename('core_menu') . " WHERE id IN ({$ids_str})"); } pdo_query('DELETE FROM ' . tablename('core_menu') . " WHERE id = {$id}"); cache_build_frame_menu(); message('删除分类成功', referer(), 'success'); } if($do == 'ajax') { $id = intval($_GPC['id']); $value = intval($_GPC['value']) ? 0 : 1; pdo_update('core_menu', array('is_display' => $value), array('id' => $id)); cache_build_frame_menu(); exit(); } if($do == 'module') { load()->model('module'); if(checksubmit('submit')) { if(!empty($_GPC['eid'])) { foreach($_GPC['eid'] as $k => $v) { $update = array(); $entry = trim($_GPC['entry'][$k]); if($entry == 'mine') { $update['url'] = trim($_GPC['url'][$k]); } $update['icon'] = empty($_GPC['icon'][$k]) ? 'fa fa-puzzle-piece' : $_GPC['icon'][$k]; $update['displayorder'] = intval($_GPC['displayorder'][$k]); pdo_update('modules_bindings', $update, array('eid' => intval($v))); } } if(!empty($_GPC['add_title'])) { foreach($_GPC['add_title'] as $k => $v) { $title = trim($v); $url = trim($_GPC['add_url'][$k]); $m = trim($_GPC['add_module'][$k]); if(strexists($url, 'http://') || strexists($url, 'https://')) { if(strexists($url, $_W['siteroot'])) { $url = './index.php?' . str_replace($_W['siteroot'].'web/index.php?', '', $url); } } $icon = empty($_GPC['add_icon'][$k]) ? 'fa fa-puzzle-piece' : trim($_GPC['add_icon'][$k]); if($title && $url && $m) { $data = array(); $data['do'] = ''; $data['module'] = $m; $data['entry'] = 'mine'; $data['title'] = $title; $data['url'] = $url; $data['icon'] = $icon; $data['displayorder'] = intval($_GPC['add_displayorder'][$k]); pdo_insert('modules_bindings', $data); } else { continue; } } } message('更新模块菜单成功', 'refresh', 'success'); } $modules = pdo_fetchall('SELECT mid, name, title FROM ' . tablename('modules') . ' WHERE issystem = 0'); foreach($modules as &$li) { $li['entry'] = module_entries($li['name'], array('mine', 'menu')); } template('extension/module-permission'); } if($do == 'del_bind') { $eid = intval($_GPC['eid']); $permission = intval($_GPC['permission']); pdo_delete('modules_bindings', array('eid' => $eid, 'entry' => 'mine')); exit(); }
6、
漏洞名称:
微擎最新版SQL注入
漏洞描述:
htmlspecialchars_decode 函数对全局过滤gpc产生的 ’ 进行转义,将可控的参数$html的污染值插入数据库后,产生SQL注入漏洞
位置:/web/source/site/editor.ctrl.php
解决方法:
打开“/web/source/site/editor.ctrl.php”文件,从第127行找到“if (!empty($nav)) {”然后在下面加上“$nav['id'] = intval($nav['id']);”保存文件去验证一下就OK了。