Image Gallery – Photo Grid & Video Gallery <= 2.13.3 - Missing Authorization to Authenticated (Author+) Arbitrary Gallery Modification
Description
The Image Gallery – Photo Grid & Video Gallery plugin for WordPress is vulnerable to unauthorized modification of data due to a missing capability check on the `add_images_to_gallery_callback()` function in all versions up to, and including, 2.13.3. This makes it possible for authenticated attackers, with Author-level access and above, to add images to arbitrary Modula galleries owned by other users.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=2.13.3Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2025-14003 (Modula Image Gallery Authorization Bypass) ## 1. Vulnerability Summary The **Modula Image Gallery** plugin (<= 2.13.3) is vulnerable to unauthorized data modification. Specifically, the `add_images_to_gallery_callback()` function, which handles adding i…
Show full research plan
Exploitation Research Plan: CVE-2025-14003 (Modula Image Gallery Authorization Bypass)
1. Vulnerability Summary
The Modula Image Gallery plugin (<= 2.13.3) is vulnerable to unauthorized data modification. Specifically, the add_images_to_gallery_callback() function, which handles adding images to galleries via AJAX, lacks a proper capability check (authorization). While the function is registered for authenticated users, it fails to verify if the requesting user has the authority to modify the specific gallery ID provided in the request. This allows an attacker with Author level permissions to modify galleries belonging to other users (including Administrators).
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - AJAX Action:
modula_add_images_to_gallery(inferred from function name) - HTTP Method:
POST - Parameters:
action:modula_add_images_to_gallerygallery_id: The ID of the target gallery (can be a gallery owned by an Administrator).images: An array or comma-separated list of attachment IDs to add to the gallery.nonce: A security nonce (likelymodula_nonceor similar).
- Required Authentication: Author level or higher (needs
upload_filescapability to have images to add, and access to the Modula admin UI to obtain a nonce).
3. Code Flow
- Entry Point: An authenticated user (Author+) sends a POST request to
admin-ajax.phpwithaction=modula_add_images_to_gallery. - Hook Registration: The plugin registers the action (likely in
includes/class-modula-ajax.phpor similar):add_action( 'wp_ajax_modula_add_images_to_gallery', array( $this, 'add_images_to_gallery_callback' ) ); - Vulnerable Function:
add_images_to_gallery_callback()is invoked. - Nonce Verification: The function likely calls
check_ajax_referer( 'modula-nonce', 'nonce' ). If the user is logged in, they can obtain a valid nonce for this action. - Missing Check: The function proceeds to update the gallery (likely using
update_post_metaor a custom database query) using thegallery_idfrom$_POST['gallery_id']without checking ifcurrent_user_can( 'edit_post', $gallery_id ). - Sink: The images are appended to the gallery's image list in the database.
4. Nonce Acquisition Strategy
The Modula plugin localizes its settings and nonces for the WordPress admin dashboard. Since the attacker must be an Author, they have access to the /wp-admin/ area.
- Identify Enqueueing: The nonce is likely localized in the
modulaormodula-edit-galleryadmin screens. - Creation of Attacker Gallery: To ensure the script is loaded, the Author should create their own "test" gallery or visit the Modula "Galleries" list.
- Extraction:
- Navigate to:
/wp-admin/edit.php?post_type=modula-gallery - Use
browser_evalto extract the nonce:browser_eval("window.modula_vars?.nonce || window.modula_helper_vars?.nonce")(inferred variable names based on common Modula patterns).
- Navigate to:
5. Exploitation Strategy
- Prerequisites:
- Identify a Gallery ID owned by an Administrator (e.g., ID
123). - Identify an Image Attachment ID owned by the Author (e.g., ID
456).
- Identify a Gallery ID owned by an Administrator (e.g., ID
- Step 1: Obtain Nonce: Log in as Author and extract the
modula-noncefrom the admin dashboard. - Step 2: Forge Request: Use
http_requestto send the malicious payload.- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=modula_add_images_to_gallery&gallery_id=123&images[]=456&nonce=[EXTRACTED_NONCE]
- URL:
- Step 3: Verification: Check if Image
456now appears in Gallery123.
6. Test Data Setup
- Admin User: Create an admin user
victim_admin. - Victim Gallery: As
victim_admin, create a Modula gallery named "Private Gallery" (Post IDX). - Author User: Create a user
attacker_authorwith theAuthorrole. - Attacker Image: As
attacker_author, upload an image (Attachment IDY). - Page Creation: Ensure the Modula plugin is active.
7. Expected Results
- The
admin-ajax.phpresponse should return a success status (likely{"success":true}or a HTML snippet of the image). - The gallery metadata for Post ID
Xshould now include Attachment IDYin its image list. - The Author, despite not owning Gallery
X, has successfully modified its content.
8. Verification Steps (Post-Exploit)
- WP-CLI Check:
wp post meta get [GALLERY_ID] [META_KEY]
(Note: Modula usually stores image IDs in a serialized array under a meta key likemodula_imagesormodula_gallery_images.) - Admin UI Check: Log in as Admin and view the "Private Gallery" to see the injected image.
9. Alternative Approaches
- Metadata Overwrite: Check if the endpoint allows sending an empty
imagesarray to potentially clear an Administrator's gallery (Unauthorized Deletion). - Bulk Modification: Test if
gallery_idcan be an array to modify multiple galleries in one request. - Nonce via Modula Shortcode: If the Author cannot access the admin backend (e.g., if restricted by another plugin), check if the nonce is exposed on the frontend via a page containing the
[modula id='...']shortcode.
Summary
The Modula Image Gallery plugin for WordPress is vulnerable to an authorization bypass in its AJAX handler for adding images. Due to a missing permission check on the target gallery ID, authenticated users with Author-level access can modify galleries belonging to other users, including administrators.
Vulnerable Code
// includes/class-modula-ajax.php public function add_images_to_gallery_callback() { check_ajax_referer( 'modula-nonce', 'nonce' ); $gallery_id = isset( $_POST['gallery_id'] ) ? absint( $_POST['gallery_id'] ) : 0; $images = isset( $_POST['images'] ) ? $_POST['images'] : array(); if ( ! $gallery_id || empty( $images ) ) { wp_send_json_error(); } // Vulnerability: No current_user_can('edit_post', $gallery_id) check performed here // Logic to append attachment IDs to the gallery metadata follows $this->append_images( $gallery_id, $images ); wp_send_json_success(); }
Security Fix
@@ -254,6 +254,10 @@ if ( ! $gallery_id || empty( $images ) ) { wp_send_json_error(); } + + if ( ! current_user_can( 'edit_post', $gallery_id ) ) { + wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to edit this gallery.', 'modula-best-grid-gallery' ) ) ); + } $this->append_images( $gallery_id, $images );
Exploit Outline
The exploit targets the 'modula_add_images_to_gallery' AJAX action. An attacker must have at least Author-level permissions to access the WordPress admin dashboard and obtain a valid security nonce (localized as 'modula-nonce'). The methodology involves: 1. Logging into the WordPress dashboard as an Author. 2. Extracting the 'modula-nonce' from the global JavaScript variables localized on any Modula admin page. 3. Identifying the ID of a target gallery (e.g., one owned by an Admin). 4. Sending a POST request to '/wp-admin/admin-ajax.php' with the parameters: 'action=modula_add_images_to_gallery', 'gallery_id=[TARGET_ID]', 'images[]=[ATTACKER_ATTACHMENT_ID]', and the extracted nonce. Because the plugin only verifies the nonce and not the user's permission to edit the specific 'gallery_id', the attachment is successfully added to the target gallery.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.