GHSA-g8x9-7mgh-7cvj: AVideo's GET-Based CSRF in setPermission.json.php Enables Privilege Escalation via Arbitrary Permission Modification
SummaryThe `plugin/Permissions/setPermission.json.php` endpoint accepts GET parameters for a state-changing operation that modifies user group permissions. The endpoint has no CSRF token validation, and the application explicitly sets `session.cookie_samesite=None` on session cookies. This allows an unauthenticated attacker to craft a page with `<img>` tags that, when visited by an admin, silently grant arbitrary permissions to the attacker's user group — escalating the attacker to near-admin access.DetailsThe root cause is a combination of three issues:**1. `$_REQUEST` used instead of `$_POST` (accepts GET parameters):**`plugin/Permissions/setPermission.json.php:14-24`:The only authorization check is `User::isAdmin()` at line 10 — there is no CSRF token validation via `isGlobalTokenValid()`.**2. Session cookies set to `SameSite=None`:**`objects/include_config.php:134-141`:This means the admin's session cookie is sent on cross-origin requests, including those initiated by `<img src="...">` tags on attacker-controlled pages.**3. The codebase's own security model requires CSRF tokens on state-mutating endpoints:**The comment at `include_config.php:137-138` states: *"All state-mutating endpoints that are vulnerable to CSRF must instead enforce a short-lived globalToken (verifyToken)."* Other endpoints like `saveSort.json.php` and `pluginImport.json.php` enforce `isGlobalTokenValid()`, but `setPermission.json.php` does not.**Execution flow:**Attacker hosts a page containing `<img src="https://target/plugin/Permissions/setPermission.json.php?users_groups_id=2&plugins_id=1&type=10&isEnabled=true">`Admin visits the page (e.g., via link in forum, email, or embedded content)Browser issues GET request with the admin's `SameSite=None` session cookie`User::isAdmin()` passes because the request carries the admin's session`Permissions::setPermission()` grants PERMISSION_FULLACCESSVIDEOS (type=10) to user group 2Any user in group 2 (including the attacker) now has full video admin accessThe `users_groups_id` values are small sequential integers (typically 1-3 for default groups) and can be trivially enumerated.PoC**Step 1: Attacker creates a page granting multiple permissions to their user group (ID 2):****Step 2: Attacker sends the link to an admin (social engineering, forum post, etc.)****Step 3: When the admin loads the page, all four `<img>` tags fire simultaneously.**Expected response for each request (visible in browser dev tools):**Step 4: Verify — the attacker (a regular user in group 2) now has full video management, user management, upload, and livestream permissions without being an admin.**Impact**Privilege escalation:** A low-privileged user can gain near-admin permissions (full video access, user management, upload, livestream) by tricking an admin into loading a single page.**No JavaScript required:** The attack uses only `<img>` tags, bypassing Content Security Policy restrictions and working even in contexts where scripts are blocked (email clients, forum BBCode, etc.).**Zero interaction beyond page load:** Unlike POST-based CSRF that requires form submission or JavaScript, this fires automatically when the page renders.**Chaining:** Multiple permissions can be granted simultaneously by embedding multiple `<img>` tags. An attacker can grant their group all available permission types in a single page load.**Blast radius:** All users in the targeted group receive the escalated permissions, not just the attacker.Recommended FixIn `plugin/Permissions/setPermission.json.php`, change `$_REQUEST` to `$_POST` and add CSRF token validation:The AJAX call in `getPermissionsFromPlugin.html.php:84-92` already uses `type: 'post'` but must also send the `globalToken` parameter in its data payload.
CVSS v3.1: 8.1