### 简要描述: PHPMPS信息分类系统多处SQL注入 ### 详细说明: 第1-3处SQL注入 二次注入,问题在会员中心,购买信息币是存在二次注入: member.php文件: ``` case 'act_gold': $type = $_POST['type']; $number = $type == 'money2gold' ? intval($_POST['m_number']) : intval($_POST['c_number']); if($number <= 0)showmsg('数量必须大于0'); $userinfo = member_info($_userid); $_credit = $number * $CFG['credit2gold']; $_money = $number * $CFG['money2gold']; if($type == 'money2gold') { if($_money > $userinfo['money']) showmsg('您的资金不足以支付此次购买'); money_diff($_username, $_money, $type); } else { if($_credit > $userinfo['credit']) showmsg('您的积分不足以支付此次购买'); credit_diff($_username, $_credit, $type); } gold_add($_username, $number, $type); showmsg('购买信息币成功' , 'member.php?act=gold'); break; ``` 这里存在多处二次注入。 第一处: money_diff($_username, $_money, $type); 第二处: credit_diff($_username, $_credit, $type); 第三处: gold_add($_username, $number, $type); 我们来看看这写函数: ``` function money_diff($username, $number, $note = '') { global $db, $table; $number = round(floatval($number) ,2);...
### 简要描述: PHPMPS信息分类系统多处SQL注入 ### 详细说明: 第1-3处SQL注入 二次注入,问题在会员中心,购买信息币是存在二次注入: member.php文件: ``` case 'act_gold': $type = $_POST['type']; $number = $type == 'money2gold' ? intval($_POST['m_number']) : intval($_POST['c_number']); if($number <= 0)showmsg('数量必须大于0'); $userinfo = member_info($_userid); $_credit = $number * $CFG['credit2gold']; $_money = $number * $CFG['money2gold']; if($type == 'money2gold') { if($_money > $userinfo['money']) showmsg('您的资金不足以支付此次购买'); money_diff($_username, $_money, $type); } else { if($_credit > $userinfo['credit']) showmsg('您的积分不足以支付此次购买'); credit_diff($_username, $_credit, $type); } gold_add($_username, $number, $type); showmsg('购买信息币成功' , 'member.php?act=gold'); break; ``` 这里存在多处二次注入。 第一处: money_diff($_username, $_money, $type); 第二处: credit_diff($_username, $_credit, $type); 第三处: gold_add($_username, $number, $type); 我们来看看这写函数: ``` function money_diff($username, $number, $note = '') { global $db, $table; $number = round(floatval($number) ,2); if($number == 0) return true; if($number < 0) showmsg('不能小于0元'); $note = addslashes($note); $r = member_info($username,'2'); if(!$r) showmsg('不存在此用户'); extract($r); if($number > $money) showmsg('帐户资金不够,请先入款!'); $money = $money - $number; $db->query("UPDATE {$table}member SET money=$money WHERE username='$username'"); ...... function credit_diff($username, $number, $note = '') { global $db, $table; $number = intval($number); if($number < 0) showmsg($LANG['illegal_parameters']); $note = addslashes($note); $r = member_info($username,'2'); if(!$r) showmsg('不存在此用户'); extract($r); $time = time(); $ip = get_ip(); if($chargetype == 0) { if($number > $credit) showmsg('您的积分不足以支付'); $db->query("UPDATE {$table}member SET credit=credit-$number WHERE username='$username'"); $db->query("INSERT INTO {$table}pay_exchange (`username`,`type`,`value`,`note`,`addtime`,`ip`) VALUES('$username','credit','-".$number."','$note','$time','$ip')"); } return TRUE; } ...... function gold_add($username, $number, $note = '') { global $db,$table; $number = intval($number); if($number < 0) showmsg('数量不能小于0'); $note = addslashes($note); $db->query("UPDATE {$table}member SET gold=gold+$number WHERE username='$username'"); if($db->affected_rows() == 0) showmsg('操作失败'); $time = time(); $ip = get_ip(); $db->query("INSERT INTO {$table}pay_exchange (`username`,`type`,`value`,`note`,`addtime`,`ip`) VALUES('$username','gold','$number','$note','$time','$ip')"); } ``` 从上面的函数看出,都直接把username带进了SQL语句。 来看看这个username的来源: ``` $_userid = 0; $_username = ''; $uid = $_SESSION['userid'] ? $_SESSION['userid'] : $_COOKIE['userid']; if(!empty($uid)) { $user_info = $db->getRow("select userid,username,lastposttime,status from {$table}member where userid='$uid' "); if($user_info) { $_userid = $user_info['userid']; $_username = $user_info['username']; $_lastposttime = $user_info['lastposttime']; $_status = $user_info['status']; } } ``` username是直接从用户的信息中取出,没有经过任何过滤直接进入了上面的sql语句,导致二次注入。 漏洞证明: 那么我们注册两个恶意的用户时,如: 1、222222 2、222222' and sleep(5)# 此时,登陆用户2,访问http://localhost/phpmps/member.php?act=gold 然后购买信息币,提交时就会触发执行我们的恶意sql语句,sleep(5) 第4-5处SQL注入 还是二次注入,问题在会员中心,发布我的信息时存在二次注入: post.php文件: ``` <?php define('IN_PHPMPS', true); require dirname(__FILE__) . '/include/common.php'; require PHPMPS_ROOT . 'include/json.class.php'; require PHPMPS_ROOT . 'include/pay.fun.php'; $act = $_REQUEST['act'] ? trim($_REQUEST['act']) : 'select' ; $ip = get_ip(); $postarea = getPostArea($ip); onlyarea($postarea); ...... //奖励积分 if($_username) { $credit_count = getCreditTimes($_username, 'post_info_credit'); if($credit_count < $CFG['max_info_credit']) { if(!empty($CFG['post_info_credit'])) credit_add($_username, $CFG['post_info_credit'], 'post_info_credit'); } $query = $db->query("UPDATE {$table}member SET lastposttime=".time()." WHERE userid='$_userid' "); } ``` 发问信息后,会进行积分奖励,这里又是直接使用了$_username。 第四处SQL注入: 先来看看getCreditTimes函数: ``` function getCreditTimes($username, $type) { global $db, $table; $credit_times = $db->getOne("SELECT COUNT(*) FROM {$table}pay_exchange WHERE username='$_username' AND addtime>".mktime(0,0,0)." AND note='$type' "); return $credit_times; } ``` 这里直接使用了$_username。 第5处SQL注入: 看看函数credit_add,这里也是用了$_username: ``` function credit_add($username, $number, $note = '') { global $db, $table; $number = intval($number); if($number < 0) showmsg('数量不能小于0'); $db->query("UPDATE {$table}member SET credit=credit+$number WHERE username='$username'"); $note = addslashes($note); $time = time(); $ip = get_ip(); if($db->affected_rows() == 0) showmsg('添加失败'); $db->query("INSERT INTO {$table}pay_exchange (`username`,`type`,`value`,`note`,`addtime`,`ip`) VALUES('$username','credit','$number','$note','$time','$ip')"); } ``` 然后也是直接进入sql语句。 最后看看$_username的来源,/include/commom.php文件: ``` $_userid = 0; $_username = ''; $uid = $_SESSION['userid'] ? $_SESSION['userid'] : $_COOKIE['userid']; if(!empty($uid)) { $user_info = $db->getRow("select userid,username,lastposttime,status from {$table}member where userid='$uid' "); if($user_info) { $_userid = $user_info['userid']; $_username = $user_info['username']; $_lastposttime = $user_info['lastposttime']; $_status = $user_info['status']; } } ``` 直接获取的用户的信息,没有过滤,直接进入sql语句。 要是我们注册恶意的用户名,导致二次SQL注入。 漏洞证明: 那么我们注册两个恶意的用户时,如: 1、222222 2、222222' and sleep(5)# 此时,登陆用户2,访问http://localhost/phpmps/post.php发表信息,然后提交时就会sleep(5) ### 漏洞证明: 见详细说明