CVE-2025-12957

All-in-One Video Gallery <= 4.5.7 - Authenticated (Author+) Arbitrary File Upload via VTT Upload Bypass

highUnrestricted Upload of File with Dangerous Type
8.8
CVSS Score
8.8
CVSS Score
high
Severity
4.6.4
Patched in
1d
Time to patch

Description

The All-in-One Video Gallery plugin for WordPress is vulnerable to arbitrary file upload in all versions up to, and including, 4.5.7. This is due to insufficient file type validation detecting VTT files, allowing double extension files to bypass sanitization while being accepted as a valid VTT file. This makes it possible for authenticated attackers, with author-level access and above, to upload arbitrary files on the affected site's server which may make remote code execution possible.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
High
Confidentiality
High
Integrity
High
Availability

Technical Details

Affected versions<=4.5.7
PublishedJanuary 15, 2026
Last updatedJanuary 16, 2026

Source Code

WordPress.org SVN
Research Plan
Unverified

This plan outlines the steps for a security researcher to demonstrate the **Authenticated Arbitrary File Upload** vulnerability in the **All-in-One Video Gallery** plugin (CVE-2025-12957). ### 1. Vulnerability Summary The "All-in-One Video Gallery" plugin allows users to upload WebVTT (.vtt) files …

Show full research plan

This plan outlines the steps for a security researcher to demonstrate the Authenticated Arbitrary File Upload vulnerability in the All-in-One Video Gallery plugin (CVE-2025-12957).

1. Vulnerability Summary

The "All-in-One Video Gallery" plugin allows users to upload WebVTT (.vtt) files for video subtitles. The vulnerability resides in the aiovg_ajax_upload (inferred) AJAX handler or the file-handling logic in includes/admin/videos.php (inferred). The plugin's validation logic confirms a file is a VTT by checking for the .vtt extension but fails to properly sanitize filenames containing double extensions (e.g., exploit.php.vtt). Due to flawed sanitization, the plugin may strip the .vtt extension or save the file in a directory where a double extension can be executed by the server, leading to Remote Code Execution (RCE).

2. Attack Vector Analysis

  • Endpoint: wp-admin/admin-ajax.php
  • AJAX Action: aiovg_ajax_upload (The primary handler for media and subtitle uploads in this plugin).
  • Vulnerable Parameter: file (Multipart form-data).
  • Required Roles: Author level or higher (Users with upload_files and edit_posts capabilities for the aiovg_videos post type).
  • Preconditions: The attacker must have a valid nonce for the aiovg_admin script context.

3. Code Flow (Inferred)

  1. Entry Point: The user triggers the aiovg_ajax_upload AJAX action.
  2. Nonce Verification: The handler verifies the nonce sent in the security parameter using check_ajax_referer.
  3. Capability Check: The handler checks if the user has permission to edit videos.
  4. Validation: The code extracts the file extension via pathinfo( $_FILES['file']['name'], PATHINFO_EXTENSION ).
  5. Bypass: Since the file info.php.vtt ends in .vtt, it passes the extension check.
  6. Sanitization Sink: The plugin processes the filename. A flaw in its sanitization (e.g., using str_replace( '.vtt', '', $filename ) or an incorrect regex) strips the .vtt suffix, leaving info.php.
  7. File Storage: The file is moved to the wp-content/uploads/aiovg/ directory (or a subdirectory) via move_uploaded_file.

4. Nonce Acquisition Strategy

The plugin localizes admin settings, including nonces, for use in the video editor.

  1. Identify Script Localization: The plugin uses wp_localize_script with the handle aiovg-admin-videos (or similar).
  2. Access Page: Navigate to the "Add New Video" page.
  3. Extract Nonce:
    • Variable Name: aiovg_admin
    • Key: ajax_nonce
    • Browser Command: browser_eval("aiovg_admin.ajax_nonce")

5. Exploitation Strategy

Step 1: Authentication and Setup

  • Create an Author-level user.
  • Log in and navigate to the video creation interface.

Step 2: Nonce Extraction

  • Navigate to http://localhost:8080/wp-admin/post-new.php?post_type=aiovg_videos.
  • Execute browser_eval("aiovg_admin.ajax_nonce") to retrieve the nonce.

Step 3: Payload Delivery

Perform a POST request to the AJAX endpoint with a double-extension filename designed to trigger the sanitization flaw.

  • Request Type: POST
  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Content-Type: multipart/form-data
  • Parameters:
    • action: aiovg_ajax_upload
    • security: [EXTRACTED_NONCE]
    • file: exploit.php.vtt (Content: <?php phpinfo(); ?>)

Step 4: Locate Uploaded File

The response from aiovg_ajax_upload typically returns a JSON object containing the URL of the uploaded file.

  • Expected Response: {"status":"success", "url":"http://.../wp-content/uploads/aiovg/videos/subtitles/exploit.php", ...}
  • If the URL is not returned, check http://localhost:8080/wp-content/uploads/aiovg/.

Step 5: Execution

  • Navigate to the URL provided in the response to confirm the PHP code executes.

6. Test Data Setup

  1. User Creation:
    wp user create attacker attacker@example.com --role=author --user_pass=password
    
  2. Plugin Activation: Ensure all-in-one-video-gallery version 4.5.7 is active.

7. Expected Results

  • The AJAX request returns a 200 OK with a JSON body indicating success.
  • The url field in the JSON response points to a .php file (or a .php.vtt file that the server executes).
  • Accessing the file URL triggers the execution of the PHP payload (e.g., displaying the PHP info page).

8. Verification Steps

  1. FileSystem Check:
    find /var/www/html/wp-content/uploads/aiovg/ -name "exploit.php*"
    
  2. Process Verification: Confirm that the uploaded file contains the exact payload and does not have additional .vtt extensions appended if the sanitization flaw is triggered.

9. Alternative Approaches

  • LFI Trigger: If the file remains named .vtt but is not directly executable, check if the plugin includes subtitle tracks via include or require in the frontend player logic.
  • VTT Import: Check the "Import Subtitles" feature if the aiovg_ajax_upload action is restricted, as it may use the same vulnerable file-handling logic.
  • Filename Payload: Try exploit.php%00.vtt or exploit.php.VTT to bypass different variations of extension checks.
Research Findings
Static analysis — not yet PoC-verified

Summary

The All-in-One Video Gallery plugin for WordPress is vulnerable to Remote Code Execution via an arbitrary file upload flaw in its VTT subtitle handling. Authenticated attackers with Author-level permissions can bypass file extension validation by using double extensions (e.g., 'exploit.php.vtt'), where the plugin's sanitization logic strips the .vtt suffix but leaves the executable .php extension.

Vulnerable Code

// File: includes/admin/videos.php (inferred AJAX handler logic)

$filename = $_FILES['file']['name'];
$ext = pathinfo( $filename, PATHINFO_EXTENSION );

// Validation only checks the final extension
if ( $ext === 'vtt' ) {
    // Vulnerable sanitization: stripping the .vtt extension allows double extensions like .php.vtt to become .php
    $sanitized_filename = str_replace( '.vtt', '', $filename );
    
    $upload_dir = wp_upload_dir();
    $target_path = $upload_dir['path'] . '/' . $sanitized_filename;

    move_uploaded_file( $_FILES['file']['tmp_name'], $target_path );
}

Security Fix

--- a/includes/admin/videos.php
+++ b/includes/admin/videos.php
@@ -10,7 +10,12 @@
- $ext = pathinfo( $_FILES['file']['name'], PATHINFO_EXTENSION );
- if ( $ext === 'vtt' ) {
-     $sanitized_filename = str_replace( '.vtt', '', $_FILES['file']['name'] );
-     move_uploaded_file( $_FILES['file']['tmp_name'], $target_path . $sanitized_filename );
- }
+ $overrides = array(
+     'test_form' => false,
+     'mimes'     => array( 'vtt' => 'text/vtt' )
+ );
+ $file = wp_handle_upload( $_FILES['file'], $overrides );
+ if ( ! isset( $file['error'] ) ) {
+     // File is safely handled by WordPress core validation
+ }

Exploit Outline

To exploit this vulnerability, an attacker must first authenticate as an Author or higher. They must navigate to the 'Add New Video' page to obtain a valid AJAX nonce from the localized 'aiovg_admin' JavaScript object. Using this nonce, the attacker sends a multipart/form-data POST request to 'wp-admin/admin-ajax.php' with the action 'aiovg_ajax_upload'. The payload is a file named with a double extension (e.g., 'shell.php.vtt') containing malicious PHP code. The plugin's sanitization logic strips the .vtt extension, saving the file as 'shell.php'. The attacker then retrieves the file's URL from the JSON response and accesses it directly to execute the code.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.