Grav CMS Multiple RCE Vectors: Unsafe Deserialization & Command Injection
Grav CMS contains five remote code execution vulnerabilities spanning unsafe unserialize() calls without class restrictions and unescaped shell parameters in git operations. This PoC is significant because it demonstrates ecosystem-wide deserialization hygiene gaps and highlights that security controls exist in the same codebase but are inconsistently applied.
CVE References
Affected
Vulnerability Description
Grav CMS contains three critical unsafe deserialization vulnerabilities and one critical command injection vulnerability. The root cause is inconsistent application of security controls: the codebase does implement a Serializable trait with proper class allowlisting, yet multiple components call unserialize() with either no allowed_classes parameter (JobQueue) or with allowed_classes => true (FileCache, Session). The JobQueue vulnerability is particularly direct—the Job class contains a call_user_func_array() gadget chain that accepts attacker-controlled command and args properties. FileCache and Session deserialization can instantiate arbitrary classes if an attacker gains write access to cache or session storage. The git clone command injection affects branch, URL, and path parameters that reach shell execution without escaping.
PoC Significance & Attack Surface
This disclosure is high-fidelity because it identifies three different deserialization patterns in production code, proving the vulnerability class is systematic rather than isolated. The JobQueue gadget is direct and reliable—no complex gadget chain construction needed. FileCache exploitation requires prior write access (lower precondition) but has been chained with other file write primitives in real attacks. The git command injection requires admin panel access or plugin/theme upload control, narrowing the attack surface but not eliminating it for multi-tenant or plugin-ecosystem scenarios. The PoC demonstrates that inconsistent practice—even when correct patterns exist in the same repository—enables exploitation.
Detection Guidance
Log indicators: Monitor for unserialize() calls in error logs or exception traces; search application logs for unusual Job/cache instantiation errors. Source code scanning: SAST rules should flag unserialize($user_input) without allowed_classes parameter set to a restrictive array, or with allowed_classes => true. YARA signature for code audit: unserialize\s*\(\s*[^,]*,\s*\[\s*['"]allowed_classes['"]\s*=>\s*true\s*\] to catch the permissive pattern. Runtime detection: WAF/IDS should flag Base64 sequences in POST parameters to known Grav endpoints (JobQueue serialization typically appears in specific cache/job submission routes). File integrity: Monitor cache and session directory writes for suspicious serialized PHP objects.
Mitigation Steps
Immediate: Upgrade Grav to a patched version released after this advisory. Temporary mitigations: (1) Restrict file write permissions on /cache and /session directories to application user only. (2) Disable git-based plugin/theme installation if not required; restrict to admin-only access with authentication enforcement. (3) Implement strict open_basedir and disable allow_url_fopen/allow_url_include. (4) Apply Web Application Firewall rules to block suspicious serialized payloads. Long-term: Enforce code review standards requiring explicit allowed_classes arrays (not boolean) for all deserialization; migrate to JSON-based serialization where feasible. Apply the existing Serializable trait pattern consistently across the codebase.
Risk Assessment
Likelihood of exploitation is high because: (1) Grav is publicly available open-source with known install paths; (2) deserialization vulnerabilities are a known attack vector for PHP frameworks; (3) FileCache variant is accessible if any file upload primitive exists; (4) the gadget chain is direct and doesn't require complex object graphs. Threat actor interest is moderate-to-high—CMS platforms are high-value targets, and RCE via deserialization is a standard technique in APT playbooks. In-the-wild exploitation likelihood increases if Grav is deployed on shared hosting or in plugin-heavy environments where file write primitives are common.
Sources