CVE-2020-19678: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') (CWE-22)
value: Directory Traversal vulnerability found in Pfsense v.2.1.3 and Pfsense Suricata v.1.4.6 pkg v.1.0.1 allows a remote attacker to obtain sensitive information via the file parameter to suricata/suricata_logs_browser.php.
CWE description: 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.
CVSS v3 base score: 7.5
Published: 2023-04-06T18:15Z
Repository: https://github.com/pfsense/pfsense-packages
Language: PHP
Files changed: config/suricata/suricata_logs_browser.php
Commit date: 2014-05-20 08:59:44 -0400
Commit message: Fix file browser vulnerability on LOGS BROWSER tab.

Diff: diff --git a/config/suricata/suricata_logs_browser.php b/config/suricata/suricata_logs_browser.php
index 04edf373..566ab93f 100644
--- a/config/suricata/suricata_logs_browser.php
+++ b/config/suricata/suricata_logs_browser.php
@@ -53,25 +53,26 @@ if (!is_array($config['installedpackages']['suricata']['rule']))
 $a_instance = $config['installedpackages']['suricata']['rule'];
 $suricata_uuid = $a_instance[$instanceid]['uuid'];
 $if_real = get_real_interface($a_instance[$instanceid]['interface']);
 
 // Construct a pointer to the instance's logging subdirectory
-$suricatalogdir = SURICATALOGDIR . "suricata_{$if_real}{$suricata_uuid}";
+$suricatalogdir = SURICATALOGDIR . "suricata_{$if_real}{$suricata_uuid}/";
 
-$logfile = $_POST['file'];
+// Limit all file access to just the currently selected interface's logging subdirectory
+$logfile = htmlspecialchars($suricatalogdir . basename($_POST['file']));
 
 if ($_POST['action'] == 'load') {
-	if(!is_file($_POST['file'])) {
+	if(!is_file($logfile)) {
 		echo "|3|" . gettext("Log file does not exist or that logging feature is not enabled") . ".|";
 	}
 	else {
-		$data = file_get_contents($_POST['file']);
+		$data = file_get_contents($logfile);
 		if($data === false) {
 			echo "|1|" . gettext("Failed to read log file") . ".|";
 		} else {
 			$data = base64_encode($data);
-			echo "|0|{$_POST['file']}|{$data}|";	
+			echo "|0|{$logfile}|{$data}|";	
 		}
 	}
 	exit;
 }
 
@@ -178,11 +179,11 @@ if ($input_errors) {
 				$logs = array( "alerts.log", "block.log", "files-json.log", "http.log", "stats.log", "suricata.log", "tls.log" );
 				foreach ($logs as $log) {
 					$selected = "";
 					if ($log == basename($logfile))
 						$selected = "selected";
-					echo "<option value='{$suricatalogdir}/{$log}' {$selected}>" . $log . "</option>\n";
+					echo "<option value='{$suricatalogdir}{$log}' {$selected}>" . $log . "</option>\n";
 				}
 			?>
 					</select>&nbsp;&nbsp;<?php echo gettext('Choose which log you want to view.'); ?>
 				</td>
 			</tr>
@@ -220,11 +221,11 @@ if ($input_errors) {
 	</td>
 	</tr>
 </table>
 </form>
 
-<?php if(empty($logfile)): ?>
+<?php if(empty($_POST['file'])): ?>
 <script type="text/javascript">
 	document.getElementById("logFile").selectedIndex=-1;
 </script>
 <?php endif; ?>
 

Vulnerable code: $suricatalogdir = SURICATALOGDIR . "suricata_{$if_real}{$suricata_uuid}";
$logfile = $_POST['file'];
	if(!is_file($_POST['file'])) {
		$data = file_get_contents($_POST['file']);
			echo "|0|{$_POST['file']}|{$data}|";	
					echo "<option value='{$suricatalogdir}/{$log}' {$selected}>" . $log . "</option>\n";
<?php if(empty($logfile)): ?>
Fixed code: $suricatalogdir = SURICATALOGDIR . "suricata_{$if_real}{$suricata_uuid}/";
// Limit all file access to just the currently selected interface's logging subdirectory
$logfile = htmlspecialchars($suricatalogdir . basename($_POST['file']));
	if(!is_file($logfile)) {
		$data = file_get_contents($logfile);
			echo "|0|{$logfile}|{$data}|";	
					echo "<option value='{$suricatalogdir}{$log}' {$selected}>" . $log . "</option>\n";
<?php if(empty($_POST['file'])): ?>