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

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

缺陷编号: WooYun-2015-95065

漏洞标题: cmseasy 全站用户cookie枚举伪造登录

相关厂商: cmseasy

漏洞作者: menmen519

提交时间: 2015-02-02 13:17

公开时间: 2015-05-05 09:04

漏洞类型: 设计缺陷/逻辑错误

危害等级: 高

自评Rank: 20

漏洞状态: 厂商已经确认

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

Tags标签: php源码审核 白盒测试

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2015-02-02: 细节已通知厂商并且等待厂商处理中
2015-02-04: 厂商已经确认,细节仅向厂商公开
2015-02-07: 细节向第三方安全合作伙伴开放(绿盟科技唐朝安全巡航无声信息
2015-03-31: 细节向核心白帽子及相关领域专家公开
2015-04-10: 细节向普通白帽子公开
2015-04-20: 细节向实习白帽子公开
2015-05-05: 细节向公众公开

简要描述:

cmseasy 全站用户cookie枚举伪造登录

详细说明:

此问题 比较棘手,原因出在openid上面





我们之前有分析过一个案例:

http://**.**.**.**/bugs/wooyun-2014-081934



这里不赘述了,怎样去修改这个openid呢



我们发送url:

http://localhost:8080/cmseasy/uploads/index.php?case=user&act=respond&ologin_code=alipaylogin&user_id=2&real_name=test&token=xxxx



此时session里面openid已经为2



我们打印一下:



user_act.php:

code 区域
include_once ROOT.'/lib/plugins/ologin/'.$classname.'.php';
$ologinobj = new $classname();
$status = $ologinobj->respond();

$where[$classname] = session::get('openid');
if(!$where[$classname]) front::redirect(url::create('user'));
$user = new user();
$data = $user->getrow($where);
var_dump(session::get('openid'));exit;







如图所示:

1.png





此时的 session 确实是我们设置的



分析一下这一段代码的逻辑:



code 区域
include_once ROOT.'/lib/plugins/ologin/'.$classname.'.php';
$ologinobj = new $classname();
$status = $ologinobj->respond();

$where[$classname] = session::get('openid');
if(!$where[$classname]) front::redirect(url::create('user'));
$user = new user();
$data = $user->getrow($where);
//var_dump(session::get('openid'));exit;
if(!$data){
$this->view->data = $status;
}else{
cookie::set('login_username',$data['username']);
cookie::set('login_password',front::cookie_encode($data['password']));
session::set('username',$data['username']);
front::redirect(url::create('user'));
}





如果classname为alipaylogin,然后做一下sql查询



2015-02-01 15:40 SELECT * FROM `cmseasy_user` WHERE `alipaylogin`='2' ORDER BY 1 desc limit 1



这里的这个alipaylogin 结果是唯一的



下来查询到了,就把用户名和密码暴露到cookie里面,此时我们就可以拿到这个cookie伪造登录了





那么问题来了,我们看看数据结构

2.png





发现这里是没有记录用户唯一性的第三方登录标志的id的





我们大胆猜想一下,如果用户采用第三方登录 或者第三方注册,那么这个alipaylogin 值会不会生成,而且永远不变呢



代码向上推 首先看注册的地方:

code 区域
if(front::post('username') &&front::post('password')) {
$username=front::post('username');
$username=str_replace('\\', '', $username);
$password=md5(front::post('password'));
$data=array(
'username'=>$username,
'password'=>$password,
'groupid'=>101,
'userip'=>front::ip(),
$classname=>session::get('openid'),
);
if($this->_user->getrow(array('username'=>$username))) {
front::flash(lang('该用户名已被注册!'));
return;
}







发现了 这个位置当你采用第三方注册时候 这里就会生成alipaylogin 或者qqlogin的数值



而且经过我们的排查,这个值永远不变随着用户的注册之后,绑定了



我们在往下看第三方登录这里:

code 区域
if (front::post('submit')) {
if (front::post('username') && front::post('password')) {
$username = front::post('username');
$password = md5(front::post('password'));
$data = array(
'username' => $username,
'password' => $password,
);
$user = new user();
$row = $user->getrow(array('username' => $data['username'], 'password' => $data['password']));
if (!is_array($row)) {
$this->login_false();
return;
}
$post[$classname] = session::get('openid');





发现了 正式用户刚才注册的然后在填写用户名密码进行登录



分析到这我们清楚了一个道理,如果用用户采用第三方去注册,那么我们是可以获取到这个用户的用户名和密码的cookie的





我们在看看正常的用户登录这里需要的cookie是否和我们刚才通过第三方拿到的cookie结构是否一样



code 区域
function login_action() {
if(!$this->loginfalsemaxtimes())
if(front::post('submit')) {
if(config::get('verifycode')) {
if(!session::get('verify') ||front::post('verify')<>session::get('verify')) {
front::flash(lang('验证码错误!')."<a href=''>".lang('backuppage')."</a>");
return;
}
}
if(front::post('username') &&front::post('password')) {
$username=front::post('username');
$password=md5(front::post('password'));
$data=array(
'username'=>$username,
'password'=>$password,
);
$user=new user();
$user=$user->getrow(array('username'=>$data['username'],'password'=>$data['password']));
if(!is_array($user)) {
$this->login_false();
return;
}
$user=$data;
cookie::set('login_username',$user['username']);
cookie::set('login_password',front::cookie_encode($user['password']));







发现填写的cookie 和第三方要构造的 一模一样







下载 剩下的问题就是 ,如果所有权限的入口只是查了一下cookie里面的name和passwd,我们的分析就正确无误:

code 区域
function init() {
$user='';
if(cookie::get('login_username') &&cookie::get('login_password')) {
$user=new user();
$user=$user->getrow(array('username'=>cookie::get('login_username')));
if(cookie::get('login_password')!=front::cookie_encode($user['password'])){
unset($user);
}
}





user_act里面的 符合我们刚才分析的,其他的我们就不看了,我们看一下管理员:





管理员这里比较bug,站点安装完成之后,管理员的 比如说alipaylogin 是空的



那么我们只要把openid设置为空就直接可以查看管理员cookie了



分析到此为止



我们来实际操作一下



第三方注册一个用户:



url:

http://localhost:8080/cmseasy/uploads/index.php?case=user&act=respond&ologin_code=alipaylogin



postdata:

regsubmit=xxx&username=test2&password=111111





我们怎么去获取test2用户cookie,并且伪造登录:



打印一下相关的数据:

code 区域
$where[$classname] = session::get('openid');
if(!$where[$classname]) front::redirect(url::create('user'));
$user = new user();
$data = $user->getrow($where);
var_dump($data);
if(!$data){
$this->view->data = $status;
}else{
cookie::set('login_username',$data['username']);
cookie::set('login_password',front::cookie_encode($data['password']));
session::set('username',$data['username']);
var_dump($_SESSION);
var_dump($_COOKIE);
exit;
front::redirect(url::create('user'));
}





访问url:

http://localhost:8080/cmseasy/uploads/index.php?case=user&act=respond&ologin_code=alipaylogin&user_id=1&real_name=test&token=xxxx





我没有登录,获取到了这个的cookie:

3.png









注释,由于我们alipaylogin.php,上下文查看没有可以影响到user_id的传递,本地没有搭建第三方



我们模拟了一下

code 区域
//var_dump($alipayNotify);
$verify_result = $alipayNotify->verifyReturn();
//var_dump($verify_result);
if(true || $verify_result) {//验证成功
$user_id = front::$get['user_id'];
$token = front::$get['token'];
session::set('access_token',$token);
session::set("openid",$user_id);





第三方这里的恒等true 进入到设置session里面来 ,这个在之前的一个漏洞已经说明原因



分析到此为止

漏洞证明:

修复方案:

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


漏洞回应

厂商回应:

危害等级:低

漏洞Rank:5

确认时间:2015-02-04 09:03

厂商回复:

感谢

最新状态:

暂无


漏洞评价:

对本漏洞信息进行评价,以更好的反馈信息的价值,包括信息客观性,内容是否完整以及是否具备学习价值

漏洞评价(共0人评价):
登陆后才能进行评分

评价

  1. 2015-02-02 16:55 | 命运 ( 路人 | Rank:3 漏洞数:2 | 我是来乌云秀智商下限的~~)
    0

    menmen表示我找不到你qq了= =

  2. 2015-02-02 17:03 | menmen519 ( 普通白帽子 | Rank:914 漏洞数:161 | http://menmen519.blog.sohu.com/)
    0

    @命运 ........

  3. 2015-02-02 18:29 | 君宝 ( 路人 | Rank:19 漏洞数:4 | 不要跟我比浪。。你浪不过我。。)
    0

    马克!

  4. 2015-02-05 23:49 | 命运 ( 路人 | Rank:3 漏洞数:2 | 我是来乌云秀智商下限的~~)
    0

    @menmen519 = =真找不到了 以前和你在一个群就没加你 后来那个qq被盗了

登录后才能发表评论,请先 登录