CVE-2020-28925 (published 2020-12-30T19:15Z)

Bolt before 3.7.2 does not restrict filter options in a Request in the Twig context, and is therefore inconsistent with the "How to Harden Your PHP for Better Security" guidance.

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

Weakness information:
cwe_id: NVD-CWE-noinfo
cwe_name: Insufficient Information
description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/bolt/bolt
commit_details: repo_url: https://github.com/bolt/bolt
author: Xiao Hu Tai
author_date: 2020-10-16 15:10:28+02:00
msg: Restrict `filter` options in `Request` in Twig context
repository: repo_url: https://github.com/bolt/bolt
repo_name: bolt/bolt
description: Bolt is a simple CMS written in PHP. It is based on Silex and Symfony components, uses Twig and either SQLite, MySQL or PostgreSQL.
repo_language: PHP
owner: bolt
file_changes: filename: ArrayAccessSecurityProxy.php
change_type: ModificationType.MODIFY
diff: @@ -72,6 +72,19 @@ class ArrayAccessSecurityProxy implements ArrayAccess, Countable, IteratorAggreg
     {
         $this->sandbox->checkPropertyAllowed($this, $offset);
 
+        if ($offset === 'request') {
+            $request = $this->object[$offset];
+
+            $request->request = new Request\ParameterBag($request->request->all());
+            $request->query = new Request\ParameterBag($request->query->all());
+            $request->attributes = new Request\ParameterBag($request->attributes->all());
+            $request->cookies = new Request\ParameterBag($request->cookies->all());
+            $request->files = new Request\FileBag($request->files->all());
+            $request->server = new Request\ServerBag($request->server->all());
+
+            return $request;
+        }
+
         return $this->object[$offset];
     }
 

programming_language: PHP
filename: FileBag.php
change_type: ModificationType.ADD
diff: @@ -0,0 +1,15 @@
+<?php
+
+namespace Bolt\Twig\Request;
+
+/**
+ * ParameterBag is a container for key/value pairs.
+ * Overridden in order to disable certain filters.
+ *
+ * @author Xiao-Hu Tai <xiao@twokings.nl>
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class FileBag extends \Symfony\Component\HttpFoundation\FileBag implements \IteratorAggregate, \Countable
+{
+    use RestrictedFilterTrait;
+}

programming_language: PHP
filename: ParameterBag.php
change_type: ModificationType.ADD
diff: @@ -0,0 +1,15 @@
+<?php
+
+namespace Bolt\Twig\Request;
+
+/**
+ * ParameterBag is a container for key/value pairs.
+ * Overridden in order to disable certain filters.
+ *
+ * @author Xiao-Hu Tai <xiao@twokings.nl>
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ParameterBag extends \Symfony\Component\HttpFoundation\ParameterBag implements \IteratorAggregate, \Countable
+{
+    use RestrictedFilterTrait;
+}

programming_language: PHP
filename: RestrictedFilterTrait.php
change_type: ModificationType.ADD
diff: @@ -0,0 +1,102 @@
+<?php
+
+namespace Bolt\Twig\Request;
+
+/**
+ * Override filter function in order to restrict certain options in Twig context.
+ * The list of restricted options are taken from "How to Harden Your PHP for
+ * Better Security" [1].
+ *
+ * [1] https://howtogetonline.com/how-to-harden-your-php-for-better-security.php
+ *
+ * @author Xiao-Hu Tai <xiao@twokings.nl>
+ */
+trait RestrictedFilterTrait
+{
+    /** @var array */
+    private $restrictedOptions = [
+        '_getppid',
+        'allow_url_fopen',
+        'allow_url_include',
+        'chgrp',
+        'chmod',
+        'chown',
+        'curl_exec',
+        'curl_multi_exec',
+        'diskfreespace',
+        'dl',
+        'exec',
+        'fpaththru',
+        'getmypid',
+        'getmyuid',
+        'highlight_file',
+        'ignore_user_abord',
+        'ini_set',
+        'lchgrp',
+        'lchown',
+        'leak',
+        'link',
+        'listen',
+        'parse_ini_file',
+        'passthru',
+        'pcntl_exec',
+        'php_uname',
+        'phpinfo',
+        'popen',
+        'posix_ctermid',
+        'posix_getcwd',
+        'posix_getegid',
+        'posix_geteuid',
+        'posix_getgid',
+        'posix_getgrgid',
+        'posix_getgrnam',
+        'posix_getgroups',
+        'posix_getlogin',
+        'posix_getpgid',
+        'posix_getpgrp',
+        'posix_getpid',
+        'posix_getpwnam',
+        'posix_getpwuid',
+        'posix_getrlimit',
+        'posix_getsid',
+        'posix_getuid',
+        'posix_isatty',
+        'posix_kill',
+        'posix_mkfifo',
+        'posix_setegid',
+        'posix_seteuid',
+        'posix_setgid',
+        'posix_setpgid',
+        'posix_setsid',
+        'posix_setuid',
+        'posix_times',
+        'posix_ttyname',
+        'posix_uname',
+        'posix',
+        'proc_close',
+        'proc_get_status',
+        'proc_nice',
+        'proc_open',
+        'proc_terminate',
+        'putenv',
+        'set_time_limit',
+        'shell_exec',
+        'show_source',
+        'source',
+        'system',
+        'tmpfile',
+        'virtual',
+    ];
+
+    /**
+     * {@inheritdoc}
+     */
+    public function filter($key, $default = null, $filter = FILTER_DEFAULT, $options = array(), $deep = false)
+    {
+        if (isset($options['options']) && in_array($options['options'], $this->restrictedOptions)) {
+            unset($options['options']);
+        }
+
+        return parent::filter($key, $default, $filter, $options, $deep);
+    }
+}

programming_language: PHP
filename: ServerBag.php
change_type: ModificationType.ADD
diff: @@ -0,0 +1,15 @@
+<?php
+
+namespace Bolt\Twig\Request;
+
+/**
+ * ParameterBag is a container for key/value pairs.
+ * Overridden in order to disable certain filters.
+ *
+ * @author Xiao-Hu Tai <xiao@twokings.nl>
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ServerBag extends \Symfony\Component\HttpFoundation\ServerBag implements \IteratorAggregate, \Countable
+{
+    use RestrictedFilterTrait;
+}

programming_language: PHP