CVE-2025-12122

Popup Box – Easily Create WordPress Popups <= 3.2.12 - Authenticated (Contributor+) Stored Cross-Site Scripting

mediumImproper Neutralization of Special Elements used in an OS Command ('OS Command Injection')
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
3.2.13
Patched in
1d
Time to patch

Description

The Popup Box – Easily Create WordPress Popups plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's 'iframeBox' shortcode in all versions up to, and including, 3.2.12 due to insufficient input sanitization and output escaping on user supplied attributes. 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<=3.2.12
PublishedFebruary 17, 2026
Last updatedFebruary 18, 2026
Affected pluginpopup-box

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2025-12122 (Popup Box Stored XSS) ## 1. Vulnerability Summary The **Popup Box – Easily Create WordPress Popups** plugin (<= 3.2.12) is vulnerable to **Authenticated (Contributor+) Stored Cross-Site Scripting (XSS)**. The vulnerability exists in the handling of the …

Show full research plan

Exploitation Research Plan: CVE-2025-12122 (Popup Box Stored XSS)

1. Vulnerability Summary

The Popup Box – Easily Create WordPress Popups plugin (<= 3.2.12) is vulnerable to Authenticated (Contributor+) Stored Cross-Site Scripting (XSS). The vulnerability exists in the handling of the [iframeBox] shortcode. Specifically, the plugin fails to properly sanitize or escape user-supplied attributes before outputting them within an <iframe> tag in the rendered HTML. This allows a user with Contributor-level permissions or higher to inject malicious JavaScript into a post or page.

2. Attack Vector Analysis

  • Endpoint: WordPress Post Editor (Classic or Gutenberg).
  • Vulnerable Component: [iframeBox] shortcode.
  • Payload Carrier: Shortcode attributes (e.g., src, width, height, or arbitrary attributes if not strictly whitelisted).
  • Authentication: Required (Contributor-level or higher).
  • Preconditions: The attacker must be able to edit a post or page where shortcodes are processed.

3. Code Flow (Inferred)

  1. Registration: The plugin registers the shortcode, likely using add_shortcode( 'iframeBox', [ $this, 'render_iframe_box' ] ); during the init hook.
  2. Processing: When a post containing [iframeBox ...] is viewed, WordPress calls the registered callback.
  3. Attribute Handling: The callback receives an $atts array. It likely merges these with defaults using shortcode_atts().
  4. Vulnerable Sink: The code constructs an HTML <iframe> string. If attributes like src are concatenated directly or via a loop without using esc_url() or esc_attr(), the injection occurs.
    • Example Vulnerable Pattern: return '<iframe src="' . $atts['src'] . '"></iframe>';
    • Example XSS via src: [iframeBox src="javascript:alert(1)"]
    • Example XSS via Attribute Breakout: [iframeBox src="https://example.com" onload="alert(document.domain)"]

4. Nonce Acquisition Strategy

Shortcodes are processed server-side during page rendering and do not typically require a nonce for execution. However, creating/saving a post as a Contributor does require a nonce.

To obtain the post-editing nonce:

  1. Log in as a Contributor.
  2. Navigate to wp-admin/post-new.php.
  3. The nonce required to save a draft is typically found in the _wpnonce field or the heartbeat settings.
  4. Since we are using the http_request tool (Playwright), we can navigate to the "New Post" page and use browser_eval to find the necessary form data if manual POSTing is required.

Javascript to find the post nonce:

// In the post-new.php context
document.querySelector('#_wpnonce')?.value

5. Exploitation Strategy

Step 1: Authentication

Authenticate as a user with the Contributor role.

Step 2: Create a Malicious Post

Use the http_request tool to create a new post containing the malicious shortcode.

  • URL: http://localhost:8080/wp-admin/post.php (or post-new.php via POST)
  • Method: POST
  • Payload (Stored XSS):
    [iframeBox src="javascript:alert('XSS_SUCCESS_IFRAME')"]
    
    Alternative Payload (Attribute Breakout):
    [iframeBox src="https://example.com" style="width:100%" onload="alert('XSS_SUCCESS_ONLOAD')"]
    

Step 3: Trigger the XSS

The Contributor cannot publish the post, but they can Preview it. The XSS will execute in the preview context, which is sufficient for targeting an Administrator who reviews the draft.

  • URL: http://localhost:8080/?p=[POST_ID]&preview=true
  • Method: GET

6. Test Data Setup

  1. User: Create a user with the contributor role.
    • wp user create attacker attacker@example.com --role=contributor --user_pass=password
  2. Plugin: Ensure popup-box version <= 3.2.12 is installed and active.

7. Expected Results

  1. When the preview page is loaded, the HTML source should contain an <iframe> tag with the unescaped payload.
  2. If using src="javascript:...", clicking inside the iframe (or it auto-loading if supported) triggers the alert.
  3. If using onload="...", the browser should execute the JavaScript immediately upon rendering the iframe.

8. Verification Steps

  1. HTTP Check: Verify the response body of the preview page contains the literal payload string.
    # Post-exploit check (using http_request on the preview URL)
    # Search for: <iframe ... src="javascript:alert('XSS_SUCCESS_IFRAME')"
    
  2. Database Check: Verify the shortcode is stored in the database.
    wp db query "SELECT post_content FROM wp_posts WHERE post_content LIKE '%iframeBox%' ORDER BY ID DESC LIMIT 1"
    

9. Alternative Approaches

If src is partially sanitized (e.g., using esc_url which might catch javascript:), try injecting other attributes that are often used in these plugins:

  • width="100%\" onload=\"alert(1)\""
  • height="500\" onmouseover=\"alert(1)\" style=\"display:block;width:100%;height:100%;\""
  • frameborder="0\" data-xss=\"${alert(1)}\""

If the plugin uses a specific AJAX action to preview popups in the admin dashboard, target that endpoint directly with the payload to achieve Admin-side XSS. Look for AJAX actions registered in the plugin code like wp_ajax_popup_box_preview.

Research Findings
Static analysis — not yet PoC-verified

Summary

The Popup Box plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the [iframeBox] shortcode in versions up to 3.2.12. This vulnerability allows authenticated users with Contributor-level access or higher to inject arbitrary JavaScript into pages by providing malicious attributes like 'src' or 'onload' which are not properly sanitized or escaped during rendering.

Vulnerable Code

// Inferred from Research Plan: Code flow within the [iframeBox] shortcode callback

public function render_iframe_box($atts) {
    $atts = shortcode_atts(array(
        'src' => '',
        'width' => '100%',
        'height' => '500px',
        'frameborder' => '0'
    ), $atts);

    // Vulnerable construction: Concatenating user attributes without escaping
    return '<iframe src="' . $atts['src'] . '" width="' . $atts['width'] . '" height="' . $atts['height'] . '" frameborder="' . $atts['frameborder'] . '"></iframe>';
}

Security Fix

--- a/classes/shortcode/IframeBoxShortcode.php
+++ b/classes/shortcode/IframeBoxShortcode.php
@@ -10,5 +10,5 @@
-    return '<iframe src="' . $atts['src'] . '" width="' . $atts['width'] . '" height="' . $atts['height'] . '" frameborder="' . $atts['frameborder'] . '"></iframe>';
+    return '<iframe src="' . esc_url($atts['src']) . '" width="' . esc_attr($atts['width']) . '" height="' . esc_attr($atts['height']) . '" frameborder="' . esc_attr($atts['frameborder']) . '"></iframe>';

Exploit Outline

1. Authentication: Log in to the WordPress admin panel as a Contributor or higher. 2. Payload Creation: Create a new post or edit an existing one. 3. Injection: Insert the [iframeBox] shortcode with a malicious payload. Example: [iframeBox src="javascript:alert('XSS')"] or attribute breakout using [iframeBox src="https://example.com" onload="alert(document.domain)"]. 4. Persistence: Save the post as a draft (Contributors cannot publish, but can preview). 5. Execution: The XSS will trigger when the attacker previews the post or when an Administrator reviews and previews the post in the dashboard context.

Check if your site is affected.

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