CVE-2020-13795 (PHP, published 2020-06-03T22:15Z)
Description: value: An issue was discovered in Navigate CMS through 2.8.7. It allows Directory Traversal because lib/packages/templates/template.class.php mishandles ../ and ..\ substrings.
Severity: MEDIUM (CVSS v3 base score: 5.3)
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/templates/template.class.php
lib/packages/templates/templates.php
lib/packages/themes/themes.php
Commit message: * template.class: filter file location path


Vulnerable code:
		$this->file			= $main->file;
				$template = $ws_theme->templates[$t];
		if(!$template) return;
		$this->file			= $_REQUEST['file'];
			if(empty($_REQUEST['template-sections-code'][$s])) continue;
			return $this->update();
			return $this->insert();			
		$navibars->title(t(20, 'Templates').' / '.t(38, 'Create'));	
		$navibars->title(t(20, 'Templates').' / '.t(170, 'Edit').' ['.$item->id.']');		
		$navibars->add_actions(		array(	'<a href="#" onclick="navigate_tabform_submit(1);"><img height="16" align="absmiddle" width="16" src="img/icons/silk/accept.png"> '.t(34, 'Save').'</a>'	)
									);
		$navibars->add_actions(		array(	'<a href="#" onclick="navigate_tabform_submit(1);"><img height="16" align="absmiddle" width="16" src="img/icons/silk/accept.png"> '.t(34, 'Save').'</a>',
											'<a href="#" onclick="navigate_delete_dialog();"><img height="16" align="absmiddle" width="16" src="img/icons/silk/cancel.png"> '.t(35, 'Delete').'</a>'
										)
									);		
	$navibars->add_actions(	array(	(!empty($item->id)? '<a href="?fid=templates&act=2"><img height="16" align="absmiddle" width="16" src="img/icons/silk/add.png"> '.t(38, 'Create').'</a>' : ''),
									'<a href="?fid=templates&act=0"><img height="16" align="absmiddle" width="16" src="img/icons/silk/application_view_list.png"> '.t(39, 'List').'</a>',
									'search_form' ));
	$navibars->add_tab_content_row(array(	'<label>ID</label>',
											'<span>'.(!empty($item->id)? $item->id : t(52, '(new)')).'</span>' ));
	$navibars->add_tab_content_row(array(	'<label>'.t(67, 'Title').'</label>',
											$naviforms->textfield('title', $item->title),
										));		
        $navibars->add_tab_content_row(array(	'<label>'.t(82, 'File').'</label>',
                                                        '<span>'.$item->file.'</span>'
                                                    ));
	$navibars->add_tab_content_row(array(	'<label>'.t(68, 'Status').'</label>',
											$naviforms->selectfield('permission', 
												array(
														0 => 0,
														1 => 1,
														2 => 2
													),
												array(
														0 => t(69, 'Published'),
														1 => t(70, 'Private'),
														2 => t(81, 'Hidden')
													),
												$item->permission,
												'',
												false,
												array(
														0 => t(360, 'Visible to everybody'),
														1 => t(359, 'Visible only to Navigate CMS users'),
														2 => t(358, 'Hidden to everybody')												
												)
											)
										)
									);						
	$navibars->add_tab_content_row(array(	'<label>'.t(62, 'Statistics').'</label>',
											$naviforms->checkbox('statistics', $item->statistics),
										));																									
	$navibars->add_tab_content_row(array(	'<label>'.t(65, 'Enabled').'</label>',
											$naviforms->checkbox('enabled', $item->enabled),
										));	
			$table->addRow($p, array(
					array('content' => '<input type="text" name="template-sections-code[]" value="'.$item->sections[$p]['code'].'" style="width: 140px;" />', 'align' => 'left'),			
					array('content' => '<input type="text" name="template-sections-name[]" value="'.template::section_name($item->sections[$p]['name']).'" style="width: 290px;" />', 'align' => 'left'),
					array('content' => $select_editor, 'align' => 'left'),
					array('content' => '<div style=" white-space: nowrap; "><input type="text" name="template-sections-width[]" value="'.template::section_name($item->sections[$p]['width']).'" style="width: 40px;" /> px</div>', 'align' => 'left'),
					array('content' => ((!empty($disabled) || $readonly)? '' : '<img src="'.NAVIGATE_URL.'/img/icons/silk/cancel.png" onclick="navigate_templates_sections_remove(this);" />'), 'align' => 'center')
				));			
            $navibars->add_tab_content_row(array(	'<label>'.t(236, 'Sections').'</label>',
                                                    '<div>'.$table->generate().'</div>'));
            $navibars->add_tab_content_row(array(	'<label>'.t(236, 'Sections').'</label>',
                                                    '<div>'.$table->generate().'</div>',
                                                    '<div class="subcomment">
                                                        <img src="img/icons/silk/information.png" align="absmiddle" /> '.t(72, 'Drag any row to assign priorities').'.
                                                         '.t(192, 'Double click any row to edit').'
                                                    </div>' ));

            $navibars->add_tab_content_row(array(	'<label>&nbsp;</label>',
                                                    '<button id="templates-sections-create"><img src="img/icons/silk/add.png" align="absmiddle" style="cursor:pointer;" /> '.t(38, 'Create').'</button>'));
			</form>');
		$navibars->add_tab_content_row(array(	'<label>'.t(210, 'Gallery').'</label>',
												$naviforms->checkbox('gallery', $item->gallery),
											));	
		$navibars->add_tab_content_row(array(	'<label>'.t(250, 'Comments').'</label>',
												$naviforms->checkbox('comments', $item->comments),
											));	
		$navibars->add_tab_content_row(array(	'<label>'.t(265, 'Tags').'</label>',
												$naviforms->checkbox('tags', $item->tags),
											));												
        $element_types = array(	'item'	=> 	t(180, 'Item'),
								'structure' => t(16, 'Structure')/*,
								'product' => t(214, 'Product')*/);
			$table->addRow($properties[$p]->id, array(
					array('content' => $properties[$p]->name, 'align' => 'left'),
					array('content' => $types[$properties[$p]->type], 'align' => 'left'),
					array('content' => $element_types[$properties[$p]->element], 'align' => 'left'),					
					array('content' => '<input type="checkbox" name="property-enabled[]" class="raw-checkbox" value="'.$properties[$p]->id.'" '.(($properties[$p]->enabled=='1'? ' checked=checked ' : '')).' />', 'align' => 'center'),
				));
            $navibars->add_tab_content_row(array(	'<label>'.t(77, 'Properties').'</label>',
                                                    '<div>'.$table->generate().'</div>'));
            $navibars->add_tab_content_row(array(	'<label>'.t(77, 'Properties').'</label>',
                                                    '<div>'.$table->generate().'</div>',
                                                    '<div class="subcomment">
                                                        <img src="img/icons/silk/information.png" align="absmiddle" /> '.t(72, 'Drag any row to assign priorities').'.
                                                         '.t(192, 'Double click any row to edit').'
                                                    </div>' ));

            $navibars->add_tab_content_row(array(	'<label>&nbsp;</label>',
                                                    '<button id="templates-properties-create"><img src="img/icons/silk/add.png" align="absmiddle" /> '.t(38, 'Create').'</button>'));
	$DB->query('SELECT sections
				  FROM nv_templates
				 WHERE website = '.intval($website->id),
				'array');
		if(!is_array($sections)) $sections = array();
                $tmp_file = sys_get_temp_dir().DIRECTORY_SEPARATOR.$query['code'].'.zip';

Fixed code:
		$this->file			= str_replace(array('../', '..\\'), '', $main->file);
            {
                $template = $ws_theme->templates[$t];
            }
		if(!$template)
        {
            return;
        }
        // filter file path
        $template->file = str_replace(array('../', '..\\'), '', $template->file);

                {
                }
		$this->file			= str_replace(array('../', '..\\'), '', $_REQUEST['file']);
			if(empty($_REQUEST['template-sections-code'][$s]))
            {
                continue;
            }
        {
            return $this->update();
        }
        {
            return $this->insert();
        }
    {
        $navibars->title(t(20, 'Templates').' / '.t(38, 'Create'));
    }
    {
        $navibars->title(t(20, 'Templates').' / '.t(170, 'Edit').' ['.$item->id.']');
    }
		$navibars->add_actions(
		    array(
		        '<a href="#" onclick="navigate_tabform_submit(1);"><img height="16" align="absmiddle" width="16" src="img/icons/silk/accept.png"> '.t(34, 'Save').'</a>'
            )
        );
		$navibars->add_actions(
		    array(
		        '<a href="#" onclick="navigate_tabform_submit(1);"><img height="16" align="absmiddle" width="16" src="img/icons/silk/accept.png"> '.t(34, 'Save').'</a>',
                '<a href="#" onclick="navigate_delete_dialog();"><img height="16" align="absmiddle" width="16" src="img/icons/silk/cancel.png"> '.t(35, 'Delete').'</a>'
            )
        );
	$navibars->add_actions(
	    array(
	        (!empty($item->id)? '<a href="?fid=templates&act=2"><img height="16" align="absmiddle" width="16" src="img/icons/silk/add.png"> '.t(38, 'Create').'</a>' : ''),
            '<a href="?fid=templates&act=0"><img height="16" align="absmiddle" width="16" src="img/icons/silk/application_view_list.png"> '.t(39, 'List').'</a>',
			'search_form'
        )
    );
	$navibars->add_tab_content_row(
	    array(
	        '<label>ID</label>',
			'<span>'.(!empty($item->id)? $item->id : t(52, '(new)')).'</span>'
        )
    );
	$navibars->add_tab_content_row(
	    array(
	        '<label>'.t(67, 'Title').'</label>',
			$naviforms->textfield('title', $item->title),
        )
    );
        $navibars->add_tab_content_row(
            array(
                '<label>'.t(82, 'File').'</label>',
                '<span>'.$item->file.'</span>'
            )
        );
	$navibars->add_tab_content_row(
	    array(
	        '<label>'.t(68, 'Status').'</label>',
			$naviforms->selectfield(
			    'permission',
                array(
                        0 => 0,
                        1 => 1,
                        2 => 2
                ),
                array(
                        0 => t(69, 'Published'),
                        1 => t(70, 'Private'),
                        2 => t(81, 'Hidden')
                ),
                $item->permission,
                '',
                false,
                array(
                        0 => t(360, 'Visible to everybody'),
                        1 => t(359, 'Visible only to Navigate CMS users'),
                        2 => t(358, 'Hidden to everybody')
                )
            )
        )
    );
	$navibars->add_tab_content_row(
	    array(
	        '<label>'.t(62, 'Statistics').'</label>',
			$naviforms->checkbox('statistics', $item->statistics),
        )
    );
	$navibars->add_tab_content_row(
	    array(
	        '<label>'.t(65, 'Enabled').'</label>',
			$naviforms->checkbox('enabled', $item->enabled),
        )
    );
			$table->addRow(
                $p,
                array(
                    array('content' => '<input type="text" name="template-sections-code[]" value="'.$item->sections[$p]['code'].'" style="width: 140px;" />', 'align' => 'left'),
                    array('content' => '<input type="text" name="template-sections-name[]" value="'.template::section_name($item->sections[$p]['name']).'" style="width: 290px;" />', 'align' => 'left'),
                    array('content' => $select_editor, 'align' => 'left'),
                    array('content' => '<div style=" white-space: nowrap; "><input type="text" name="template-sections-width[]" value="'.template::section_name($item->sections[$p]['width']).'" style="width: 40px;" /> px</div>', 'align' => 'left'),
                    array('content' => ((!empty($disabled) || $readonly)? '' : '<img src="'.NAVIGATE_URL.'/img/icons/silk/cancel.png" onclick="navigate_templates_sections_remove(this);" />'), 'align' => 'center')
                )
            );
            $navibars->add_tab_content_row(
                array(
                    '<label>'.t(236, 'Sections').'</label>',
                    '<div>'.$table->generate().'</div>'
                )
            );
            $navibars->add_tab_content_row(
                array(
                    '<label>'.t(236, 'Sections').'</label>',
                    '<div>'.$table->generate().'</div>',
                    '<div class="subcomment">
                        <img src="img/icons/silk/information.png" align="absmiddle" /> '.t(72, 'Drag any row to assign priorities').'.
                         '.t(192, 'Double click any row to edit').'
                    </div>'
                )
            );

            $navibars->add_tab_content_row(
                array(
                    '<label>&nbsp;</label>',
                    '<button id="templates-sections-create"><img src="img/icons/silk/add.png" align="absmiddle" style="cursor:pointer;" /> '.t(38, 'Create').'</button>'
                )
            );
			</form>'
        );
		$navibars->add_tab_content_row(
		    array(
		        '<label>'.t(210, 'Gallery').'</label>',
				$naviforms->checkbox('gallery', $item->gallery),
            )
        );
		$navibars->add_tab_content_row(
		    array(
		        '<label>'.t(250, 'Comments').'</label>',
				$naviforms->checkbox('comments', $item->comments),
            )
        );
		$navibars->add_tab_content_row(
		    array(
		        '<label>'.t(265, 'Tags').'</label>',
				$naviforms->checkbox('tags', $item->tags),
            )
        );
        $element_types = array(
            'item'	=> 	t(180, 'Item'),
			'structure' => t(16, 'Structure'),
			'product' => t(214, 'Product')
        );
			$table->addRow(
                $properties[$p]->id,
                array(
                    array('content' => $properties[$p]->name, 'align' => 'left'),
                    array('content' => $types[$properties[$p]->type], 'align' => 'left'),
                    array('content' => $element_types[$properties[$p]->element], 'align' => 'left'),
                    array('content' => '<input type="checkbox" name="property-enabled[]" class="raw-checkbox" value="'.$properties[$p]->id.'" '.(($properties[$p]->enabled=='1'? ' checked=checked ' : '')).' />', 'align' => 'center'),
                )
            );
            $navibars->add_tab_content_row(
                array(
                    '<label>'.t(77, 'Properties').'</label>',
                    '<div>'.$table->generate().'</div>'
                )
            );
            $navibars->add_tab_content_row(
                array(
                    '<label>'.t(77, 'Properties').'</label>',
                    '<div>'.$table->generate().'</div>',
                    '<div class="subcomment">
                        <img src="img/icons/silk/information.png" align="absmiddle" /> '.t(72, 'Drag any row to assign priorities').'.
                         '.t(192, 'Double click any row to edit').'
                    </div>'
                )
            );

            $navibars->add_tab_content_row(
                array(
                    '<label>&nbsp;</label>',
                    '<button id="templates-properties-create"><img src="img/icons/silk/add.png" align="absmiddle" /> '.t(38, 'Create').'</button>'
                )
            );
	$DB->query(
	    'SELECT sections
              FROM nv_templates
             WHERE website = '.intval($website->id),

        'array'
    );
		if(!is_array($sections))
        {
            $sections = array();
        }
                $tmp_file = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $query['code'] . '.zip';
                    {
                    }