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- Range: 9.9, 9.9.1, 9.9.2, …
- Range: <9.13.4
Patches
110 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- www.exploit-db.com/exploits/45271/mitreexploitx_refsource_EXPLOIT-DB
- seclists.org/fulldisclosure/2018/Aug/34mitremailing-listx_refsource_FULLDISC
News mentions
0No linked articles in our index yet.