### 简要描述:
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)
### 漏洞证明:
见详细说明
暂无评论