Chybeta

某CMS 5.X版本 管理员密码重置漏洞

某CMS 5.X版本 管理员密码重置漏洞

首发于: 某CMS 5.X版本 管理员密码重置漏洞

0x00 前言

蹭一下某CMS 5.X版本GETSHELL漏洞合集的热点。

0x01 漏洞分析

在 admin/admin/getpassword.php 中包含了 admin/include/common.inc.php 。跟入common.inc.php,第77行:

1
2
3
4
5
6
foreach(array('_COOKIE', '_POST', '_GET') as $_request) {
foreach($$_request as $_key => $_value) {
$_key{0} != '_' && $$_key = daddslashes($_value,0,0,1);
$_M['form'][$_key]=daddslashes($_value,0,0,1);
}
}

这里存在变量覆盖漏洞。

回到 admin/admin/getpassword.php ,从第 94 行开始是发送重置密码链接邮箱的处理过程:

  1. 从数据库中取出管理员的信息
  2. 生成密码重置链接
  3. 发送密码重置链接

在发送阶段,admin/admin/getpassword.php 第 143 行:

1
2
3
4
5
6
7
8
9
require_once ROOTPATH.'include/jmail.php';
$sendMail=jmailsend($from,$fromname,$to,$title,$body,$usename,$usepassword,$smtp);
if($sendMail==0){
require_once ROOTPATH.'include/export.func.php';
$post=array('to'=>$to,'title'=>$title,'body'=>$body);
$met_file='/passwordmail.php';
$sendMail=curl_post($post,30);
if($sendMail=='nohost')$sendMail=0;
}

先来看看当$sendMail==0时的情况,此时会将所需信息整合为变量$post,之后调用curl_post发送。curl_post定义在 include/export.func.php:

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
function curl_post($post,$timeout){
global $met_weburl,$met_host,$met_file;
$host=$met_host;
$file=$met_file;
if(get_extension_funcs('curl')&&function_exists('curl_init')&&function_exists('curl_setopt')&&function_exists('curl_exec')&&function_exists('curl_close')){
$curlHandle=curl_init();
curl_setopt($curlHandle,CURLOPT_URL,'http://'.$host.$file);
curl_setopt($curlHandle,CURLOPT_REFERER,$met_weburl);
....
$result=curl_exec($curlHandle);
curl_close($curlHandle);
}
else{
if(function_exists('fsockopen')||function_exists('pfsockopen')){
$post_data=$post;
$post='';
@ini_set("default_socket_timeout",$timeout);
while (list($k,$v) = each($post_data)) {
$post .= rawurlencode($k)."=".rawurlencode($v)."&";
}
$post = substr( $post , 0 , -1 );
$len = strlen($post);
if(function_exists(fsockopen)){
$fp = @fsockopen($host,80,$errno,$errstr,$timeout);
}
else{
$fp = @pfsockopen($host,80,$errno,$errstr,$timeout);
}
if (!$fp) {
$result='';
}
else {
$result = '';
$out = "POST $file HTTP/1.0\r\n";
$out .= "Host: $host\r\n";
$out .= "Referer: $met_weburl\r\n";
$out .= "Content-type: application/x-www-form-urlencoded\r\n";
$out .= "Connection: Close\r\n";
$out .= "Content-Length: $len\r\n";
$out .="\r\n";
$out .= $post."\r\n";
fwrite($fp, $out);

可以看到这里的$met_host操控了邮件内容的发送地点,而该参数可以利用前面的变量覆盖漏洞来进行直接的控制。

接着考虑如何让$sendMail==0。跟入jmailsend,include/jmail.php 第7行:

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
function jmailsend($from,$fromname,$to,$title,$body,$usename,$usepassword,$smtp,$repto,$repname)
{
global $met_fd_port,$met_fd_way;
...
if(stripos($smtp,'.gmail.com')===false){
$mail->Port = $met_fd_port;
...
}
else{
$mail->Port = 465;
...
}
...
if(!$mail->Send()) {
$mail->SmtpClose();
//return "Mailer Error: " . $mail->ErrorInfo;
return false;
} else {
$mail->SmtpClose();
//return "Message sent!";
return true;
}
}

met_fd_port指定了邮件发送端口,属于系统配置。因此倘若我们利用前面的变量覆盖漏洞修改端口,即可导致邮件发送失败,进入到curl_post

0x02 漏洞复现

因为使用curl_post中使用的是http协议,默认端口为80。因此在vps上监听80端口:

1
nc -lvv 80

在填入管理员密码或邮箱后,抓包修改数据:

1.png

forward掉后,
2.png

3.png

0x03 漏洞补丁

在6.0版本中,官方直接删除了该文件,简单粗暴。

微信扫码加入知识星球【漏洞百出】
chybeta WeChat Pay

点击图片放大,扫码知识星球【漏洞百出】

本文标题:某CMS 5.X版本 管理员密码重置漏洞

文章作者:chybeta

发布时间:2018年03月05日 - 16:03

最后更新:2018年03月06日 - 16:03

原始链接:http://chybeta.github.io/2018/03/05/某CMS-5-X版本-管理员密码重置漏洞/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。