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

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

缺陷编号:wooyun-2014-053922

漏洞标题:PHPMPS信息分类系统二次SQL注入1-5

相关厂商:phpmps.com

漏洞作者: xfkxfk

提交时间:2014-03-18 09:49

修复时间:2014-06-16 09:49

公开时间:2014-06-16 09:49

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2014-03-18: 细节已通知厂商并且等待厂商处理中
2014-03-18: 厂商已经确认,细节仅向厂商公开
2014-03-21: 细节向第三方安全合作伙伴开放
2014-05-12: 细节向核心白帽子及相关领域专家公开
2014-05-22: 细节向普通白帽子公开
2014-06-01: 细节向实习白帽子公开
2014-06-16: 细节向公众公开

简要描述:

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)

漏洞证明:

见详细说明

修复方案:

在进入sql时过滤

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


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:20

确认时间:2014-03-18 09:55

厂商回复:

感谢xfkxfk 提供漏洞详情,我们会尽快发布补丁。

最新状态:

暂无