Fix vulnerability with directories created in upper levels
This commit is contained in:
parent
44656b9d65
commit
57eeb9a1db
|
@ -1,17 +1,32 @@
|
|||
<?php
|
||||
/**
|
||||
* Images File Manager
|
||||
*
|
||||
* @category File manager
|
||||
* @package Pandora FMS
|
||||
* @subpackage Community
|
||||
* @version 1.0.0
|
||||
* @license See below
|
||||
*
|
||||
* ______ ___ _______ _______ ________
|
||||
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
|
||||
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
|
||||
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
|
||||
*
|
||||
* ============================================================================
|
||||
* Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
|
||||
* Please see http://pandorafms.org for full contribution list
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation for version 2.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
// Pandora FMS - http://pandorafms.com
|
||||
// ==================================================
|
||||
// Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
|
||||
// Please see http://pandorafms.org for full contribution list
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation for version 2.
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
// Load global vars
|
||||
// Get global data.
|
||||
global $config;
|
||||
|
||||
check_login();
|
||||
|
@ -24,10 +39,10 @@ if (! check_acl($config['id_user'], 0, 'PM')) {
|
|||
|
||||
require_once 'include/functions_filemanager.php';
|
||||
|
||||
// Header
|
||||
// Header.
|
||||
ui_print_page_header(__('File manager'), '', false, '', true);
|
||||
|
||||
if (isset($config['filemanager']['message'])) {
|
||||
if (isset($config['filemanager']['message']) === true) {
|
||||
echo $config['filemanager']['message'];
|
||||
$config['filemanager']['message'] = null;
|
||||
}
|
||||
|
@ -35,7 +50,7 @@ if (isset($config['filemanager']['message'])) {
|
|||
$directory = (string) get_parameter('directory', '/');
|
||||
$directory = str_replace('\\', '/', $directory);
|
||||
|
||||
// A miminal security check to avoid directory traversal
|
||||
// A miminal security check to avoid directory traversal.
|
||||
if (preg_match('/\.\./', $directory)) {
|
||||
$directory = 'images';
|
||||
}
|
||||
|
@ -48,17 +63,17 @@ if (preg_match('/^manager/', $directory)) {
|
|||
$directory = 'images';
|
||||
}
|
||||
|
||||
// Add custom directories here
|
||||
// Add custom directories here.
|
||||
$fallback_directory = 'images';
|
||||
|
||||
$banned_directories['include'] = true;
|
||||
$banned_directories['godmode'] = true;
|
||||
$banned_directories['operation'] = true;
|
||||
$banned_directories['reporting'] = true;
|
||||
$banned_directories['general'] = true;
|
||||
// Banned directories.
|
||||
$banned_directories['include'] = true;
|
||||
$banned_directories['godmode'] = true;
|
||||
$banned_directories['operation'] = true;
|
||||
$banned_directories['reporting'] = true;
|
||||
$banned_directories['general'] = true;
|
||||
$banned_directories[ENTERPRISE_DIR] = true;
|
||||
|
||||
if (isset($banned_directories[$directory])) {
|
||||
if (isset($banned_directories[$directory]) === true) {
|
||||
$directory = $fallback_directory;
|
||||
}
|
||||
|
||||
|
@ -67,15 +82,15 @@ $real_directory = realpath($config['homedir'].'/'.$directory);
|
|||
echo '<h4>'.__('Index of %s', $directory).'</h4>';
|
||||
|
||||
$upload_file_or_zip = (bool) get_parameter('upload_file_or_zip');
|
||||
$create_text_file = (bool) get_parameter('create_text_file');
|
||||
$create_text_file = (bool) get_parameter('create_text_file');
|
||||
|
||||
$default_real_directory = realpath($config['homedir'].'/'.$fallback_directory);
|
||||
|
||||
if ($upload_file_or_zip) {
|
||||
if ($upload_file_or_zip === true) {
|
||||
upload_file($upload_file_or_zip, $default_real_directory);
|
||||
}
|
||||
|
||||
if ($create_text_file) {
|
||||
if ($create_text_file === true) {
|
||||
create_text_file($default_real_directory);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,36 +1,40 @@
|
|||
<?php
|
||||
|
||||
// Pandora FMS - http://pandorafms.com
|
||||
// ==================================================
|
||||
// Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
|
||||
// Please see http://pandorafms.org for full contribution list
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public License
|
||||
// as published by the Free Software Foundation; version 2
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
/**
|
||||
* @package Include
|
||||
* @subpackage Filemanager
|
||||
* Images File Manager functions.
|
||||
*
|
||||
* @category Functions
|
||||
* @package Pandora FMS
|
||||
* @subpackage Community
|
||||
* @version 1.0.0
|
||||
* @license See below
|
||||
*
|
||||
* ______ ___ _______ _______ ________
|
||||
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
|
||||
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
|
||||
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
|
||||
*
|
||||
* ============================================================================
|
||||
* Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
|
||||
* Please see http://pandorafms.org for full contribution list
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation for version 2.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* #@+
|
||||
* Constants
|
||||
*/
|
||||
// Get global data.
|
||||
// Constants.
|
||||
define('MIME_UNKNOWN', 0);
|
||||
define('MIME_DIR', 1);
|
||||
define('MIME_IMAGE', 2);
|
||||
define('MIME_ZIP', 3);
|
||||
define('MIME_TEXT', 4);
|
||||
/*
|
||||
#@-
|
||||
*/
|
||||
|
||||
if (!function_exists('mime_content_type')) {
|
||||
if (function_exists('mime_content_type') === false) {
|
||||
|
||||
|
||||
/**
|
||||
|
@ -38,11 +42,11 @@ if (!function_exists('mime_content_type')) {
|
|||
*
|
||||
* Help function in case mime_magic is not loaded on PHP.
|
||||
*
|
||||
* @param string Filename to get MIME type.
|
||||
* @param string $filename Filename to get MIME type.
|
||||
*
|
||||
* @return The MIME type of the file.
|
||||
*/
|
||||
function mime_content_type($filename)
|
||||
function mime_content_type(string $filename)
|
||||
{
|
||||
$mime_types = [
|
||||
'txt' => 'text/plain',
|
||||
|
@ -55,7 +59,7 @@ if (!function_exists('mime_content_type')) {
|
|||
'xml' => 'application/xml',
|
||||
'swf' => 'application/x-shockwave-flash',
|
||||
'flv' => 'video/x-flv',
|
||||
// images
|
||||
// Images.
|
||||
'png' => 'image/png',
|
||||
'jpe' => 'image/jpeg',
|
||||
'jpeg' => 'image/jpeg',
|
||||
|
@ -67,7 +71,7 @@ if (!function_exists('mime_content_type')) {
|
|||
'tif' => 'image/tiff',
|
||||
'svg' => 'image/svg+xml',
|
||||
'svgz' => 'image/svg+xml',
|
||||
// archives
|
||||
// Archives.
|
||||
'zip' => 'application/zip',
|
||||
'rar' => 'application/x-rar-compressed',
|
||||
'exe' => 'application/x-msdownload',
|
||||
|
@ -75,22 +79,22 @@ if (!function_exists('mime_content_type')) {
|
|||
'cab' => 'application/vnd.ms-cab-compressed',
|
||||
'gz' => 'application/x-gzip',
|
||||
'gz' => 'application/x-bzip2',
|
||||
// audio/video
|
||||
// Audio/Video.
|
||||
'mp3' => 'audio/mpeg',
|
||||
'qt' => 'video/quicktime',
|
||||
'mov' => 'video/quicktime',
|
||||
// adobe
|
||||
// Adobe.
|
||||
'pdf' => 'application/pdf',
|
||||
'psd' => 'image/vnd.adobe.photoshop',
|
||||
'ai' => 'application/postscript',
|
||||
'eps' => 'application/postscript',
|
||||
'ps' => 'application/postscript',
|
||||
// ms office
|
||||
// MS Office.
|
||||
'doc' => 'application/msword',
|
||||
'rtf' => 'application/rtf',
|
||||
'xls' => 'application/vnd.ms-excel',
|
||||
'ppt' => 'application/vnd.ms-powerpoint',
|
||||
// open office
|
||||
// Open Source Office files.
|
||||
'odt' => 'application/vnd.oasis.opendocument.text',
|
||||
'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
|
||||
];
|
||||
|
@ -98,9 +102,9 @@ if (!function_exists('mime_content_type')) {
|
|||
$ext_fields = explode('.', $filename);
|
||||
$ext = array_pop($ext_fields);
|
||||
$ext = strtolower($ext);
|
||||
if (array_key_exists($ext, $mime_types)) {
|
||||
if (array_key_exists($ext, $mime_types) === true) {
|
||||
return $mime_types[$ext];
|
||||
} else if (function_exists('finfo_open')) {
|
||||
} else if (function_exists('finfo_open') === true) {
|
||||
$finfo = finfo_open(FILEINFO_MIME);
|
||||
$mimetype = finfo_file($finfo, $filename);
|
||||
finfo_close($finfo);
|
||||
|
@ -117,6 +121,14 @@ if (!function_exists('mime_content_type')) {
|
|||
global $config;
|
||||
|
||||
|
||||
/**
|
||||
* Upload file.
|
||||
*
|
||||
* @param boolean $upload_file_or_zip Upload file or zip.
|
||||
* @param string $default_real_directory String with default directory.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function upload_file($upload_file_or_zip, $default_real_directory)
|
||||
{
|
||||
global $config;
|
||||
|
@ -124,7 +136,7 @@ function upload_file($upload_file_or_zip, $default_real_directory)
|
|||
$homedir_filemanager = trim($config['homedir']);
|
||||
$sec2 = get_parameter('sec2');
|
||||
|
||||
if ($sec2 == 'enterprise/godmode/agentes/collections' || $sec2 == 'advanced/collections') {
|
||||
if ($sec2 === 'enterprise/godmode/agentes/collections' || $sec2 === 'advanced/collections') {
|
||||
$homedir_filemanager .= '/attachment/collection/';
|
||||
}
|
||||
|
||||
|
@ -140,9 +152,9 @@ function upload_file($upload_file_or_zip, $default_real_directory)
|
|||
return;
|
||||
}
|
||||
|
||||
if ($upload_file_or_zip) {
|
||||
$decompress = get_parameter('decompress');
|
||||
if (!$decompress) {
|
||||
if ($upload_file_or_zip === true) {
|
||||
$decompress = (bool) get_parameter('decompress', false);
|
||||
if ($decompress === false) {
|
||||
$upload_file = true;
|
||||
$upload_zip = false;
|
||||
} else {
|
||||
|
@ -151,24 +163,24 @@ function upload_file($upload_file_or_zip, $default_real_directory)
|
|||
}
|
||||
} else {
|
||||
$upload_file = (bool) get_parameter('upload_file');
|
||||
$upload_zip = (bool) get_parameter('upload_zip');
|
||||
$upload_zip = (bool) get_parameter('upload_zip');
|
||||
}
|
||||
|
||||
// Upload file
|
||||
if ($upload_file) {
|
||||
if (isset($_FILES['file']) && $_FILES['file']['name'] != '') {
|
||||
$filename = $_FILES['file']['name'];
|
||||
$filesize = $_FILES['file']['size'];
|
||||
// Upload file.
|
||||
if ($upload_file === true) {
|
||||
if (isset($_FILES['file']) === true && empty($_FILES['file']['name']) === false) {
|
||||
$filename = $_FILES['file']['name'];
|
||||
$filesize = $_FILES['file']['size'];
|
||||
$real_directory = io_safe_output((string) get_parameter('real_directory'));
|
||||
$directory = io_safe_output((string) get_parameter('directory'));
|
||||
$umask = io_safe_output((string) get_parameter('umask', ''));
|
||||
$directory = io_safe_output((string) get_parameter('directory'));
|
||||
$umask = io_safe_output((string) get_parameter('umask'));
|
||||
|
||||
if (strpos($real_directory, $default_real_directory) !== 0) {
|
||||
// Perform security check to determine whether received upload directory is part of the default path for caller uploader and user is not trying to access an external path (avoid execution of PHP files in directories that are not explicitly controlled by corresponding .htaccess).
|
||||
ui_print_error_message(__('Security error'));
|
||||
} else {
|
||||
// Copy file to directory and change name
|
||||
if ($directory == '') {
|
||||
// Copy file to directory and change name.
|
||||
if (empty($directory) === true) {
|
||||
$nombre_archivo = $real_directory.'/'.$filename;
|
||||
} else {
|
||||
$nombre_archivo = $homedir_filemanager.'/'.$directory.'/'.$filename;
|
||||
|
@ -177,36 +189,36 @@ function upload_file($upload_file_or_zip, $default_real_directory)
|
|||
if (! @copy($_FILES['file']['tmp_name'], $nombre_archivo)) {
|
||||
$config['filemanager']['message'] = ui_print_error_message(__('Upload error'));
|
||||
} else {
|
||||
if ($umask !== '') {
|
||||
if (empty($umask) === false) {
|
||||
chmod($nombre_archivo, $umask);
|
||||
}
|
||||
|
||||
$config['filemanager']['correct_upload_file'] = 1;
|
||||
ui_print_success_message(__('Upload correct'));
|
||||
|
||||
// Delete temporal file
|
||||
// Delete temporal file.
|
||||
unlink($_FILES['file']['tmp_name']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Upload zip
|
||||
if ($upload_zip) {
|
||||
if (isset($_FILES['file']) && $_FILES['file']['name'] != '') {
|
||||
$filename = $_FILES['file']['name'];
|
||||
$filesize = $_FILES['file']['size'];
|
||||
// Upload zip.
|
||||
if ($upload_zip === true) {
|
||||
if (isset($_FILES['file']) === true && empty($_FILES['file']['name']) === false) {
|
||||
$filename = $_FILES['file']['name'];
|
||||
$filesize = $_FILES['file']['size'];
|
||||
$real_directory = (string) get_parameter('real_directory');
|
||||
$real_directory = io_safe_output($real_directory);
|
||||
$directory = (string) get_parameter('directory');
|
||||
$directory = io_safe_output($directory);
|
||||
$directory = (string) get_parameter('directory');
|
||||
$directory = io_safe_output($directory);
|
||||
|
||||
if (strpos($real_directory, $default_real_directory) !== 0) {
|
||||
// Perform security check to determine whether received upload directory is part of the default path for caller uploader and user is not trying to access an external path (avoid execution of PHP files in directories that are not explicitly controlled by corresponding .htaccess).
|
||||
ui_print_error_message(__('Security error'));
|
||||
} else {
|
||||
// Copy file to directory and change name
|
||||
if ($directory == '') {
|
||||
// Copy file to directory and change name.
|
||||
if (empty($directory) === true) {
|
||||
$nombre_archivo = $real_directory.'/'.$filename;
|
||||
} else {
|
||||
$nombre_archivo = $homedir_filemanager.'/'.$directory.'/'.$filename;
|
||||
|
@ -215,10 +227,10 @@ function upload_file($upload_file_or_zip, $default_real_directory)
|
|||
if (! @copy($_FILES['file']['tmp_name'], $nombre_archivo)) {
|
||||
ui_print_error_message(__('Attach error'));
|
||||
} else {
|
||||
// Delete temporal file
|
||||
// Delete temporal file.
|
||||
unlink($_FILES['file']['tmp_name']);
|
||||
|
||||
// Extract the zip file
|
||||
// Extract the zip file.
|
||||
$zip = new ZipArchive;
|
||||
$pathname = $homedir_filemanager.'/'.$directory.'/';
|
||||
|
||||
|
@ -236,9 +248,9 @@ function upload_file($upload_file_or_zip, $default_real_directory)
|
|||
}
|
||||
|
||||
|
||||
if (isset($_SERVER['CONTENT_LENGTH'])) {
|
||||
// Control the max_post_size exceed
|
||||
if (intval($_SERVER['CONTENT_LENGTH']) > 0 && empty($_POST) and empty($_FILES)) {
|
||||
if (isset($_SERVER['CONTENT_LENGTH']) === true) {
|
||||
// Control the max_post_size exceed.
|
||||
if (intval($_SERVER['CONTENT_LENGTH']) > 0 && empty($_POST) === true && empty($_FILES) === true) {
|
||||
$config['filemanager']['correct_upload_file'] = 0;
|
||||
$config['filemanager']['message'] = ui_print_error_message(__('File size seems to be too large. Please check your php.ini configuration or contact with the administrator'), '', true);
|
||||
}
|
||||
|
@ -270,12 +282,12 @@ function create_text_file($default_real_directory)
|
|||
|
||||
$filename = io_safe_output(get_parameter('name_file'));
|
||||
|
||||
if ($filename != '') {
|
||||
if (empty($filename) === false) {
|
||||
$real_directory = (string) get_parameter('real_directory');
|
||||
$real_directory = io_safe_output($real_directory);
|
||||
$directory = (string) get_parameter('directory');
|
||||
$directory = io_safe_output($directory);
|
||||
$umask = (string) get_parameter('umask', '');
|
||||
$directory = (string) get_parameter('directory');
|
||||
$directory = io_safe_output($directory);
|
||||
$umask = (string) get_parameter('umask');
|
||||
|
||||
if (strpos($real_directory, $default_real_directory) !== 0) {
|
||||
// Perform security check to determine whether received upload directory is part of the default path for caller uploader and user is not trying to access an external path (avoid execution of PHP files in directories that are not explicitly controlled by corresponding .htaccess).
|
||||
|
@ -307,13 +319,13 @@ function create_text_file($default_real_directory)
|
|||
|
||||
$homedir_filemanager = trim($config['homedir']);
|
||||
$sec2 = get_parameter('sec2');
|
||||
if ($sec2 == 'enterprise/godmode/agentes/collections' || $sec2 == 'advanced/collections') {
|
||||
if ($sec2 === 'enterprise/godmode/agentes/collections' || $sec2 === 'advanced/collections') {
|
||||
$homedir_filemanager .= '/attachment/collection/';
|
||||
}
|
||||
|
||||
// CREATE DIR
|
||||
// CREATE DIR.
|
||||
$create_dir = (bool) get_parameter('create_dir');
|
||||
if ($create_dir) {
|
||||
if ($create_dir === true) {
|
||||
global $config;
|
||||
|
||||
$config['filemanager'] = [];
|
||||
|
@ -322,16 +334,19 @@ if ($create_dir) {
|
|||
|
||||
$directory = (string) get_parameter('directory', '/');
|
||||
$directory = io_safe_output($directory);
|
||||
$hash = get_parameter('hash', '');
|
||||
$testHash = md5($directory.$config['dbpass']);
|
||||
$hash = (string) get_parameter('hash');
|
||||
$testHash = md5($directory.$config['dbpass']);
|
||||
|
||||
if ($hash != $testHash) {
|
||||
if ($hash !== $testHash) {
|
||||
ui_print_error_message(__('Security error.'));
|
||||
} else {
|
||||
$dirname = (string) get_parameter('dirname');
|
||||
$dirname = io_safe_output($dirname);
|
||||
|
||||
if ($dirname != '') {
|
||||
if (empty($dirname) === false) {
|
||||
$dirname = io_safe_output($dirname);
|
||||
// For security reasons, level up is avoid.
|
||||
$dirname = str_replace('../', '', $dirname);
|
||||
// Create directory.
|
||||
@mkdir(
|
||||
$homedir_filemanager.'/'.$directory.'/'.$dirname
|
||||
);
|
||||
|
@ -344,9 +359,9 @@ if ($create_dir) {
|
|||
}
|
||||
}
|
||||
|
||||
// DELETE FILE OR DIR
|
||||
// DELETE FILE OR DIR.
|
||||
$delete_file = (bool) get_parameter('delete_file');
|
||||
if ($delete_file) {
|
||||
if ($delete_file === true) {
|
||||
global $config;
|
||||
|
||||
$config['filemanager'] = [];
|
||||
|
@ -355,22 +370,22 @@ if ($delete_file) {
|
|||
|
||||
$filename = (string) get_parameter('filename');
|
||||
$filename = io_safe_output($filename);
|
||||
$hash = get_parameter('hash', '');
|
||||
$hash = get_parameter('hash', '');
|
||||
$testHash = md5($filename.$config['dbpass']);
|
||||
|
||||
if ($hash != $testHash) {
|
||||
if ($hash !== $testHash) {
|
||||
$config['filemanager']['message'] = ui_print_error_message(__('Security error'), '', true);
|
||||
} else {
|
||||
$config['filemanager']['message'] = ui_print_success_message(__('Deleted'), '', true);
|
||||
|
||||
if (is_dir($filename)) {
|
||||
if (rmdir($filename)) {
|
||||
if (is_dir($filename) === true) {
|
||||
if (rmdir($filename) === true) {
|
||||
$config['filemanager']['delete'] = 1;
|
||||
} else {
|
||||
$config['filemanager']['delete'] = 0;
|
||||
}
|
||||
} else {
|
||||
if (unlink($filename)) {
|
||||
if (unlink($filename) === true) {
|
||||
$config['filemanager']['delete'] = 1;
|
||||
} else {
|
||||
$config['filemanager']['delete'] = 0;
|
||||
|
|
Loading…
Reference in New Issue