VYPR
Unrated severityOSV Advisory· Published Aug 24, 2018· Updated Aug 5, 2024

CVE-2018-15535

CVE-2018-15535

Description

/filemanager/ajax_calls.php in tecrail Responsive FileManager before 9.13.4 uses external input to construct a pathname that should be within a restricted directory, but it does not properly neutralize get_file sequences such as ".." that can resolve to a location that is outside of that directory, aka Directory Traversal.

Affected products

2

Patches

1
a50cac88ebcf

version 9.13.4

10 files changed · +133 93
  • changelog.txt+14 0 modified
    @@ -1,5 +1,19 @@
     Responsive Filemanager Changelog 
     
    +*********************************************************
    +*  RFM 9.13.4
    +*********************************************************
    +- fix Directory Traversal Allows to Read Any File (thanks to Simon Uvarov for reporting)
    +- fix Path Traversal While Upacking Archives (thanks to Simon Uvarov for reporting)
    +- Fix foreach warning on URL upload
    +- Fix http https URL upload
    +- add toggle on config for extract_files
    +- prevent image creation for broken links in URL upload (thanks to davodavodavo3)
    +- Migrate to yarn on development (thanks to mklkj)
    +- code refactoring
    +
    +
    +
     *********************************************************
     *  RFM 9.13.3
     *********************************************************
    
  • filemanager/ajax_calls.php+34 43 modified
    @@ -23,6 +23,21 @@
     	response(trans('Lang_Not_Found').AddErrorLocation())->send();
     	exit;
     }
    +
    +
    +//check $_GET['file']
    +if(isset($_GET['file']) && !checkRelativePath($_GET['file'])) {
    +    response(trans('wrong path'))->send();
    +    exit;
    +}
    +
    +//check $_GET['file']
    +if(isset($_GET['path']) && !checkRelativePath($_GET['path'])) {
    +    response(trans('wrong path'))->send();
    +    exit;
    +}
    +
    +
     $ftp = ftp_con($config);
     
     if(isset($_GET['action']))
    @@ -83,12 +98,7 @@
     		case 'save_img':
     			$info = pathinfo($_POST['name']);
     
    -			if (
    -				strpos($_POST['path'], '/') === 0
    -				|| strpos($_POST['path'], '../') !== false
    -				|| strpos($_POST['path'], '..\\') !== false
    -				|| strpos($_POST['path'], './') === 0
    -				|| (strpos($_POST['url'], 'http://s3.amazonaws.com/feather') !== 0 && strpos($_POST['url'], 'https://s3.amazonaws.com/feather') !== 0)
    +			if ((strpos($_POST['url'], 'http://s3.amazonaws.com/feather') !== 0 && strpos($_POST['url'], 'https://s3.amazonaws.com/feather') !== 0)
     				|| $_POST['name'] != fix_filename($_POST['name'], $config)
     				|| ! in_array(strtolower($info['extension']), array( 'jpg', 'jpeg', 'png' ))
     			)
    @@ -135,15 +145,9 @@
     			}
     			break;
     		case 'extract':
    -			if (	strpos($_POST['path'], '/') === 0 
    -				|| strpos($_POST['path'], '../') !== false 
    -				|| strpos($_POST['path'], '..\\') !== false 
    -				|| strpos($_POST['path'], './') === 0)
    -			{
    -				response(trans('wrong path'.AddErrorLocation()))->send();
    -				exit;
    +			if(!$config['extract_files']){
    +				response(trans('wrong action'))->send();
     			}
    -
     			if($ftp){
     				$path = $config['ftp_base_url'].$config['upload_dir'] . $_POST['path'];
     				$base_folder = $config['ftp_base_url'].$config['upload_dir'] . fix_dirname($_POST['path']) . "/";
    @@ -186,28 +190,24 @@
     							exit;
     						}
     
    -						//make all the folders
    -						for ($i = 0; $i < $zip->numFiles; $i++)
    -						{
    -							$OnlyFileName = $zip->getNameIndex($i);
    -							$FullFileName = $zip->statIndex($i);
    -							if (substr($FullFileName['name'], -1, 1) == "/")
    -							{
    -								create_folder($base_folder . $FullFileName['name']);
    -							}
    -						}
    -						//unzip into the folders
    +						//make all the folders and unzip into the folders
     						for ($i = 0; $i < $zip->numFiles; $i++)
     						{
    -							$OnlyFileName = $zip->getNameIndex($i);
     							$FullFileName = $zip->statIndex($i);
     
    -							if ( ! (substr($FullFileName['name'], -1, 1) == "/"))
    -							{
    -								$fileinfo = pathinfo($OnlyFileName);
    -								if (in_array(strtolower($fileinfo['extension']), $config['ext']))
    +							if(checkRelativePath($FullFileName['name'])){
    +								if (substr($FullFileName['name'], -1, 1) == "/")
     								{
    -									copy('zip://' . $path . '#' . $OnlyFileName, $base_folder . $FullFileName['name']);
    +									create_folder($base_folder . $FullFileName['name']);
    +								}
    +
    +								if ( ! (substr($FullFileName['name'], -1, 1) == "/"))
    +								{
    +									$fileinfo = pathinfo($FullFileName['name']);
    +									if (in_array(strtolower($fileinfo['extension']), $config['ext']))
    +									{
    +										copy('zip://' . $path . '#' . $FullFileName['name'], $base_folder . $FullFileName['name']);
    +									}
     								}
     							}
     						}
    @@ -232,7 +232,7 @@
     					$phar = new PharData($path);
     					$phar->decompressFiles();
     					$files = array();
    -					check_files_extensions_on_phar($phar, $files, '', $config['ext']);
    +					check_files_extensions_on_phar($phar, $files, '', $config);
     					$phar->extractTo($base_folder, $files, true);
     
     					break;
    @@ -365,16 +365,7 @@
     		case 'copy_cut':
     			if ($_POST['sub_action'] != 'copy' && $_POST['sub_action'] != 'cut')
     			{
    -				response(trans('wrong sub-action').AddErrorLocation())->send();
    -				exit;
    -			}
    -
    -			if (strpos($_POST['path'],'../') !== FALSE
    -				|| strpos($_POST['path'],'./') !== FALSE 
    -				|| strpos($_POST['path'],'..\\') !== FALSE
    -				|| strpos($_POST['path'],'.\\') !== FALSE )
    -			{
    -				response(trans('wrong path'.AddErrorLocation()))->send();
    +				response(trans('wrong sub-action'))->send();
     				exit;
     			}
     
    @@ -611,7 +602,7 @@
     
     			if ($sub_action != 'preview' && $sub_action != 'edit')
     			{
    -				response(trans('wrong action').AddErrorLocation())->send();
    +				response(trans('wrong action'))->send();
     				exit;
     			}
     
    
  • filemanager/config/config.php+1 0 modified
    @@ -329,6 +329,7 @@
     	'rename_files'                            => true,
     	'rename_folders'                          => true,
     	'duplicate_files'                         => true,
    +	'extract_files'                           => true,
     	'copy_cut_files'                          => true, // for copy/cut files
     	'copy_cut_dirs'                           => true, // for copy/cut directories
     	'chmod_files'                             => true, // change file permissions
    
  • filemanager/dialog.php+8 13 modified
    @@ -47,15 +47,8 @@
     }elseif(isset($_SESSION['RF']['fldr']) && !empty($_SESSION['RF']['fldr'])){
     	$subdir_path = rawurldecode(trim(strip_tags($_SESSION['RF']['fldr']),"/"));
     }
    -$subdir_path_decoded = urldecode($subdir_path);
    -if (strpos($subdir_path,'../') === FALSE
    -	&& strpos($subdir_path,'./') === FALSE
    -	&& strpos($subdir_path,'..\\') === FALSE
    -	&& strpos($subdir_path,'.\\') === FALSE
    -	&& strpos($subdir_path_decoded,'../') === FALSE
    -	&& strpos($subdir_path_decoded,'./') === FALSE
    -	&& strpos($subdir_path_decoded,'..\\') === FALSE
    -	&& strpos($subdir_path_decoded,'.\\') === FALSE)
    +
    +if ( checkRelativePath($subdir_path))
     {
     	$subdir = strip_tags($subdir_path) ."/";
     	$_SESSION['RF']['fldr'] = $subdir_path;
    @@ -99,9 +92,10 @@
     }
     $rfm_subfolder = '';
     
    -if (!empty($_SESSION['RF']["subfolder"]) && strpos($_SESSION['RF']["subfolder"],'../') === FALSE && strpos($_SESSION['RF']["subfolder"],'..\\') === FALSE
    -&& strpos($_SESSION['RF']["subfolder"],'./') === FALSE && strpos($_SESSION['RF']["subfolder"],"/") !== 0
    -&& strpos($_SESSION['RF']["subfolder"],'.') === FALSE)
    +if (!empty($_SESSION['RF']["subfolder"]) 
    +	&& strpos($_SESSION['RF']["subfolder"],"/") !== 0
    +	&& strpos($_SESSION['RF']["subfolder"],'.') === FALSE
    +)
     {
     	$rfm_subfolder = $_SESSION['RF']['subfolder'];
     }
    @@ -257,7 +251,7 @@
     	$ext_tmp = array();
     	foreach($extensions as $extension){
     		$extension = fix_strtolower($extension);
    -		if(in_array( $extension, $config['ext'])){
    +		if(check_file_extension( $extension, $config)){
     			$ext_tmp[]=$extension;
     		}
     	}
    @@ -482,6 +476,7 @@
     	<input type="hidden" id="lang_error_upload" value="<?php echo trans('Error_Upload');?>" />
     	<input type="hidden" id="lang_select" value="<?php echo trans('Select');?>" />
     	<input type="hidden" id="lang_extract" value="<?php echo trans('Extract');?>" />
    +	<input type="hidden" id="extract_files" value="<?php if($config['extract_files']) echo 1; else echo 0;?>" />
     	<input type="hidden" id="transliteration" value="<?php echo $config['transliteration']?"true":"false";?>" />
     	<input type="hidden" id="convert_spaces" value="<?php echo $config['convert_spaces']?"true":"false";?>" />
     	<input type="hidden" id="replace_with" value="<?php echo $config['convert_spaces']? $config['replace_with'] : "";?>" />
    
  • filemanager/execute.php+4 8 modified
    @@ -9,13 +9,9 @@
     	exit;
     }
     
    -if (strpos($_POST['path'],'/')===0
    -	|| strpos($_POST['path'],'../')!==FALSE
    -	|| strpos($_POST['path'],'./')===0
    -	|| strpos($_POST['path'],'..\\')!==FALSE
    -	|| strpos($_POST['path'],'.\\')===0)
    +if (!checkRelativePath($_POST['path']))
     {
    -	response(trans('wrong path'.AddErrorLocation()))->send();
    +	response(trans('wrong path'))->send();
     	exit;
     }
     
    @@ -373,7 +369,7 @@ function returnPaths($_path,$_name,$config){
     
     			// something terribly gone wrong
     			if ($action != 'copy' && $action != 'cut'){
    -				response(trans('wrong action').AddErrorLocation())->send();
    +				response(trans('wrong action'))->send();
     				exit;
     			}
     			if($ftp){
    @@ -514,7 +510,7 @@ function returnPaths($_path,$_name,$config){
     
     			break;
     		default:
    -			response(trans('wrong action').AddErrorLocation())->send();
    +			response(trans('wrong action'))->send();
     			exit;
     	}
     }
    
  • filemanager/force_download.php+3 7 modified
    @@ -12,20 +12,16 @@
     }
     
     
    -if (
    +if (!checkRelativePath($_POST['path']) ||
         strpos($_POST['path'], '/') === 0
    -    || strpos($_POST['path'], '../') !== false
    -    || strpos($_POST['path'], './') === 0
    -    || strpos($_POST['path'], '..\\') !== false
    -    || strpos($_POST['path'], '.\\') === 0
     ) {
    -    response(trans('wrong path' . AddErrorLocation()), 400)->send();
    +    response(trans('wrong path'), 400)->send();
         exit;
     }
     
     
     if (strpos($_POST['name'], '/') !== false) {
    -    response(trans('wrong path' . AddErrorLocation()), 400)->send();
    +    response(trans('wrong path' ), 400)->send();
         exit;
     }
     
    
  • filemanager/include/utils.php+57 3 modified
    @@ -94,6 +94,32 @@ function trans($var)
     	}
     }
     
    +
    +
    +
    +/**
    +* Check relative path
    +*
    +* @param  string  $path
    +*
    +* @return boolean is it correct?
    +*/
    +function checkRelativePath($path){
    +	$path_correct = true;
    +	$path_decoded = rawurldecode($path);
    +	if (strpos($path, '../') !== false
    +        || strpos($path, './') !== false
    +        || strpos($path, '..\\') !== false
    +        || strpos($path, '.\\') !== false
    +    	|| strpos($path_decoded, '../') !== false
    +        || strpos($path_decoded, './') !== false
    +        || strpos($path_decoded, '..\\') !== false
    +        || strpos($path_decoded, '.\\') !== false) {
    +        $path_correct = false;
    +    }
    +    return $path_correct;
    +}
    +
     /**
     * Delete file
     *
    @@ -567,6 +593,34 @@ function check_files_extensions_on_path($path, $ext)
     	}
     }
     
    +
    +/**
    +* Check file extension 
    +*
    +* @param  string  $extension
    +* @param  array   $config
    +*/
    +
    +function check_file_extension($extension,$config){
    +	$check = false;
    +	if (!$config['ext_blacklist']) {
    +		if(in_array(mb_strtolower($extension), $conf['ext'])){
    +			$check = true;
    +		}
    +    } else {
    +    	if(!in_array(mb_strtolower($extension), $conf['ext_blacklist'])){
    +			$check = true;
    +		}
    +    }
    +
    +	if($config['files_without_extension'] && $extension == ''){
    +		$check = true;
    +	}
    +
    +	return $check;
    +}
    +
    +
     /**
     * Get file extension present in PHAR file
     *
    @@ -575,13 +629,13 @@ function check_files_extensions_on_path($path, $ext)
     * @param  string  $basepath
     * @param  string  $ext
     */
    -function check_files_extensions_on_phar($phar, &$files, $basepath, $ext)
    +function check_files_extensions_on_phar($phar, &$files, $basepath, $config)
     {
     	foreach ($phar as $file)
     	{
     		if ($file->isFile())
     		{
    -			if (in_array(mb_strtolower($file->getExtension()), $ext))
    +			if (check_file_extension($file->getExtension()))
     			{
     				$files[] = $basepath . $file->getFileName();
     			}
    @@ -591,7 +645,7 @@ function check_files_extensions_on_phar($phar, &$files, $basepath, $ext)
     			if ($file->isDir())
     			{
     				$iterator = new DirectoryIterator($file);
    -				check_files_extensions_on_phar($iterator, $files, $basepath . $file->getFileName() . '/', $ext);
    +				check_files_extensions_on_phar($iterator, $files, $basepath . $file->getFileName() . '/', $config);
     			}
     		}
     	}
    
  • filemanager/upload.php+2 5 modified
    @@ -34,11 +34,8 @@
     
         $fldr = rawurldecode(trim(strip_tags($_POST['fldr']), "/") . "/");
     
    -    if (strpos($fldr, '../') !== false
    -        || strpos($fldr, './') !== false
    -        || strpos($fldr, '..\\') !== false
    -        || strpos($fldr, '.\\') !== false) {
    -        response(trans('wrong path' . AddErrorLocation()))->send();
    +    if (!checkRelativePath($fldr)) {
    +        response(trans('wrong path'))->send();
             exit;
         }
     
    
  • gulpfile.js+0 5 modified
    @@ -88,9 +88,4 @@ elixir(function (mix) {
             ['modernizr.custom.js'],
             'filemanager/js/modernizr.custom.js'
         );
    -
    -    mix.scripts(
    -        ['load_more.js'],
    -        'filemanager/js/load_more.js'
    -    );
     });
    
  • resources/assets/js/include.js+10 9 modified
    @@ -3,7 +3,7 @@ var encodeURL,show_animation,hide_animation,apply,apply_none,apply_img,apply_any
     {
     	"use strict";
     
    -	var version = "9.13.3";
    +	var version = "9.13.4";
     	var active_contextmenu = true;
     	var myLazyLoad = null;
     	var clipboard = null;
    @@ -239,9 +239,10 @@ var encodeURL,show_animation,hide_animation,apply,apply_none,apply_img,apply_any
     						disabled: false
     					};
     					// extract
    -					if ($trigger.find('.img-precontainer-mini .filetype').hasClass('zip') ||
    +					if (($trigger.find('.img-precontainer-mini .filetype').hasClass('zip') ||
     						$trigger.find('.img-precontainer-mini .filetype').hasClass('tar') ||
    -						$trigger.find('.img-precontainer-mini .filetype').hasClass('gz'))
    +						$trigger.find('.img-precontainer-mini .filetype').hasClass('gz')) && 
    +						jQuery('#extract_files').val() == 1)
     					{
     						options.items.unzip = {
     							name: jQuery('#lang_extract').val(),
    @@ -840,7 +841,7 @@ var encodeURL,show_animation,hide_animation,apply,apply_none,apply_img,apply_any
     		// info btn
     		jQuery('#info').on('click', function ()
     		{
    -			bootbox.alert('<div class="text-center"><br/><img src="img/logo.png" alt="responsive filemanager"/><br/><br/><p><strong>RESPONSIVE filemanager v.' + version + '</strong><br/><a href="http://www.responsivefilemanager.com">responsivefilemanager.com</a></p><br/><p>Copyright © <a href="http://www.tecrail.com" alt="tecrail">Tecrail</a> - Alberto Peripolli. All rights reserved.</p><br/><p>License<br/><small><img alt="Creative Commons License" style="border-width:0" src="http://responsivefilemanager.com/license.php" /><br />This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc/3.0/">Creative Commons Attribution-NonCommercial 3.0 Unported License</a>.</small></p></div>');
    +			bootbox.alert('<div class="text-center"><br/><img src="img/logo.png" alt="responsive filemanager"/><br/><br/><p><strong>RESPONSIVE filemanager v.' + version + '</strong><br/><a href="http://www.responsivefilemanager.com">responsivefilemanager.com</a></p><br/><p>Copyright © <a href="http://www.tecrail.com" alt="tecrail">Tecrail</a> - Alberto Peripolli. All rights reserved.</p><br/><p>License<br/><small><img alt="Creative Commons License" style="border-width:0" src="https://www.responsivefilemanager.com/license.php" /><br />This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc/3.0/">Creative Commons Attribution-NonCommercial 3.0 Unported License</a>.</small></p></div>');
     		});
     
     		jQuery('#change_lang_btn').on('click', function ()
    @@ -982,11 +983,10 @@ var encodeURL,show_animation,hide_animation,apply,apply_none,apply_img,apply_any
     		});
     		var getFiles = function(path){
     			var files = [];
    -			var subdir = jQuery('#subdir').val();
     			jQuery('.selection:checkbox:checked:visible').each(function () {
     				var file = jQuery(this).val();
     				if(path){
    -					file = subdir + file;
    +					file = jQuery(this).closest('figure').attr('data-path');
     				}
     				files.push(file);
     			});
    @@ -1017,6 +1017,7 @@ var encodeURL,show_animation,hide_animation,apply,apply_none,apply_img,apply_any
     				if (result == true)
     				{
     					var files = getFiles(true);
    +
     					execute_multiple_action('delete_files', files, '', '', '');
     					var fil = jQuery('#files_number');
     					fil.text(parseInt(fil.text())-files.length);
    @@ -1752,8 +1753,8 @@ var encodeURL,show_animation,hide_animation,apply,apply_none,apply_img,apply_any
     	function returnUrls(files){
     		var path = jQuery('#cur_dir').val();
     		path = path.replace('\\', '/');
    -		var subdir = jQuery('#subdir').val();
    -		subdir = subdir.replace('\\', '/');
    +		var sub_folder = jQuery('#sub_folder').val();
    +		sub_folder = sub_folder.replace('\\', '/');
     		var base_url = jQuery('#base_url').val();
     		var urls=[];
     		var is_return_relative_url = jQuery('#return_relative_url').val();
    @@ -1763,7 +1764,7 @@ var encodeURL,show_animation,hide_animation,apply,apply_none,apply_img,apply_any
     			if(is_ftp){
     				urls.push(encodeURL(jQuery('#ftp_base_url').val() + jQuery('#upload_dir').val() + jQuery('#fldr_value').val() + file));
     			}else{
    -				urls.push(encodeURL((is_return_relative_url == 1 ? subdir : base_url + path) + file));
    +				urls.push(encodeURL((is_return_relative_url == 1 ? sub_folder : base_url + path) + file));
     			}
     		}
     		return urls;
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

2

News mentions

0

No linked articles in our index yet.