VYPR
High severityNVD Advisory· Published Jun 14, 2023· Updated Dec 18, 2024

Grav vulnerable to Server-side Template Injection (SSTI) via Denylist Bypass

CVE-2023-34253

Description

Grav is a flat-file content management system. Prior to version 1.7.42, the denylist introduced in commit 9d6a2d to prevent dangerous functions from being executed via injection of malicious templates was insufficient and could be easily subverted in multiple ways -- (1) using unsafe functions that are not banned, (2) using capitalised callable names, and (3) using fully-qualified names for referencing callables. Consequently, a low privileged attacker with login access to Grav Admin panel and page creation/update permissions is able to inject malicious templates to obtain remote code execution. A patch in version 1.7.42 improves the denylist.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
getgrav/gravPackagist
< 1.7.421.7.42

Affected products

1

Patches

4
244758d43830

also handle SSTI in reduce twig filter + function

https://github.com/getgrav/gravAndy MillerJun 14, 2023via ghsa
2 files changed · +29 6
  • CHANGELOG.md+2 1 modified
    @@ -4,10 +4,11 @@
     1. [](#new)
        * Added a new `system.languages.debug` option that adds a `<span class="translate-debug"></span>` around strings translated with `|t`. This can be styled by the theme as needed.
     1. [](#improved)
    -   * More robust SSTI handling in `|filter` and `|map`
    +   * More robust SSTI handling in `filter`, `map`, and `reduce` Twig filters and functions
        * Various SSTI improvements `Utils::isDangerousFunction()`
     1. [](#bugfix)
        * Fixed Twig `|map()` allowing code execution
    +   * Fixed Twig `|reduce()` allowing code execution
     
     # v1.7.41.2
     ## 06/01/2023
    
  • system/src/Grav/Common/Twig/Extension/GravExtension.php+27 5 modified
    @@ -171,9 +171,10 @@ public function getFilters(): array
                 new TwigFilter('count', 'count'),
                 new TwigFilter('array_diff', 'array_diff'),
     
    -            // Security fix
    -            new TwigFilter('filter', [$this, 'filterFilter'], ['needs_environment' => true]),
    -            new TwigFilter('map', [$this, 'mapFilter'], ['needs_environment' => true]),
    +            // Security fixes
    +            new TwigFilter('filter', [$this, 'filterFunc'], ['needs_environment' => true]),
    +            new TwigFilter('map', [$this, 'mapFunc'], ['needs_environment' => true]),
    +            new TwigFilter('reduce', [$this, 'reduceFunc'], ['needs_environment' => true]),
             ];
         }
     
    @@ -250,6 +251,11 @@ public function getFunctions(): array
                 new TwigFunction('count', 'count'),
                 new TwigFunction('array_diff', 'array_diff'),
                 new TwigFunction('parse_url', 'parse_url'),
    +
    +            // Security fixes
    +            new TwigFunction('filter', [$this, 'filterFunc'], ['needs_environment' => true]),
    +            new TwigFunction('map', [$this, 'mapFunc'], ['needs_environment' => true]),
    +            new TwigFunction('reduce', [$this, 'reduceFunc'], ['needs_environment' => true]),
             ];
         }
     
    @@ -1706,7 +1712,7 @@ public function ofTypeFunc($var, $typeTest = null, $className = null)
          * @return array|CallbackFilterIterator
          * @throws RuntimeError
          */
    -    function filterFilter(Environment $env, $array, $arrow)
    +    function filterFunc(Environment $env, $array, $arrow)
         {
             if (!$arrow instanceof \Closure && !is_string($arrow) || Utils::isDangerousFunction($arrow)) {
                 throw new RuntimeError('Twig |filter("' . $arrow . '") is not allowed.');
    @@ -1722,12 +1728,28 @@ function filterFilter(Environment $env, $array, $arrow)
          * @return array|CallbackFilterIterator
          * @throws RuntimeError
          */
    -    function mapFilter(Environment $env, $array, $arrow)
    +    function mapFunc(Environment $env, $array, $arrow)
         {
             if (!$arrow instanceof \Closure && !is_string($arrow) || Utils::isDangerousFunction($arrow)) {
                 throw new RuntimeError('Twig |map("' . $arrow . '") is not allowed.');
             }
     
             return twig_array_map($env, $array, $arrow);
         }
    +
    +    /**
    +     * @param Environment $env
    +     * @param array $array
    +     * @param callable|string $arrow
    +     * @return array|CallbackFilterIterator
    +     * @throws RuntimeError
    +     */
    +    function reduceFunc(Environment $env, $array, $arrow)
    +    {
    +        if (!$arrow instanceof \Closure && !is_string($arrow) || Utils::isDangerousFunction($arrow)) {
    +            throw new RuntimeError('Twig |reduce("' . $arrow . '") is not allowed.');
    +        }
    +
    +        return twig_array_map($env, $array, $arrow);
    +    }
     }
    
71bbed12f950

more SSTI fixes in Utils::isDangerousFunction()

https://github.com/getgrav/gravAndy MillerJun 13, 2023via ghsa
2 files changed · +18 1
  • CHANGELOG.md+1 0 modified
    @@ -5,6 +5,7 @@
        * Added a new `system.languages.debug` option that adds a `<span class="translate-debug"></span>` around strings translated with `|t`. This can be styled by the theme as needed.
     1. [](#improved)
        * More robust SSTI handling in `|filter` and `|map`
    +   * Various SSTI improvements `Utils::isDangerousFunction()`
     1. [](#bugfix)
        * Fixed Twig `|map()` allowing code execution
     
    
  • system/src/Grav/Common/Utils.php+17 1 modified
    @@ -1950,7 +1950,7 @@ public static function getSupportPageTypes(array $defaults = null)
         }
     
         /**
    -     * @param string|array $name
    +     * @param string|array|Closure $name
          * @return bool
          */
         public static function isDangerousFunction($name): bool
    @@ -2048,8 +2048,24 @@ public static function isDangerousFunction($name): bool
                 'posix_setpgid',
                 'posix_setsid',
                 'posix_setuid',
    +            'unserialize',
    +            'ini_alter',
    +            'simplexml_load_file',
    +            'simplexml_load_string',
    +            'forward_static_call',
    +            'forward_static_call_array',
             ];
     
    +        $name = strtolower($name);
    +
    +        if ($name instanceof \Closure) {
    +            return false;
    +        }
    +
    +        if (strpos($name, "\\") !== false) {
    +            return false;
    +        }
    +
             if (is_array($name) || strpos($name, ":") !== false) {
                 return false;
             }
    
8c2c1cb72611

better SSTI in |map and |filter

https://github.com/getgrav/gravAndy MillerJun 13, 2023via ghsa
3 files changed · +11 5
  • CHANGELOG.md+3 1 modified
    @@ -3,8 +3,10 @@
     
     1. [](#new)
        * Added a new `system.languages.debug` option that adds a `<span class="translate-debug"></span>` around strings translated with `|t`. This can be styled by the theme as needed.
    +1. [](#improved)
    +   * More robust SSTI handling in `|filter` and `|map`
     1. [](#bugfix)
    -   * * Fixed Twig `|map()` allowing code execution
    +   * Fixed Twig `|map()` allowing code execution
     
     # v1.7.41.2
     ## 06/01/2023
    
  • system/src/Grav/Common/Twig/Extension/GravExtension.php+2 2 modified
    @@ -1708,7 +1708,7 @@ public function ofTypeFunc($var, $typeTest = null, $className = null)
          */
         function filterFilter(Environment $env, $array, $arrow)
         {
    -        if (is_string($arrow) && Utils::isDangerousFunction($arrow)) {
    +        if (!$arrow instanceof \Closure && !is_string($arrow) || Utils::isDangerousFunction($arrow)) {
                 throw new RuntimeError('Twig |filter("' . $arrow . '") is not allowed.');
             }
     
    @@ -1724,7 +1724,7 @@ function filterFilter(Environment $env, $array, $arrow)
          */
         function mapFilter(Environment $env, $array, $arrow)
         {
    -        if (is_string($arrow) && Utils::isDangerousFunction($arrow)) {
    +        if (!$arrow instanceof \Closure && !is_string($arrow) || Utils::isDangerousFunction($arrow)) {
                 throw new RuntimeError('Twig |map("' . $arrow . '") is not allowed.');
             }
     
    
  • system/src/Grav/Common/Utils.php+6 2 modified
    @@ -1950,10 +1950,10 @@ public static function getSupportPageTypes(array $defaults = null)
         }
     
         /**
    -     * @param string $name
    +     * @param string|array $name
          * @return bool
          */
    -    public static function isDangerousFunction(string $name): bool
    +    public static function isDangerousFunction($name): bool
         {
             static $commandExecutionFunctions = [
                 'exec',
    @@ -2050,6 +2050,10 @@ public static function isDangerousFunction(string $name): bool
                 'posix_setuid',
             ];
     
    +        if (is_array($name) || strpos($name, ":") !== false) {
    +            return false;
    +        }
    +
             if (in_array($name, $commandExecutionFunctions)) {
                 return true;
             }
    
9d01140a63c7

Fix for dangerous tags in |map filter

https://github.com/getgrav/gravAndy MillerJun 13, 2023via ghsa
2 files changed · +19 0
  • CHANGELOG.md+2 0 modified
    @@ -3,6 +3,8 @@
     
     1. [](#new)
        * Added a new `system.languages.debug` option that adds a `<span class="translate-debug"></span>` around strings translated with `|t`. This can be styled by the theme as needed.
    +1. [](#bugfix)
    +   * * Fixed Twig `|map()` allowing code execution
     
     # v1.7.41.2
     ## 06/01/2023
    
  • system/src/Grav/Common/Twig/Extension/GravExtension.php+17 0 modified
    @@ -173,6 +173,7 @@ public function getFilters(): array
     
                 // Security fix
                 new TwigFilter('filter', [$this, 'filterFilter'], ['needs_environment' => true]),
    +            new TwigFilter('map', [$this, 'mapFilter'], ['needs_environment' => true]),
             ];
         }
     
    @@ -1713,4 +1714,20 @@ function filterFilter(Environment $env, $array, $arrow)
     
             return twig_array_filter($env, $array, $arrow);
         }
    +
    +    /**
    +     * @param Environment $env
    +     * @param array $array
    +     * @param callable|string $arrow
    +     * @return array|CallbackFilterIterator
    +     * @throws RuntimeError
    +     */
    +    function mapFilter(Environment $env, $array, $arrow)
    +    {
    +        if (is_string($arrow) && Utils::isDangerousFunction($arrow)) {
    +            throw new RuntimeError('Twig |map("' . $arrow . '") is not allowed.');
    +        }
    +
    +        return twig_array_map($env, $array, $arrow);
    +    }
     }
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

11

News mentions

0

No linked articles in our index yet.