继续进行代码审计,本次选择的是XiaoCMS
0x01 简单分析
这个CMS采用的MVC模式,先看下入口文件
index.php
1 2 3 4 5 6 7 8
   | <?php
 
 
 
  define('XIAOCMS_PATH',   dirname(__FILE__) . DIRECTORY_SEPARATOR); include XIAOCMS_PATH . 'core/xiaocms.php'; xiaocms::run();
   | 
 
包含了xiaocms.php
有一个安全处理函数,将’/‘和’.’替换为’’
1 2 3
   | private static function _safe($str) { 	return str_replace(array('/', '.'), '', $str); }
  | 
 
还有一个读取文件的函数,不过用在了加载控制器中了,也没什么用
进入Base.class.php
重新定义了GET和POST方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14
   | public static function get($string)     {         if (!isset($_GET[$string])) return null;         if (!is_array($_GET[$string])) return htmlspecialchars(trim($_GET[$string]));         return null;     }
      public static function post($string)     {         if (!isset($_POST[$string])) return null;         if (!is_array($_POST[$string])) return htmlspecialchars(trim($_POST[$string]));         $postArray = self::array_map_htmlspecialchars($_POST[$string]);         return $postArray;     }
   | 
 
htmlspecialchars会将<>和双引号过滤
0x02 后台任意文件上传
看到有upload.class.php,进去看下,有个upload函数
1 2 3 4 5 6 7 8
   |  public function upload($file_upload, $file_name)     {         if (!is_array($file_upload) || empty($file_name)) return false;         $this->parse_init($file_upload);         if (!@move_uploaded_file($this->file_name['tmp_name'], $file_name)) return '文件上传失败,请检查服务器目录权限';         return true;     }
 
  | 
 
跟进parse_init函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
   | protected function parse_init($file)     {         $this->file_name = $file;         if ($this->file_name['size'] > $this->limit_size) {             echo '您上传的文件:' . $this->file_name['name'] . ' 大小超出上传限制!';             exit();         }         if ($this->limit_type) {             if (!in_array($this->get_file_ext(), $this->limit_type)) {                 echo '您上传的:' . $this->file_name['name'] . ' 文件格式不正确!';                 exit();             }         }         return true;     }
   | 
 
$this->limit_type通过set_limit_type函数获取,搜索set_limit_type
在admin/controller/uploadfile.php中发现upload函数
1 2 3 4 5 6 7
   | private function upload($fields, $type, $size) { 		$upload   = xiaocms::load_class('upload');         $ext      = strtolower(substr(strrchr($_FILES[$fields]['name'], '.'), 1)); …… ……     $result   = $upload->set_limit_size(1024*1024*$size)->set_limit_type($type)->upload($_FILES[$fields],XIAOCMS_PATH.$filenpath); ……
  | 
 
同样在admin/controller/uploadfile.php中发现uploadify_uploadAction函数
1 2 3 4 5 6 7 8 9 10 11
   | /** 	 * uploadify_upload 	 */     public function uploadify_uploadAction() { 	    $type = $this->get('type'); 		$size = (int)$this->get('size'); 	    if ($this->post('submit')) { 	        $data = $this->upload('file', explode(',', $type), $size);             if ($data['result']) echo $data['path']; 	    } 	}
   | 
 
$this->limit_type与$this->limit_size都可以控制了,接下来构造upload.html
上传shell


0x03 后台模板写shell
漏洞位于admin/controller/template.php
editAction函数
1 2 3 4 5 6 7 8 9
   | public function editAction() {         …… 		if ($this->post('submit')) { 		    file_put_contents($filepath, htmlspecialchars_decode($this->post('file_content')), LOCK_EX); 		    $this->show_message('提交成功',1); 		}         $filecontent = htmlspecialchars(file_get_contents($filepath));         include $this->admin_tpl('template_add');     }
  | 
 
前面提到过get post到的内容都被htmlspecialchars转义了,而这里又用htmlspecialchars_decode反转义了

0x04 总结
htmlspecialchars和MySQL PDO是真的难受……