CVE-2025-14003

Image Gallery – Photo Grid & Video Gallery <= 2.13.3 - Missing Authorization to Authenticated (Author+) Arbitrary Gallery Modification

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
2.13.4
Patched in
1d
Time to patch

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:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
None
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=2.13.3
PublishedDecember 15, 2025
Last updatedDecember 15, 2025

Source Code

WordPress.org SVN
Research Plan
Unverified

# 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_gallery
    • gallery_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 (likely modula_nonce or similar).
  • Required Authentication: Author level or higher (needs upload_files capability to have images to add, and access to the Modula admin UI to obtain a nonce).

3. Code Flow

  1. Entry Point: An authenticated user (Author+) sends a POST request to admin-ajax.php with action=modula_add_images_to_gallery.
  2. Hook Registration: The plugin registers the action (likely in includes/class-modula-ajax.php or similar):
    add_action( 'wp_ajax_modula_add_images_to_gallery', array( $this, 'add_images_to_gallery_callback' ) );
  3. Vulnerable Function: add_images_to_gallery_callback() is invoked.
  4. 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.
  5. Missing Check: The function proceeds to update the gallery (likely using update_post_meta or a custom database query) using the gallery_id from $_POST['gallery_id'] without checking if current_user_can( 'edit_post', $gallery_id ).
  6. 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.

  1. Identify Enqueueing: The nonce is likely localized in the modula or modula-edit-gallery admin screens.
  2. Creation of Attacker Gallery: To ensure the script is loaded, the Author should create their own "test" gallery or visit the Modula "Galleries" list.
  3. Extraction:
    • Navigate to: /wp-admin/edit.php?post_type=modula-gallery
    • Use browser_eval to extract the nonce:
      browser_eval("window.modula_vars?.nonce || window.modula_helper_vars?.nonce") (inferred variable names based on common Modula patterns).

5. Exploitation Strategy

  1. 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).
  2. Step 1: Obtain Nonce: Log in as Author and extract the modula-nonce from the admin dashboard.
  3. Step 2: Forge Request: Use http_request to 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]
  4. Step 3: Verification: Check if Image 456 now appears in Gallery 123.

6. Test Data Setup

  1. Admin User: Create an admin user victim_admin.
  2. Victim Gallery: As victim_admin, create a Modula gallery named "Private Gallery" (Post ID X).
  3. Author User: Create a user attacker_author with the Author role.
  4. Attacker Image: As attacker_author, upload an image (Attachment ID Y).
  5. Page Creation: Ensure the Modula plugin is active.

7. Expected Results

  • The admin-ajax.php response should return a success status (likely {"success":true} or a HTML snippet of the image).
  • The gallery metadata for Post ID X should now include Attachment ID Y in its image list.
  • The Author, despite not owning Gallery X, has successfully modified its content.

8. Verification Steps (Post-Exploit)

  1. 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 like modula_images or modula_gallery_images.)
  2. 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 images array to potentially clear an Administrator's gallery (Unauthorized Deletion).
  • Bulk Modification: Test if gallery_id can 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.
Research Findings
Static analysis — not yet PoC-verified

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

--- a/includes/class-modula-ajax.php
+++ b/includes/class-modula-ajax.php
@@ -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.