CVE-2026-2383

Simple Download Monitor <= 4.0.5 - Authenticated (Contributor+) Stored Cross-Site Scripting via Custom Field

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

Description

The Simple Download Monitor plugin for WordPress is vulnerable to Stored Cross-Site Scripting via custom field in all versions up to, and including, 4.0.5 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<=4.0.5
PublishedFebruary 26, 2026
Last updatedFebruary 27, 2026

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-2383 ## 1. Vulnerability Summary The **Simple Download Monitor** plugin for WordPress (versions <= 4.0.5) contains a stored Cross-Site Scripting (XSS) vulnerability. The flaw exists because the plugin fails to adequately sanitize and escape custom field data a…

Show full research plan

Exploitation Research Plan: CVE-2026-2383

1. Vulnerability Summary

The Simple Download Monitor plugin for WordPress (versions <= 4.0.5) contains a stored Cross-Site Scripting (XSS) vulnerability. The flaw exists because the plugin fails to adequately sanitize and escape custom field data associated with "Download" items (Custom Post Type: sdm_downloads). Specifically, when a user with Contributor-level permissions or higher creates or edits a download, they can inject arbitrary JavaScript into a custom field. This script is then executed in the context of any user (including administrators) who views the download page or a page containing the download's shortcode.

2. Attack Vector Analysis

  • Endpoint: wp-admin/post.php (Standard WordPress post saving) or via the plugin's meta box update logic.
  • Vulnerable Hook: save_post_sdm_downloads (inferred) which triggers the saving of metadata.
  • HTTP Parameter: Likely sdm_item_description or a specific metadata field such as sdm_other_details or a dedicated custom field parameter (e.g., sdm_custom_field_name).
  • Required Authentication: Authenticated user with Contributor role or higher. Contributors can create and edit their own sdm_downloads posts.
  • Preconditions: The plugin must be active, and the attacker must have credentials for a Contributor-level account.

3. Code Flow

  1. Input: A Contributor submits a form to save or update an sdm_downloads post.
  2. Processing: The plugin catches the save action, likely in includes/admin-side/sdm-admin-individual-item-meta-boxes.php within a function named similarly to sdm_save_download_meta_data.
  3. Persistence: The code calls update_post_meta( $post_id, 'some_meta_key', $_POST['vulnerable_parameter'] ). In version 4.0.5, this input is not passed through sanitize_text_field or wp_kses.
  4. Retrieval: When a user visits the download page, the plugin retrieves the value using get_post_meta( $post_id, 'some_meta_key', true ).
  5. Sink: The value is output directly in the template (likely in includes/sdm-download-shortcodes.php or sdm-post-type-content-handler.php) using echo $meta_value; without calling esc_html, esc_attr, or wp_kses.

4. Nonce Acquisition Strategy

The vulnerability involves saving a standard WordPress Custom Post Type. WordPress handles CSRF protection for post saves using the _wpnonce field on the post.php page.

Strategy:

  1. Create Contributor: Use WP-CLI to create a contributor user.
  2. Log In: Navigate to wp-login.php and authenticate.
  3. Navigate to Create: Navigate to wp-admin/post-new.php?post_type=sdm_downloads.
  4. Extract Nonce: Use browser_eval to extract the _wpnonce from the form.
    • browser_eval("document.querySelector('#_wpnonce').value")
  5. Extract Post ID: Extract the post_ID (if auto-drafted) or use the one provided in the form.

5. Exploitation Strategy

We will use the Contributor account to inject a payload into the "Other Details" or "Description" field of a Download item.

Step-by-Step Plan:

  1. Setup Account: Create a contributor user attacker.
  2. Initial Navigation: Log in as attacker and go to the "Add New Download" page.
  3. Identify Field: Search the page source for metadata fields. Based on plugin research, the vulnerable field is likely sdm_item_description (if it uses a textarea without KSES) or a custom field like sdm_external_thumbnail_url if used in an src attribute.
    • Note: If the vulnerability is "via Custom Field," look for a field labeled "Other Details" or a repeating custom field section.
  4. Payload Injection:
    • Target URL: http://localhost:8080/wp-admin/post.php
    • Method: POST
    • Payload: {"action": "editpost", "post_ID": "[ID]", "_wpnonce": "[NONCE]", "sdm_item_description": "<script>alert('XSS_SUCCESS')</script>", "post_title": "Malicious Download", "post_type": "sdm_downloads"}
    • Headers: Content-Type: application/x-www-form-urlencoded
  5. Triggering: Navigate to the public URL of the created download or create a page with the shortcode [sdm_download id="[ID]" fancy="1"].
  6. Admin Verification: Log in as an Administrator and view the page to confirm the script executes in the Admin's session.

6. Test Data Setup

  1. User: wp user create attacker attacker@example.com --role=contributor --user_pass=password
  2. Plugin Setup: Ensure "Simple Download Monitor" is installed and active.
  3. Shortcode Page: Create a public page to view the payload if the direct CPT link is restricted.
    • wp post create --post_type=page --post_status=publish --post_title="Download View" --post_content='[sdm_download id="REPLACE_WITH_ID"]'

7. Expected Results

  • The update_post_meta call will store the raw <script> tag in the wp_postmeta table.
  • When the download page or shortcode is rendered, the HTML source will contain the raw script: <div class="sdm_download_description"><script>alert('XSS_SUCCESS')</script></div>.
  • A browser alert box appearing with XSS_SUCCESS when the page is viewed.

8. Verification Steps

  1. Database Check: Use WP-CLI to verify the content of the meta field.
    • wp post meta get [POST_ID] sdm_item_description
    • Confirm it contains the unescaped <script> tag.
  2. Frontend Inspection: Use http_request to fetch the public page and grep for the payload.
    • response.body should contain <script>alert('XSS_SUCCESS')</script>.

9. Alternative Approaches

  • External Thumbnail URL: If sdm_item_description is sanitized in some versions, check sdm_external_thumbnail_url. If it is echoed into an <img> src or a value attribute without esc_attr, use: " onerror="alert(1).
  • Shortcode Attributes: Test if a Contributor can use the [sdm_download] shortcode in a post and if the plugin fails to escape attributes like button_text.
    • Payload: [sdm_download id="1" button_text='<script>alert(1)</script>']
  • AJAX Endpoint: Check if the plugin uses a specific AJAX handler for saving downloads (e.g., wp_ajax_sdm_save_download) which might lack nonce/capability checks.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Simple Download Monitor plugin for WordPress is vulnerable to Stored Cross-Site Scripting via custom fields in the 'sdm_downloads' post type. Authenticated attackers with Contributor-level access or higher can inject arbitrary JavaScript into fields such as the download description, which then executes when any user, including administrators, views the affected download page or a shortcode displaying it.

Vulnerable Code

// includes/admin-side/sdm-admin-individual-item-meta-boxes.php (approximate saving logic)
if (isset($_POST['sdm_item_description'])) {
    // No sanitization before saving metadata
    update_post_meta($post_id, 'sdm_item_description', $_POST['sdm_item_description']);
}

---

// includes/sdm-download-shortcodes.php (approximate rendering logic)
$description = get_post_meta($post_id, 'sdm_item_description', true);
// No output escaping before echoing to the page
echo '<div class="sdm_download_description">' . $description . '</div>';

Security Fix

--- a/includes/admin-side/sdm-admin-individual-item-meta-boxes.php
+++ b/includes/admin-side/sdm-admin-individual-item-meta-boxes.php
@@ -10,1 +10,1 @@
-update_post_meta($post_id, 'sdm_item_description', $_POST['sdm_item_description']);
+update_post_meta($post_id, 'sdm_item_description', wp_kses_post($_POST['sdm_item_description']));

--- a/includes/sdm-download-shortcodes.php
+++ b/includes/sdm-download-shortcodes.php
@@ -20,1 +20,1 @@
-echo '<div class="sdm_download_description">' . $description . '</div>';
+echo '<div class="sdm_download_description">' . wp_kses_post($description) . '</div>';

Exploit Outline

To exploit this vulnerability, an attacker requires a WordPress account with at least Contributor permissions. The attacker navigates to the 'Downloads' section and creates a new download item. In the description field (or any custom metadata field provided by the plugin), they inject a script payload such as <script>alert(1)</script>. Upon saving the post, the plugin stores the raw script in the database without sanitization. The XSS is triggered when any user visits the public permalink for that download or views a page where the download is rendered via a shortcode (e.g., [sdm_download id="123"]), as the plugin outputs the stored metadata without appropriate escaping.

Check if your site is affected.

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