CVE-2018-17553 (PHP, published 2018-10-03T20:29Z)
Description: value: An "Unrestricted Upload of File with Dangerous Type" issue with directory traversal in navigate_upload.php in Naviwebs Navigate CMS 2.8 allows authenticated attackers to achieve remote code execution via a POST request with engine=picnik and id=../../../navigate_info.php.
Severity: MEDIUM (CVSS v3 base score: 8.8)
Weakness: CWE-22 \u2014 Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.
Repository: https://github.com/NavigateCMS/Navigate-CMS
Files changed:
lib/packages/files/files.php
navigate_upload.php
Commit message: - files: removed unused code related to "picnik" upload


Vulnerable code:
		/*	
		case 91: // picnik editing
			ob_clean();
			
			// $strPicnikUrl is the URL that we use to launch Picnik.
			$strPicnikUrl = "http://www.picnik.com/service";	
			// $aPicnikParams collects together all the params we'll give Picnik.  Start with an API key
			$aPicnikParams['_apikey'] = $website->picnik_api_key;
			// tell Picnik where to send the exported image
			$aPicnikParams['_export'] = NAVIGATE_URL.'/navigate_upload.php?wid='.$website->id.'&engine=picnik&id='.$_REQUEST['id'].'&engine=picnik&session_id='.session_id();
			// give the export button a title
			$aPicnikParams['_export_title'] = t(34, 'Save');
			// turn on the close button, and tell it to come back here
			//$aPicnikParams['_close_target'] = $strRoot;
			// send in the previous "king" image in case the user feels like decorating it
			$aPicnikParams['_import'] = NAVIGATE_DOWNLOAD.'?wid='.$website->id.'&id='.$_REQUEST['id'].'&disposition=attachment&sid='.session_id();	
			// tell Picnik to redirect the user to the following URL after the HTTP POST instead of just redirecting to _export
			$aPicnikParams['_redirect'] = NAVIGATE_DOWNLOAD.'?wid='.$website->id.'&id='.$_REQUEST['id'].'&disposition=inline&ts='.core_time(); //'javascript: return false;';
		
			// tell Picnik our name.  It'll use it in a few places as appropriate
			$aPicnikParams['_host_name'] = 'Navigate';
			// turn off the "Save &amp; Share" tab so users don't get confused
			$aPicnikParams['_exclude'] = "out";
		
			echo '<html><head></head><body>';
		
			echo '<form id="picnik_form" method="POST" action="'.$strPicnikUrl.'" style=" visibility: hidden; ">';
			
			// put all the API parameters into the form as hidden inputs
			foreach( $aPicnikParams as $key => $value ) {
				echo "<input type='hidden' name='$key' value='$value'/>\n";
			}
			
			//echo "<input type='text' name='address' value='Your Majesty'/>\n";
			echo "<input type='submit' value='Picnik'/>\n";
			echo "</form>";
			echo '<script language="javascript" type="text/javascript">
					document.forms[0].submit();
				  </script>';
			echo '</body></html>';

			core_terminate();
			break;
		*/
// no maximum uploading / execution time
//file_put_contents(NAVIGATE_PRIVATE.'/'.$website->id.'/files/out.txt', print_r($_FILES, true));

else if($_REQUEST['engine']=='picnik')
{
	// PHP script to receive image data from Picnik via HTTP POST
	// retrieve the image's attributes from the $_FILES array
	$image_tmp_filename = $_FILES['file']['tmp_name'];
	$image_filename = $_FILES['file']['name'];
	
	// Save the image to disk.  It'll go into the same directory as
	// this script.  You'd probably want to put it somewhere else in the
	// file system like a "/images" directory, or maybe even into a database.
	// Make sure your web server has write access to the destination dir,
	// or the call to file_put_contents isn't going to work.
	$image_data = file_get_contents( $image_tmp_filename );
	
	if(!empty($_REQUEST['id']) && file_exists($targetDir.'/'.$_REQUEST['id']))
	{	
		file_put_contents( $targetDir.'/'.$_REQUEST['id'], $image_data );
	}
	
	core_terminate();
}

Fixed code:
// no maximum uploading/execution time