GitHub Advisoryadvisory · Packagist
GHSA-whr7-m3f8-mpm8 Grav Server-side Template Injection (SSTI) via Twig Default Filters
HIGH
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
References
- https://github.com/getgrav/grav/security/advisories/GHSA-whr7-m3f8-mpm8 web
- https://nvd.nist.gov/vuln/detail/CVE-2023-34448 advisory
- https://github.com/getgrav/grav/commit/244758d4383034fe4cd292d41e477177870b65ec web
- https://github.com/getgrav/grav/commit/71bbed12f950de8335006d7f91112263d8504f1b web
- https://github.com/getgrav/grav/commit/8c2c1cb72611a399f13423fc6d0e1d998c03e5c8 web
- https://github.com/getgrav/grav/commit/9d01140a63c77075ef09b26ef57cf186138151a5 web
- https://github.com/getgrav/grav package
- https://github.com/twigphp/Twig/blob/v1.44.7/src/Environment.php#L148 web
- https://huntr.dev/bounties/3ef640e6-9e25-4ecb-8ec1-64311d63fe66 web
- https://www.github.com/getgrav/grav/commit/9d6a2dba09fd4e56f5cdfb9a399caea355bfeb83 web