CVE-2020-15246 (published 2020-11-23T20:15Z)

October is a free, open-source, self-hosted CMS platform based on the Laravel PHP Framework. In October CMS from version 1.0.421 and before version 1.0.469, an attacker can read local files on an October CMS server via a specially crafted request. Issue has been patched in Build 469 (v1.0.469) and v1.1.0.

Severity: MEDIUM
CVSS v2 base score: 5.0 (AV:N/AC:L/Au:N/C:P/I:N/A:N)
CVSS v3 base score: 7.5, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N)

Weakness information:
cwe_id: CWE-22
cwe_name: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
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.
extended_description: 
            Many file operations are intended to take place within a restricted directory. By using special elements such as ".." and "/" separators, attackers can escape outside of the restricted location to access files or directories that are elsewhere on the system. One of the most common special elements is the "../" sequence, which in most modern operating systems is interpreted as the parent directory of the current location. This is referred to as relative path traversal. Path traversal also covers the use of absolute pathnames such as "/usr/local/bin" to access unexpected files. This is referred to as absolute path traversal.
         
         

Fix information:
repo_url: https://github.com/octobercms/library
commit_details: repo_url: https://github.com/octobercms/library
author: Luke Towers
author_date: 2020-09-03 20:54:11-06:00
msg: Security fixes for v1.0.469

Temporarily disables SVG uploads
Improves path validation in FileDatasource & reorgs / cleans up Halcyon Builder
Adds XSS filtering to SystemException messages (related https://github.com/octobercms/library/commit/c16fefde03080fe2b3937e565d9cdf7b70291384#diff-4915b631d3234e0c5232490be34effe4)
repository: repo_url: https://github.com/octobercms/library
repo_name: octobercms/library
description: October Rain Library
repo_language: PHP
owner: octobercms
file_changes: filename: SystemException.php
change_type: ModificationType.MODIFY
diff: @@ -1,12 +1,29 @@
 <?php namespace October\Rain\Exception;
 
+use Exception;
+use October\Rain\Html\HtmlBuilder;
+
 /**
  * This class represents a critical system exception.
  * System exceptions are logged in the error log.
  *
  * @package october\exception
- * @author Alexey Bobkov, Samuel Georges
+ * @author Alexey Bobkov, Samuel Georges, Luke Towers
  */
 class SystemException extends ExceptionBase
 {
+    /**
+     * Override the constructor to escape all messages to protect against potential XSS
+     * from user provided inputs being included in the exception message
+     *
+     * @param string $message Error message.
+     * @param int $code Error code.
+     * @param Exception $previous Previous exception.
+     */
+    public function __construct($message = "", $code = 0, Exception $previous = null)
+    {
+        $message = HtmlBuilder::clean($message);
+
+        parent::__construct($message, $code, $previous);
+    }
 }

programming_language: PHP
filename: Definitions.php
change_type: ModificationType.MODIFY
diff: @@ -103,7 +103,6 @@ class Definitions
             'png',
             'webp',
             'gif',
-            'svg',
             'js',
             'map',
             'ico',
@@ -163,7 +162,6 @@ class Definitions
             'js',
             'woff',
             'woff2',
-            'svg',
             'ttf',
             'eot',
             'json',

programming_language: PHP
filename: Builder.php
change_type: ModificationType.MODIFY
diff: @@ -142,79 +142,99 @@ class Builder
     }
 
     /**
-     * Switches mode to select a single template by its name.
+     * Get the compiled file content representation of the query.
      *
-     * @param  string  $fileName
-     * @return $this
+     * @return string
      */
-    public function whereFileName($fileName)
+    public function toCompiled()
     {
-        $this->selectSingle = $this->model->getFileNameParts($fileName);
-
-        return $this;
+        return $this->processor->processUpdate($this, []);
     }
 
     /**
-     * Set the directory name which the query is targeting.
+     * Get an array with the values of a given column.
      *
-     * @param  string  $dirName
-     * @return $this
+     * @param  string  $column
+     * @param  string  $key
+     * @return array
      */
-    public function from($dirName)
+    public function lists($column, $key = null)
     {
-        $this->from = $dirName;
+        $select = is_null($key) ? [$column] : [$column, $key];
 
-        return $this;
+        if (!is_null($this->cacheMinutes)) {
+            $results = $this->getCached($select);
+        }
+        else {
+            $results = $this->getFresh($select);
+        }
+
+        $collection = new Collection($results);
+
+        return $collection->lists($column, $key);
     }
 
     /**
-     * Set the "offset" value of the query.
+     * Set the "limit" value of the query.
      *
      * @param  int  $value
      * @return $this
      */
-    public function offset($value)
+    public function limit($value)
     {
-        $this->offset = max(0, $value);
+        if ($value >= 0) {
+            $this->limit = $value;
+        }
 
         return $this;
     }
 
     /**
-     * Alias to set the "offset" value of the query.
+     * Alias to set the "limit" value of the query.
      *
      * @param  int  $value
      * @return \October\Rain\Halcyon\Builder|static
      */
-    public function skip($value)
+    public function take($value)
     {
-        return $this->offset($value);
+        return $this->limit($value);
     }
 
     /**
-     * Set the "limit" value of the query.
+     * Set the "offset" value of the query.
      *
      * @param  int  $value
      * @return $this
      */
-    public function limit($value)
+    public function offset($value)
     {
-        if ($value >= 0) {
-            $this->limit = $value;
-        }
+        $this->offset = max(0, $value);
 
         return $this;
     }
 
     /**
-     * Alias to set the "limit" value of the query.
+     * Alias to set the "offset" value of the query.
      *
      * @param  int  $value
      * @return \October\Rain\Halcyon\Builder|static
      */
-    public function take($value)
+    public function skip($value)
     {
-        return $this->limit($value);
+        return $this->offset($value);
+    }
+
+    /**
+     * Set the directory name which the query is targeting.
+     *
+     * @param  string  $dirName
+     * @return $this
+     */
+    public function from($dirName)
+    {
+        $this->from = $dirName;
+
+        return $this;
     }
 
     /**
@@ -239,46 +259,18 @@ class Builder
     }
 
     /**
-     * Execute the query as a "select" statement.
-     *
-     * @param  array  $columns
-     * @return \October\Rain\Halcyon\Collection|static[]
-     */
-    public function get($columns = ['*'])
-    {
-        if (!is_null($this->cacheMinutes)) {
-            $results = $this->getCached($columns);
-        }
-        else {
-            $results = $this->getFresh($columns);
-        }
-
-        $models = $this->getModels($results ?: []);
-
-        return $this->model->newCollection($models);
-    }
-
-    /**
-     * Get an array with the values of a given column.
+     * Switches mode to select a single template by its name.
      *
-     * @param  string  $column
-     * @param  string  $key
-     * @return array
+     * @param  string  $fileName
+     * @return $this
      */
-    public function lists($column, $key = null)
+    public function whereFileName($fileName)
     {
-        $select = is_null($key) ? [$column] : [$column, $key];
-
-        if (!is_null($this->cacheMinutes)) {
-            $results = $this->getCached($select);
-        }
-        else {
-            $results = $this->getFresh($select);
-        }
+        $this->validateFileName($fileName);
 
-        $collection = new Collection($results);
+        $this->selectSingle = $this->model->getFileNameParts($fileName);
 
-        return $collection->lists($column, $key);
+        return $this;
     }
 
     /**
@@ -321,30 +313,23 @@ class Builder
     }
 
     /**
-     * Set a model instance for the model being queried.
+     * Execute the query as a "select" statement.
      *
-     * @param  \October\Rain\Halcyon\Model  $model
-     * @return $this
+     * @param  array  $columns
+     * @return \October\Rain\Halcyon\Collection|static[]
      */
-    public function setModel(Model $model)
+    public function get($columns = ['*'])
     {
-        $this->model = $model;
-
-        $this->extensions = $this->model->getAllowedExtensions();
-
-        $this->from($this->model->getObjectTypeDirName());
+        if (!is_null($this->cacheMinutes)) {
+            $results = $this->getCached($columns);
+        }
+        else {
+            $results = $this->getFresh($columns);
+        }
 
-        return $this;
-    }
+        $models = $this->getModels($results ?: []);
 
-    /**
-     * Get the compiled file content representation of the query.
-     *
-     * @return string
-     */
-    public function toCompiled()
-    {
-        return $this->processor->processUpdate($this, []);
+        return $this->model->newCollection($models);
     }
 
     /**
@@ -408,10 +393,9 @@ class Builder
     /**
      * Delete a record from the database.
      *
-     * @param  string  $fileName
      * @return int
      */
-    public function delete($fileName = null)
+    public function delete()
     {
         $this->validateFileName();
 
@@ -442,6 +426,33 @@ class Builder
         );
     }
 
+    /**
+     * Set a model instance for the model being queried.
+     *
+     * @param  \October\Rain\Halcyon\Model  $model
+     * @return $this
+     */
+    public function setModel(Model $model)
+    {
+        $this->model = $model;
+
+        $this->extensions = $this->model->getAllowedExtensions();
+
+        $this->from($this->model->getObjectTypeDirName());
+
+        return $this;
+    }
+
+    /**
+     * Get the model instance being queried.
+     *
+     * @return \October\Rain\Halcyon\Model
+     */
+    public function getModel()
+    {
+        return $this->model;
+    }
+
     /**
      * Get the hydrated models.
      *
@@ -468,16 +479,6 @@ class Builder
         return $models->all();
     }
 
-    /**
-     * Get the model instance being queried.
-     *
-     * @return \October\Rain\Halcyon\Model
-     */
-    public function getModel()
-    {
-        return $this->model;
-    }
-
     //
     // Validation (Hard)
     //
@@ -778,9 +779,8 @@ class Builder
      *
      * @param  string  $method
      * @param  array   $parameters
-     * @return mixed
-     *
      * @throws \BadMethodCallException
+     * @return void
      */
     public function __call($method, $parameters)
     {

programming_language: PHP