264 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			PHP
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			264 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			PHP
		
	
	
		
			Executable File
		
	
	
	
	
| <?php
 | |
| 
 | |
| /**
 | |
|  * uploader control panel
 | |
|  *
 | |
|  * Type:
 | |
|  * Name:
 | |
|  * Date:
 | |
|  * Purpose:
 | |
|  * Input:
 | |
|  *
 | |
|  * @author NoWhereMan <real_nowhereman at users dot sf dot com>
 | |
|  *        
 | |
|  */
 | |
| class admin_uploader extends AdminPanel {
 | |
| 
 | |
| 	var $panelname = 'uploader';
 | |
| 
 | |
| 	var $actions = array(
 | |
| 		'default' => true
 | |
| 	);
 | |
| 
 | |
| }
 | |
| 
 | |
| class admin_uploader_default extends AdminPanelAction {
 | |
| 
 | |
| 	var $events = array(
 | |
| 		'upload'
 | |
| 	);
 | |
| 
 | |
| 	function main() {
 | |
| 		if ($f = sess_remove('admin_uploader_files')) {
 | |
| 			$this->smarty->assign('uploaded_files', $f);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	function onupload() {
 | |
| 		$success = false;
 | |
| 
 | |
| 		/*
 | |
| 		 * first check if user is logged in
 | |
| 		 * to prevent remote admin.uploader.php script execution
 | |
| 		 *
 | |
| 		 * By testing the admin/main.php made the redirect job
 | |
| 		 * By direct URL call PHP throw a visible error -> AdminPanel class not found!
 | |
| 		 *
 | |
| 		 * 2019-11-23 - laborix
 | |
| 		 */
 | |
| 		if (!user_loggedin()) {
 | |
| 			utils_redirect("login.php");
 | |
| 			die();
 | |
| 		}
 | |
| 
 | |
| 		if (!file_exists(IMAGES_DIR))
 | |
| 			fs_mkdir(IMAGES_DIR);
 | |
| 
 | |
| 		if (!file_exists(ATTACHS_DIR))
 | |
| 			fs_mkdir(ATTACHS_DIR);
 | |
| 		/*
 | |
| 		 * Blacklist entries from OWASP and
 | |
| 		 * https://stackoverflow.com/questions/4166762/php-image-upload-security-check-list
 | |
| 		 *
 | |
| 		 * 2019-11-23 - laborix
 | |
| 		 */
 | |
| 		$blacklist_extensions = array(
 | |
| 			'htaccess',
 | |
| 			'pht',
 | |
| 			'phtm',
 | |
| 			'phtml',
 | |
| 			'ph2',
 | |
| 			'ph3',
 | |
| 			'ph4',
 | |
| 			'ph5',
 | |
| 			'ph6',
 | |
| 			'ph7',
 | |
| 			'ph8',
 | |
| 			'php',
 | |
| 			'php2',
 | |
| 			'php3',
 | |
| 			'php4',
 | |
| 			'php5',
 | |
| 			'php6',
 | |
| 			'php7',
 | |
| 			'php8',
 | |
| 			'phps',
 | |
| 			'cgi',
 | |
| 			'exe',
 | |
| 			'pl',
 | |
| 			'asp',
 | |
| 			'aspx',
 | |
| 			'shtml',
 | |
| 			'shtm',
 | |
| 			'fcgi',
 | |
| 			'fpl',
 | |
| 			'jsp',
 | |
| 			'htm',
 | |
| 			'html',
 | |
| 			'wml',
 | |
| 			'svg',
 | |
| 			'xml',
 | |
| 			'md',
 | |
| 			'pages',
 | |
| 			'xsig'
 | |
| 		);
 | |
| 
 | |
| 		$imgs = array(
 | |
| 			'.jpg',
 | |
| 			'.gif',
 | |
| 			'.png',
 | |
| 			'.jpeg'
 | |
| 		);
 | |
| 
 | |
| 		// intentionally
 | |
| 		// I've not put BMPs
 | |
| 
 | |
| 		$uploaded_files = array();
 | |
| 		$this->smarty->assign('uploaded_files', $uploaded_files);
 | |
| 
 | |
| 		foreach ($_FILES ["upload"] ["error"] as $key => $error) {
 | |
| 
 | |
| 			// Upload went wrong -> jump to the next file
 | |
| 			if ($error != UPLOAD_ERR_OK) {
 | |
| 				continue;
 | |
| 			}
 | |
| 
 | |
| 			$tmp_name = $_FILES ["upload"] ["tmp_name"] [$key];
 | |
| 			$name = $_FILES ["upload"] ["name"] [$key];
 | |
| 
 | |
| 			$dir = ATTACHS_DIR;
 | |
| 
 | |
| 			/*
 | |
| 			 * second check extension list
 | |
| 			 * https://stackoverflow.com/questions/4166762/php-image-upload-security-check-list
 | |
| 			 *
 | |
| 			 * 2019-11-24 - laborix
 | |
| 			 */
 | |
| 
 | |
| 			$uploadfilename = strtolower($name);
 | |
| 
 | |
| 			$isForbidden = false;
 | |
| 			$deeptest = array();
 | |
| 			$extcount = 0;
 | |
| 			$deeptest = explode('.', $uploadfilename);
 | |
| 			$extcount = count($deeptest);
 | |
| 
 | |
| 			if ($extcount == 1) {
 | |
| 				/*
 | |
| 				 * none extension like .jpg or something else
 | |
| 				 *
 | |
| 				 * possible filename = simple-file-without-extension - linux like ok
 | |
| 				 */
 | |
| 				$isForbidden = false;
 | |
| 			} elseif ($extcount == 2) {
 | |
| 				/*
 | |
| 				 * Only one possible extension
 | |
| 				 *
 | |
| 				 * possible filename = 1.jpg
 | |
| 				 * possible filename = admin.uploader.php
 | |
| 				 * possible filename = .htaccess
 | |
| 				 * and so on...
 | |
| 				 */
 | |
| 				$check_ext1 = "";
 | |
| 				$check_ext1 = trim($deeptest [1], "\x00..\x1F");
 | |
| 				if (in_array($check_ext1, $blacklist_extensions)) {
 | |
| 					$isForbidden = true;
 | |
| 				} else {
 | |
| 					$isForbidden = false;
 | |
| 				}
 | |
| 			} elseif ($extcount > 2) {
 | |
| 				/*
 | |
| 				 * Chekc only the last two possible extensions
 | |
| 				 *
 | |
| 				 * Hint: OWASP - Unrestricted File Upload
 | |
| 				 *
 | |
| 				 * In Apache, a php file might be executed using the
 | |
| 				 * double extension technique such as "file.php.jpg"
 | |
| 				 * when ".jpg" is allowed.
 | |
| 				 *
 | |
| 				 * possible filename = 1.PhP.jpg
 | |
| 				 * possible filename = admin.uploader.php.JPg
 | |
| 				 * and so on...
 | |
| 				 */
 | |
| 				$check_ext1 = "";
 | |
| 				$check_ext2 = "";
 | |
| 				$check_ext1 = trim($deeptest [$extcount - 1], "\x00..\x1F");
 | |
| 				if (in_array($check_ext1, $blacklist_extensions)) {
 | |
| 					$isForbidden = true;
 | |
| 				} else {
 | |
| 					$isForbidden = false;
 | |
| 				}
 | |
| 				/* Test only if first extension check are not in the blacklist */
 | |
| 				if (!$isForbidden) {
 | |
| 					$check_ext2 = trim($deeptest [$extcount - 2], "\x00..\x1F");
 | |
| 					if (in_array($check_ext2, $blacklist_extensions)) {
 | |
| 						$isForbidden = true;
 | |
| 					} else {
 | |
| 						$isForbidden = false;
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 			/*
 | |
| 			 * If one blacklisted extension found then
 | |
| 			 * return with -1 = An error occurred while trying to upload.
 | |
| 			 */
 | |
| 			if ($isForbidden) {
 | |
| 				$this->smarty->assign('success', $success ? 1 : -1);
 | |
| 				sess_add('admin_uploader_files', $uploaded_files);
 | |
| 				return -1;
 | |
| 			}
 | |
| 
 | |
| 			/*
 | |
| 			 * third check extension
 | |
| 			 * if someone upload a .php file as .gif, .jpg or .txt
 | |
| 			 * if someone upload a .html file as .gif, .jpg or .txt
 | |
| 			 *
 | |
| 			 * 2019-11-24 - laborix
 | |
| 			 */
 | |
| 
 | |
| 			if (version_compare(PHP_VERSION, '5.3.0') < 0)
 | |
| 				return -1;
 | |
| 			if (!function_exists('finfo_open'))
 | |
| 				return -1;
 | |
| 
 | |
| 			$finfo = finfo_open(FILEINFO_MIME_TYPE);
 | |
| 			$mime = finfo_file($finfo, $tmp_name);
 | |
| 			finfo_close($finfo);
 | |
| 
 | |
| 			if (($mime == "text/x-php") || ($mime == "text/html")) {
 | |
| 				$this->smarty->assign('success', $success ? 1 : -1);
 | |
| 				sess_add('admin_uploader_files', $uploaded_files);
 | |
| 				return -1;
 | |
| 			}
 | |
| 
 | |
| 			$ext = strtolower(strrchr($name, '.'));
 | |
| 
 | |
| 			if (in_array($ext, $imgs)) {
 | |
| 				$dir = IMAGES_DIR;
 | |
| 			}
 | |
| 
 | |
| 			$name = sanitize_title(substr($name, 0, -strlen($ext))) . $ext;
 | |
| 
 | |
| 			$target = "$dir/$name";
 | |
| 			@umask(022);
 | |
| 			$success = move_uploaded_file($tmp_name, $target);
 | |
| 			@chmod($target, 0766);
 | |
| 
 | |
| 			$uploaded_files [] = $name;
 | |
| 
 | |
| 			// one failure will make $success == false :)
 | |
| 			$success &= $success;
 | |
| 		}
 | |
| 
 | |
| 		if ($uploaded_files) {
 | |
| 			$this->smarty->assign('success', $success ? 1 : -1);
 | |
| 			sess_add('admin_uploader_files', $uploaded_files);
 | |
| 		}
 | |
| 
 | |
| 		return 1;
 | |
| 	}
 | |
| 
 | |
| }
 | |
| 
 | |
| ?>
 | 
