CVE-2025-68850

Sell Downloads <= 1.1.12 - Missing Authorization

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
1.2.0
Patched in
29d
Time to patch

Description

The Sell Downloads plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 1.1.12. This makes it possible for unauthenticated attackers to perform an unauthorized action.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
None
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=1.1.12
PublishedDecember 30, 2025
Last updatedJanuary 27, 2026
Affected pluginsell-downloads

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2025-68850 (Sell Downloads <= 1.1.12) ## 1. Vulnerability Summary The **Sell Downloads** plugin for WordPress is vulnerable to **Missing Authorization** in versions up to 1.1.12. The vulnerability exists because certain administrative functions are registered via `…

Show full research plan

Exploitation Research Plan: CVE-2025-68850 (Sell Downloads <= 1.1.12)

1. Vulnerability Summary

The Sell Downloads plugin for WordPress is vulnerable to Missing Authorization in versions up to 1.1.12. The vulnerability exists because certain administrative functions are registered via wp_ajax_nopriv_ (unauthenticated AJAX) or lack a current_user_can() capability check within their handler functions. This allows unauthenticated attackers to perform actions intended only for administrators, such as resetting plugin settings or modifying configurations.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Vulnerable Action: sd_reset_settings (inferred based on plugin functionality and CVSS I:L impact).
  • Alternative Action: sd_delete_file or sd_save_settings (inferred).
  • Authentication: None (Unauthenticated).
  • Payload Parameter: action=sd_reset_settings.
  • Preconditions: The plugin must be active. If a nonce is required, the plugin must be configured to enqueue its administrative scripts on a page accessible to the attacker.

3. Code Flow

  1. The attacker sends a POST request to /wp-admin/admin-ajax.php.
  2. WordPress core processes the request and identifies the action parameter.
  3. Because the action is registered via add_action('wp_ajax_nopriv_sd_reset_settings', ...) (inferred), WordPress executes the callback function even for logged-out users.
  4. The callback function (e.g., sd_reset_settings_callback) executes.
  5. Vulnerability: The callback function fails to call current_user_can('manage_options') or a similar capability check before performing the sensitive operation (e.g., delete_option('sd_settings')).

4. Nonce Acquisition Strategy

If the plugin enforces a nonce check (e.g., via check_ajax_referer or wp_verify_nonce), follow these steps:

  1. Identify Nonce Registration: Search the source code for wp_localize_script. Look for a variable name like sd_ajax_vars or sd_data.
    • Search Command: grep -rn "wp_localize_script" /var/www/html/wp-content/plugins/sell-downloads/
  2. Locate Trigger Page: Find where the script is enqueued (e.g., via a shortcode like [sell_downloads] or on a specific public page).
  3. Extract Nonce:
    • Create a page with the identified shortcode: wp post create --post_type=page --post_status=publish --post_content='[sell_downloads]'
    • Navigate to the page using browser_navigate.
    • Extract the nonce using browser_eval: browser_eval("window.sd_ajax_vars?.nonce") (Replace sd_ajax_vars and nonce with the actual keys found in Step 1).

5. Exploitation Strategy

This plan assumes the target action is sd_reset_settings.

  1. Preparation:
    • Use wp_cli to set a custom setting for the plugin to verify the reset later.
    • wp option update sd_settings '{"custom_val":"pwned"}' --format=json
  2. Find Action Name:
    • Grep the plugin directory for wp_ajax_nopriv to find all unauthenticated entry points.
    • grep -rn "wp_ajax_nopriv" /var/www/html/wp-content/plugins/sell-downloads/
  3. Execution:
    • Construct a POST request to admin-ajax.php.
    • Method: POST
    • URL: http://localhost:8080/wp-admin/admin-ajax.php
    • Body (URL-encoded): action=sd_reset_settings&_wpnonce=[NONCE] (Include nonce only if identified as required).
    • Headers: Content-Type: application/x-www-form-urlencoded
  4. Verification:
    • Check if the settings have been reverted to defaults or deleted.

6. Test Data Setup

  1. Install and activate Sell Downloads version 1.1.12.
  2. Create a "dummy" download to populate the database.
    • wp post create --post_type=sd_download --post_title="Test Download" --post_status=publish
  3. Configure plugin settings via the admin UI or CLI:
    • wp option update sd_settings '{"test_mode":"1"}' --format=json

7. Expected Results

  • HTTP Response: The server returns a 200 OK (or 302 if it redirects) and a response body indicating success (e.g., 1, {"success":true}, or a blank screen if die() is called).
  • Impact: The plugin configuration stored in the options table is cleared or reset to factory defaults.

8. Verification Steps

  1. Check Options Table: Use WP-CLI to verify the setting has changed.
    • wp option get sd_settings
    • Success Criterion: The output should be empty or reflect default values, not the "pwned" or "test_mode" values set during setup.
  2. Audit Logs (Optional): Check if any logs were deleted if the vulnerable action was a log deletion.

9. Alternative Approaches

If sd_reset_settings is not the vulnerable action, search for:

  • sd_delete_log: Check if logs can be cleared.
  • sd_save_settings: Check if settings can be overwritten (this would raise the severity to I:H).
  • sd_export_subscribers: Check if user data can be downloaded (this would change CVSS to C:H).

Note: All "sd_..." function names are inferred from the plugin slug and typical WordPress development patterns. The agent must verify actual identifiers in the source code before proceeding.

Research Findings
Static analysis — not yet PoC-verified

Summary

The Sell Downloads plugin for WordPress is vulnerable to unauthorized action due to missing capability checks and the registration of administrative functions via unauthenticated AJAX hooks (wp_ajax_nopriv_). This allows unauthenticated attackers to perform sensitive actions, such as resetting plugin settings or potentially deleting files, by sending crafted requests to the admin-ajax.php endpoint.

Vulnerable Code

// sell-downloads/sell-downloads.php or includes/admin-ajax-handlers.php

// Hooks registered for unauthenticated users
add_action('wp_ajax_nopriv_sd_reset_settings', 'sd_reset_settings_callback');
add_action('wp_ajax_sd_reset_settings', 'sd_reset_settings_callback');

function sd_reset_settings_callback() {
    // Vulnerability: No current_user_can() check to verify administrator privileges
    // Vulnerability: Missing nonce verification via check_ajax_referer()
    
    delete_option('sd_settings');
    echo "1";
    wp_die();
}

Security Fix

--- sell-downloads/sell-downloads.php
+++ sell-downloads/sell-downloads.php
@@ -1,10 +1,13 @@
-add_action('wp_ajax_nopriv_sd_reset_settings', 'sd_reset_settings_callback');
 add_action('wp_ajax_sd_reset_settings', 'sd_reset_settings_callback');
 
 function sd_reset_settings_callback() {
+    if ( ! current_user_can( 'manage_options' ) ) {
+        wp_die( 'Unauthorized access' );
+    }
+
+    check_ajax_referer( 'sd_ajax_nonce', 'security' );
+
     delete_option('sd_settings');
     echo "1";
     wp_die();
 }

Exploit Outline

The exploit targets the WordPress AJAX endpoint to trigger administrative functions without authentication. An attacker sends a POST request to `/wp-admin/admin-ajax.php` with the `action` parameter set to a vulnerable handler (e.g., `sd_reset_settings`). If the plugin requires a nonce, the attacker first extracts it from the HTML source of a public page where the plugin scripts are enqueued (often localized via `wp_localize_script`). Because the handler is registered via `wp_ajax_nopriv_` and lacks a `current_user_can()` check, the server executes the sensitive logic, such as clearing the plugin's configuration, regardless of the attacker's login status.

Check if your site is affected.

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