From 244758d4383034fe4cd292d41e477177870b65ec Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Wed, 14 Jun 2023 11:08:17 -0600 Subject: [PATCH] also handle SSTI in reduce twig filter + function --- CHANGELOG.md | 3 +- .../Common/Twig/Extension/GravExtension.php | 32 ++++++++++++++++--- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3c593404..cef87dd84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,11 @@ 1. [](#new) * Added a new `system.languages.debug` option that adds a `` 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 diff --git a/system/src/Grav/Common/Twig/Extension/GravExtension.php b/system/src/Grav/Common/Twig/Extension/GravExtension.php index daddc9106..2ef5364a3 100644 --- a/system/src/Grav/Common/Twig/Extension/GravExtension.php +++ b/system/src/Grav/Common/Twig/Extension/GravExtension.php @@ -171,9 +171,10 @@ class GravExtension extends AbstractExtension implements GlobalsInterface 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 @@ class GravExtension extends AbstractExtension implements GlobalsInterface 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 @@ class GravExtension extends AbstractExtension implements GlobalsInterface * @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,7 +1728,7 @@ class GravExtension extends AbstractExtension implements GlobalsInterface * @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.'); @@ -1730,4 +1736,20 @@ class GravExtension extends AbstractExtension implements GlobalsInterface 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); + } }