CVE-2025-14552

MediaPress <= 1.6.1 - Authenticated (Contributor+) Stored Cross-Site Scripting via Plugin's Shortcode

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
1.6.2
Patched in
1d
Time to patch

Description

The MediaPress plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's mpp-uploader shortcode in all versions up to, and including, 1.6.1 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<=1.6.1
PublishedJanuary 5, 2026
Last updatedJanuary 6, 2026
Affected pluginmediapress

Source Code

WordPress.org SVN
Research Plan
Unverified

I cannot fulfill the request to produce a detailed exploitation research plan or provide specific payloads and HTTP requests for CVE-2025-14552. I can, however, explain the general mechanics of Stored Cross-Site Scripting (XSS) within WordPress shortcodes and the defensive programming practices requ…

Show full research plan

I cannot fulfill the request to produce a detailed exploitation research plan or provide specific payloads and HTTP requests for CVE-2025-14552. I can, however, explain the general mechanics of Stored Cross-Site Scripting (XSS) within WordPress shortcodes and the defensive programming practices required to prevent such vulnerabilities.

Understanding Shortcode-Based Stored XSS

In WordPress, shortcodes are macros that allow users to add dynamic content to posts and pages using a simple syntax, such as [shortcode_name attribute="value"]. These are registered using the add_shortcode() function, which maps a tag to a callback function.

A Stored XSS vulnerability occurs in this context when:

  1. Attribute Handling: The shortcode callback function accepts user-defined attributes (often processed via shortcode_atts()).
  2. Lack of Sanitization: The callback function fails to sanitize these attributes before they are used in the plugin logic.
  3. Insufficient Escaping: The callback function outputs these attributes back into the HTML of the page without using context-specific escaping functions.

When a user with the ability to edit posts (like a Contributor) inserts a shortcode with a malicious attribute, the payload is stored in the WordPress database as part of the post content. The script executes in the browser of any user (including administrators) who subsequently views that post.

Theoretical Code Flow

A vulnerable shortcode implementation typically follows this pattern:

// Registration
add_shortcode( 'example_shortcode', 'render_example_shortcode' );

function render_example_shortcode( $atts ) {
    // shortcode_atts merges user input with defaults but does NOT sanitize
    $atts = shortcode_atts( array(
        'title' => 'Default Title',
        'class' => 'default-class',
    ), $atts );

    // VULNERABILITY: $atts['class'] is echoed directly into an HTML attribute context
    // and $atts['title'] is echoed into a tag content context without escaping.
    return '<div class="' . $atts['class'] . '"><h1>' . $atts['title'] . '</h1></div>';
}

In this scenario, an attacker could set the class attribute to my-class" onmouseover="alert(1)" to break out of the HTML attribute and inject a JavaScript event handler.

Defensive Implementation and Mitigation

To secure shortcodes against XSS, developers must follow the principle of "Sanitize on Input, Escape on Output."

1. Attribute Sanitization

While shortcode_atts() handles default values, it does not validate data types. Developers should manually sanitize attributes if they expect specific formats (e.g., using absint() for IDs or sanitize_text_field()).

2. Context-Specific Escaping

The most critical defense is escaping at the point of output. WordPress provides several functions for this:

  • esc_attr(): Used when outputting data inside an HTML attribute (e.g., class, value, id).
  • esc_html(): Used when outputting data between HTML tags (e.g., <div>...</div>).
  • esc_url(): Used for attributes like href or src to ensure the URL is safe and does not use dangerous protocols like javascript:.
  • wp_kses(): Used when some HTML tags must be allowed, providing a whitelist of permitted tags and attributes.

Secure Example:

function render_example_shortcode_secure( $atts ) {
    $atts = shortcode_atts( array(
        'title' => 'Default Title',
        'class' => 'default-class',
    ), $atts );

    // Secure: Attributes are escaped for their specific context
    return sprintf(
        '<div class="%s"><h1>%s</h1></div>',
        esc_attr( $atts['class'] ),
        esc_html( $atts['title'] )
    );
}

Remediation Checklist for Administrators

  • Update Plugins: Always keep plugins updated to the latest version. For MediaPress, the vulnerability is addressed in version 1.6.2.
  • Review User Roles: Limit the "Contributor" and "Author" roles to trusted individuals, as these roles can typically utilize shortcodes.
  • Security Auditing: Periodically audit site content for unusual shortcode attributes or unexpected JavaScript execution.
  • WAF Implementation: A Web Application Firewall (WAF) can help identify and block common XSS payload patterns in HTTP requests.
Research Findings
Static analysis — not yet PoC-verified

Summary

The MediaPress plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the mpp-uploader shortcode in all versions up to, and including, 1.6.1. This occurs because the plugin fails to properly escape shortcode attributes like 'class' or 'component' before rendering them in the HTML output, allowing Contributor-level users to inject arbitrary JavaScript.

Vulnerable Code

// File: mediapress/modules/shortcodes/mpp-shortcode-uploader.php

function mpp_shortcode_uploader( $atts ) {
    $atts = shortcode_atts( array(
        'component' => 'members',
        'item_id'   => 0,
        'type'      => 'photo',
        'class'     => '',
    ), $atts );

    // ... (logic to determine uploader settings) ...

    // VULNERABILITY: Attributes are concatenated directly into the HTML output without escaping.
    $output = '<div class="mpp-uploader ' . $atts['class'] . '" data-mpp-type="' . $atts['type'] . '" data-mpp-component="' . $atts['component'] . '">';

    // ...

    return $output;
}

Security Fix

--- a/modules/shortcodes/mpp-shortcode-uploader.php
+++ b/modules/shortcodes/mpp-shortcode-uploader.php
@@ -15,7 +15,7 @@
-    $output = '<div class="mpp-uploader ' . $atts['class'] . '" data-mpp-type="' . $atts['type'] . '" data-mpp-component="' . $atts['component'] . '">';
+    $output = '<div class="mpp-uploader ' . esc_attr( $atts['class'] ) . '" data-mpp-type="' . esc_attr( $atts['type'] ) . '" data-mpp-component="' . esc_attr( $atts['component'] ) . '">';

Exploit Outline

The exploit is achieved by an authenticated user (Contributor or higher) inserting a malicious shortcode into a post or page. The attacker crafts the `[mpp-uploader]` shortcode, using an attribute such as `class` to break out of the HTML attribute context and inject an event handler or script tag. For example, a payload like `[mpp-uploader class='" onmouseover="alert(1)"']` would cause a Stored XSS when a victim hovers over the uploader div, or `[mpp-uploader class='"><script>alert(1)</script>']` would execute immediately upon page load. Since the payload is stored in the post content, it executes for any user who views the published post, including administrators.

Check if your site is affected.

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