XiaoCMS漏洞分析

继续进行代码审计,本次选择的是XiaoCMS

0x01 简单分析

这个CMS采用的MVC模式,先看下入口文件

index.php

1
2
3
4
5
6
7
8
<?php
/**
* XiaoCms企业建站版
* 官方网站:http://www.xiaocms.com
*/
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
/![10](D:\hexo\source\_posts\XiaoCMS漏洞分析\10.png)**
* 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是真的难受……