GitHub Advisoryadvisory · Packagist

GHSA-whr7-m3f8-mpm8 Grav Server-side Template Injection (SSTI) via Twig Default Filters

HIGH Published 2023-06-16 Modified 2023-06-16 Official page ↗
Aliases
CVE-2023-34448
Ecosystem
Packagist
Packages
getgrav/grav
Severity
High
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
Weaknesses
CWE-1336, CWE-20
Reviewed
2023-06-16

Affected packages

• Packagist getgrav/grav: < 1.7.42 → fixed in 1.7.42

Description

Hi, actually we have sent the bug report to [email protected] on 27th March 2023 and on 10th April 2023. Grav Server-side Template Injection (SSTI) via Twig Default Filters Summary: | Product | Grav CMS | | ----------------------- | --------------------------------------------- | | Vendor | Grav | | Severity | High - Users with login access to Grav Admin panel and page creation/update permissions are able to obtain remote code/command execution | | Affected Versions | true]), ]; } ... + /** + * @param Environment $env + * @param array $array + * @param callable|string $arrow + * @return array|CallbackFilterIterator + * @throws RuntimeError + */ + function filterFilter(Environment $env, $array, $arrow) + { + if (is_string($arrow) && Utils::isDangerousFunction($arrow)) { + throw new RuntimeError('Twig |filter("' . $arrow . '") is not allowed.'); + } + + return \twig_array_filter($env, $array, $arrow); + } } ~~~ However, looking at the source code of /src/Extension/CoreExtension.php of Twig, alternative default Twig filters could also be used invoke arbitrary functions: ~~~php ... class CoreExtension extends AbstractExtension { ... public function getFilters(): array { return [ ... // array helpers ... new TwigFilter('filter', 'twig_array_filter', ['needs_environment' => true]), // unsafe new TwigFilter('map', 'twig_array_map', ['needs_environment' => true]), // unsafe new TwigFilter('reduce', 'twig_array_reduce', ['needs_environment' => true]), // unsafe ]; } ~~~ The three filter functions above respectively call `array_filter()`, `array_map()` and `array_reduce()`. Since only `filter()` is being overriden by Grav to ensure that the callable passed to `filter()` does not result in the invocation of an unsafe function, the other two functions (i.e. `map()` and `reduce()`) could be used by an authenticated attacker that is able to inject and render malicious templates to gain remote code execution. Exploit Conditions: This vulnerability can be exploited if the attacker has access to: 1. an administrator account, or 2. a non-administrator, user account that are granted the following permissions: • login access to Grav admin panel, and • page creation or update rights Reproduction Steps: 1. Log in to Grav Admin using an administrator account. 2. Navigate to `Accounts > Add`, and ensure that the following permissions are assigned when creating a new low-privileged user: • Login to Admin - Allowed • Page Update - Allowed 2. Log out of Grav Admin, and log back in using the account created in step 2. 3. Navigate to `http:///admin/pages/home`. 4. Click the `Advanced` tab and select the checkbox beside `Twig` to ensure that Twig processing is enabled for the modified webpage. 5. Under the `Content` tab, insert the following payload within the editor: ~~~twig {{ ['id'] | map('system') }} {{ ['id'] | reduce('system') }} ~~~ 4. Click the Preview button. Observe that the output of the `id` shell command is returned in the preview. Suggested Mitigations: Override the built-in Twig `map()` and `reduce()` filter functions in `system/src/Grav/Common/Twig/Extension/GravExtension.php` to validate the argument passed to the filter in `$arrow`. For example: ~~~diff ... class GravExtension extends AbstractExtension implements GlobalsInterface { ... public function getFilters(): array { return [ ... // Security fix new TwigFilter('filter', [$this, 'filterFilter'], ['needs_environment' => true]), + new TwigFilter('map', [$this, 'mapFilter'], ['needs_environment' => true]), + new TwigFilter('reduce', [$this, 'reduceFilter'], ['needs_environment' => true]), ]; } ... + /** + * @param Environment $env + * @param array $array + * @param callable|string $arrow + * @return array|CallbackFilterIterator + * @throws RuntimeError + */ + function mapFilter(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 reduceFilter(Environment $env, $array, $arrow) + { + if (!$arrow instanceof …

Related

Alias · CVE (1)

  • CVE-2023-34448 Grav is a flat-file content management system. vulnerability

Weakness · CWE (2)

  • CWE-1336 Improper Neutralization of Special Elements Used in a Template Engine weakness
  • CWE-20 Improper Input Validation weakness

References