fanwe O2O用户密码可劫持(通用/开源软件jsonp劫持案例)

TSRC西安沙龙议题之Fanwe o2o。(通用/开源应用中的jsonp劫持案例)

/mapi/Lib/core/common.php中有 fanwe o2o的output函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
* 输出接口数据
* @param unknown_type $data 返回的接口数据
* @param unknown_type $status 当前状态 0/1
* @param unknown_type $info 当前消息 可选,为空时由客户端取默认提示(默认提示包含成功的默认提示与失败的默认提示)
*/
function output($data,$status=1,$info="")
{
header("Content-Type:text/html; charset=utf-8");
$r_type = intval($_REQUEST['r_type']);//返回数据格式类型; 0:base64;1;json_encode;2:array 3:jsonp
$data[CTL] = MODULE_NAME;
$data[ACT] = ACTION_NAME;
$data['status'] = $status;
$data['info'] = $info;
$data['city_name'] = $GLOBALS['city']['name'];
$data['return'] = 1; //弃用该返回,统一返回1
$data['sess_id'] = $GLOBALS['sess_id'];

if ($r_type == 0)
{
echo base64_encode(json_encode($data));
}
else if ($r_type == 1)
{
echo(json_encode($data));
}
else if ($r_type == 2)
{
print_r($data);
}
else if($r_type == 3)
{
$json = json_encode($data);
echo $_GET['callback']."(".$json.")";
}
exit;
}

这是一个通用的输出函数,所有/mpai下的输出全部由output输出。

我们可以看到,这里当$_REQUEST['r_type']==3的时候,输出格式为jsonp。所以,如果$data中有敏感信息,即会造成jsonp劫持。

结果当前函数中就存在一个敏感信息:sess_id:$data['sess_id'] = $GLOBALS['sess_id'];

用户登陆后(fanwe o2o 默认用户账号密码都是fanwe,以这个用户为例),可劫持用户的session( http://localhost/mapi/index.php?ctl=syncbind&act=index&login_type=Sina&access_token=ooooo&sina_id=ooooo&r_type=3&callback=wooyun ):

QQ20150706-14@2x.png

继续深挖,刚才访问的这个URL( http://localhost/mapi/index.php?ctl=syncbind&act=index&login_type=Sina&access_token=ooooo&sina_id=ooooo&r_type=3&callback=wooyun ),实际上就是将账户fanwe绑定了sina_id为ooooo。

那么另外一处,我们可以直接用ooooo进行登录:
http://localhost/mapi/index.php?ctl=synclogin&act=index&login_type=Sina&sina_id=ooooo&access_token=ooooo&r_type=3&callback=wooyun

QQ20150706-15@2x.png

如上图,可以直接劫持用户密码。

写了个POC证明问题。受害者只要在登录状态,访问该POC即会弹出他的账号、邮箱、密码: http://mhz.pw/game/tx/fanweo2o.html

QQ20150706-16@2x.png