CVE-2022-39296: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') (CWE-22)
value: MelisAssetManager provides deliveries of Melis Platform's assets located in every module's public folder. Attackers can read arbitrary files on affected versions of `melisplatform/melis-asset-manager`, leading to the disclosure of sensitive information. Conducting this attack does not require authentication. Users should immediately upgrade to `melisplatform/melis-asset-manager` >= 5.0.1. This issue was addressed by restricting access to files to intended directories only.
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: 2022-10-11T18:15Z
Repository: https://github.com/melisplatform/melis-asset-manager
Language: PHP
Files changed: src/Module.php
Commit date: 2022-09-26 16:49:23 +0800
Commit message: added checking if the requested file is inside the intended directory

Diff: diff --git a/src/Module.php b/src/Module.php
index 8154ec5..a9192d2 100644
--- a/src/Module.php
+++ b/src/Module.php
@@ -146,11 +146,11 @@ class Module
             $UriParams = $UriWithoutParams[1];
         
         
         // First check if asset in main public folder
         $pathFile = $_SERVER['DOCUMENT_ROOT'] . $UriWithoutParams;
-        if (is_file($pathFile))
+        if (is_file($pathFile) && $this->checkFileInFolder($pathFile, $_SERVER['DOCUMENT_ROOT']))
             $this->sendDocument($pathFile, $UriParams);
         else
         {
             // testing module public folder second
             if (file_exists($assetConfigFolder . $this->modulePathFile))
@@ -179,11 +179,11 @@ class Module
                         for ($i = 2; $i < count($detailUri); $i++)
                             $pathFile .= '/' . $detailUri[$i];
     
                         if ($pathFile != '')
                         {
-                            if (is_file($pathFile))
+                            if (is_file($pathFile) && $this->checkFileInFolder($pathFile, $path . '/public/'))
                                 $this->sendDocument($pathFile, $UriParams);
                         }
                     }
                 }
             }
@@ -261,6 +261,20 @@ class Module
                 ],
             ],
         ];
     }
 
+     /*checks if the file is inside the given folder*/
+    protected function checkFileInFolder($file, $folder)
+    {       
+        $path = realpath($file);        
+        if ($path !== false) {
+            if (strpos($path, realpath($folder)) !== 0) {                   
+                throw new \Exception('Requested resource is outside of ' . $folder);
+            } else {              
+                return true;
+            }
+        } else {                   
+            return false;
+        }
+    }
 }

Vulnerable code:         if (is_file($pathFile))
                            if (is_file($pathFile))
Fixed code:         if (is_file($pathFile) && $this->checkFileInFolder($pathFile, $_SERVER['DOCUMENT_ROOT']))
                            if (is_file($pathFile) && $this->checkFileInFolder($pathFile, $path . '/public/'))
     /*checks if the file is inside the given folder*/
    protected function checkFileInFolder($file, $folder)
    {       
        $path = realpath($file);        
        if ($path !== false) {
            if (strpos($path, realpath($folder)) !== 0) {                   
                throw new \Exception('Requested resource is outside of ' . $folder);
            } else {              
                return true;
            }
        } else {                   
            return false;
        }
    }