Simple Download Monitor <= 4.0.5 - Authenticated (Contributor+) Stored Cross-Site Scripting via Custom Field
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:NTechnical Details
<=4.0.5Source Code
WordPress.org SVN# 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_descriptionor a specific metadata field such assdm_other_detailsor 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_downloadsposts. - Preconditions: The plugin must be active, and the attacker must have credentials for a Contributor-level account.
3. Code Flow
- Input: A Contributor submits a form to save or update an
sdm_downloadspost. - Processing: The plugin catches the save action, likely in
includes/admin-side/sdm-admin-individual-item-meta-boxes.phpwithin a function named similarly tosdm_save_download_meta_data. - 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 throughsanitize_text_fieldorwp_kses. - Retrieval: When a user visits the download page, the plugin retrieves the value using
get_post_meta( $post_id, 'some_meta_key', true ). - Sink: The value is output directly in the template (likely in
includes/sdm-download-shortcodes.phporsdm-post-type-content-handler.php) usingecho $meta_value;without callingesc_html,esc_attr, orwp_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:
- Create Contributor: Use WP-CLI to create a contributor user.
- Log In: Navigate to
wp-login.phpand authenticate. - Navigate to Create: Navigate to
wp-admin/post-new.php?post_type=sdm_downloads. - Extract Nonce: Use
browser_evalto extract the_wpnoncefrom the form.browser_eval("document.querySelector('#_wpnonce').value")
- 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:
- Setup Account: Create a contributor user
attacker. - Initial Navigation: Log in as
attackerand go to the "Add New Download" page. - 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 likesdm_external_thumbnail_urlif used in ansrcattribute.- Note: If the vulnerability is "via Custom Field," look for a field labeled "Other Details" or a repeating custom field section.
- 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
- Target URL:
- Triggering: Navigate to the public URL of the created download or create a page with the shortcode
[sdm_download id="[ID]" fancy="1"]. - 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
- User:
wp user create attacker attacker@example.com --role=contributor --user_pass=password - Plugin Setup: Ensure "Simple Download Monitor" is installed and active.
- 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_metacall will store the raw<script>tag in thewp_postmetatable. - 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_SUCCESSwhen the page is viewed.
8. Verification Steps
- 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.
- Frontend Inspection: Use
http_requestto fetch the public page and grep for the payload.response.bodyshould contain<script>alert('XSS_SUCCESS')</script>.
9. Alternative Approaches
- External Thumbnail URL: If
sdm_item_descriptionis sanitized in some versions, checksdm_external_thumbnail_url. If it is echoed into an<img> srcor avalueattribute withoutesc_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 likebutton_text.- Payload:
[sdm_download id="1" button_text='<script>alert(1)</script>']
- Payload:
- 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.
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
@@ -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'])); @@ -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.