FooGallery <= 3.1.11 - Authenticated (Author+) Stored Cross-Site Scripting
Description
The FooGallery plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 3.1.11 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
<=3.1.11Source Code
WordPress.org SVNSince source files were not provided for **CVE-2026-25362**, this plan is based on the vulnerability description, the patch notes for FooGallery 3.1.13, and standard WordPress plugin patterns for gallery management. ## 1. Vulnerability Summary **FooGallery** is a popular gallery management plugin. …
Show full research plan
Since source files were not provided for CVE-2026-25362, this plan is based on the vulnerability description, the patch notes for FooGallery 3.1.13, and standard WordPress plugin patterns for gallery management.
1. Vulnerability Summary
FooGallery is a popular gallery management plugin. In versions <= 3.1.11, the plugin fails to properly sanitize or escape certain gallery settings or metadata fields before storing them in the database and subsequently rendering them. This allows an authenticated user with Author privileges (who can create and edit galleries) to inject malicious JavaScript. When an administrator or any other user views the gallery (either in the admin preview or on the frontend via a shortcode), the script executes in their browser context.
2. Attack Vector Analysis
- Vulnerable Post Type:
foogallery(Custom Post Type). - Vulnerable Endpoint:
wp-admin/post.php. - Vulnerable Parameter: Likely within the
foogallery_settingsarray (stored as post meta) or a custom attribute field. - Authentication Level: Author or higher. Authors have the
edit_postscapability for thefoogallerypost type. - Preconditions: The FooGallery plugin must be active. The attacker needs valid Author credentials.
3. Code Flow (Inferred)
- Entry Point: An Author submits a "Save" or "Publish" request for a gallery at
wp-admin/post.php. - Processing: The plugin catches the
save_post_foogalleryhook or uses a custom AJAX handler to process$_POST['foogallery_settings']. - Sink (Storage): The unsanitized input is stored in the
wp_postmetatable usingupdate_post_meta()under a key likefoogallery_settings. - Source (Output): When a gallery is rendered (frontend or admin), the plugin retrieves these settings.
- Execution: The plugin echoes the setting value directly into the HTML (e.g., as an attribute or within a
<div>) without callingesc_attr()oresc_html().
4. Nonce Acquisition Strategy
Since this exploit involves the standard WordPress Post editor for a Custom Post Type, nonces are required for both the editor page and the save action.
- Login as Author: Use the
browser_logintool. - Navigate to Gallery Creator: Go to
wp-admin/post-new.php?post_type=foogallery. - Extract Nonces:
- Standard WordPress Post Nonce:
browser_eval("document.querySelector('#_wpnonce').value"). - FooGallery Specific Nonce (inferred): Look for a hidden input field related to settings, e.g.,
browser_eval("document.querySelector('#foogallery_settings_nonce')?.value").
- Standard WordPress Post Nonce:
- Extract Post ID: The
post-new.phppage often redirects topost.php?post=ID&action=edit. Extract the ID from the URL.
5. Exploitation Strategy
Step 1: Identify the Vulnerable Field
The agent will first inspect the "Gallery Settings" meta box in the editor to identify potential XSS sinks. Likely candidates in FooGallery:
- Custom CSS Classes
- Gallery Descriptions
- Custom Attributes (if enabled)
Step 2: Prepare the Payload
We will use a standard "break-out" payload to test for attribute-based XSS:" onmouseover="alert(document.domain)" x="
Step 3: Inject via HTTP Request
Using the http_request tool, send a POST request to simulate saving the gallery.
- URL:
https://<target>/wp-admin/post.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body (Example):
action=editpost
&post_ID=<GALLERY_ID>
&_wpnonce=<NONCE>
&post_type=foogallery
&foogallery_settings[custom_class]=" onmouseover="alert(document.domain)" x="
&save=Publish
(Note: Parameter names like foogallery_settings[custom_class] are inferred and will be verified by the agent inspecting the DOM).
Step 4: Trigger Execution
- Create a standard page/post containing the gallery shortcode:
[foogallery id="<GALLERY_ID>"]. - Navigate to that page using
browser_navigate. - Observe if the payload executes (e.g., by checking for the injected attribute in the HTML).
6. Test Data Setup
- User: Create a user with the Author role.
- Gallery Content: Upload at least one image to the Media Library so the gallery has something to render (FooGallery sometimes hides empty galleries).
- Shortcode Page: Create a public page with the FooGallery shortcode for frontend verification.
7. Expected Results
- The POST request to
post.phpshould return a302redirect (indicating a successful save). - When viewing the gallery on the frontend or in the admin preview, the HTML source should contain the unescaped payload:
class="foogallery ... " onmouseover="alert(document.domain)" x="..." - The
onmouseoverevent should trigger the alert.
8. Verification Steps
- Database Check: Use WP-CLI to verify the payload is stored raw:
wp post meta get <GALLERY_ID> foogallery_settings - Frontend Check: Use the
http_requesttool to fetch the page with the shortcode and grep for the payload:grep 'onmouseover="alert'
9. Alternative Approaches
- Template Settings: If
custom_classis sanitized, try fields within specific gallery templates (e.g., "Thumbnail" settings or "Caption" settings). - AJAX Save: If
post.phpis restricted, look for an AJAX action:wp_ajax_foogallery_save_settings. - REST API: Check if FooGallery exposes settings via the
wp/v2/foogalleryREST endpoint, which might lack the same level of sanitization as the admin UI.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.