CVE-2026-25011

Custom Admin Interface <= 7.41 - Missing Authorization

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
7.42
Patched in
9d
Time to patch

Description

The WP Custom Admin Interface plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 7.41. This makes it possible for authenticated attackers, with Subscriber-level access and above, to perform an unauthorized action.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=7.41
PublishedJanuary 25, 2026
Last updatedFebruary 2, 2026

What Changed in the Fix

Changes introduced in v7.42

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-25011 ## 1. Vulnerability Summary The **WP Custom Admin Interface** plugin (versions <= 7.41) contains a missing authorization vulnerability. Specifically, several AJAX actions and/or initialization hooks lack a `current_user_can('manage_options')` check. Thi…

Show full research plan

Exploitation Research Plan - CVE-2026-25011

1. Vulnerability Summary

The WP Custom Admin Interface plugin (versions <= 7.41) contains a missing authorization vulnerability. Specifically, several AJAX actions and/or initialization hooks lack a current_user_can('manage_options') check. This allows authenticated users with Subscriber-level permissions to perform administrative actions such as modifying plugin settings, resetting admin menus, or injecting custom content into the admin interface.

2. Attack Vector Analysis

  • Vulnerable Endpoints:
    1. /wp-admin/admin-ajax.php (Primary)
    2. /index.php (via query parameters, per the plugin's "delete-menu" feature)
  • Vulnerable Actions:
    • wp_ajax_wp_custom_admin_interface_save_settings
    • wp_ajax_wp_custom_admin_interface_reset_settings
    • wp_custom_admin_interface_delete_menu (via init hook)
  • Required Capability: Subscriber level access (PR:L).
  • Payload Parameters:
    • action: wp_custom_admin_interface_save_settings
    • security: The nonce value.
    • data: A serialized string or object containing the settings to be updated.

3. Code Flow

  1. Registration: The plugin registers AJAX handlers in wp-custom-admin-interface.php (or an included settings file) using add_action( 'wp_ajax_wp_custom_admin_interface_save_settings', ... ).
  2. Missing Check: The handler function (e.g., wp_custom_admin_interface_save_settings()) uses check_ajax_referer( 'wp_custom_admin_interface_nonce', 'security' ) to verify the nonce but fails to call current_user_can( 'manage_options' ).
  3. Execution: Since wp_ajax_ hooks are available to any logged-in user, and Subscribers can access the dashboard to receive the enqueued nonce, they can trigger the function.
  4. Sink: The function calls update_option(), allowing the Subscriber to overwrite the plugin's configuration.

4. Nonce Acquisition Strategy

The plugin enqueues its settings script and localizes a nonce for AJAX operations. Although the settings page is restricted, the script is often enqueued globally in the admin area.

  1. Navigate to Dashboard: Log in as a Subscriber and go to /wp-admin/index.php.
  2. Extract Nonce: Use browser_eval to extract the nonce from the localized JavaScript object.
    • JS Object: window.wp_custom_admin_interface_settings (inferred from plugin slug)
    • Key: nonce
    • Command: browser_eval("window.wp_custom_admin_interface_settings?.nonce")
  3. Alternative: If not localized there, search the page source for any string containing wp_custom_admin_interface_nonce.

5. Exploitation Strategy

We will attempt to modify the Admin Footer Text setting to demonstrate unauthorized integrity modification.

Step-by-Step Plan:

  1. Pre-exploitation: As Admin, set the footer text to "Original Admin Footer".
  2. Authentication: Authenticate as a Subscriber.
  3. Nonce Capture: Use the browser to navigate to /wp-admin/index.php and extract the security nonce from window.wp_custom_admin_interface_settings.nonce.
  4. Execution: Send a POST request to admin-ajax.php to overwrite settings.
    • URL: http://vulnerable-test.local/wp-admin/admin-ajax.php
    • Method: POST
    • Content-Type: application/x-www-form-urlencoded
    • Body:
      action=wp_custom_admin_interface_save_settings&security=[NONCE]&data=wp_custom_admin_interface_general_settings%5Bfooter_text%5D=Exploited+by+Subscriber
      
    • Note: If data requires a JSON string instead of form-encoded, adjust the payload accordingly.

6. Test Data Setup

  1. Users:
    • Admin: admin / password
    • Subscriber: attacker / password
  2. Plugin Configuration:
    • Ensure the plugin is active.
    • As Admin, go to Custom Admin Interface > General Settings and set "Custom Footer Text" to "Standard Footer".
    • Save changes.

7. Expected Results

  • The AJAX request should return a 200 OK or a JSON success response (e.g., {"success":true}).
  • The WordPress database option wp_custom_admin_interface_general_settings should now contain "Exploited by Subscriber" in the footer_text field.

8. Verification Steps

  1. Check via WP-CLI:
    wp option get wp_custom_admin_interface_general_settings --format=json
    
    Verify that the footer_text value has changed.
  2. Check Admin UI: Log in as Admin and navigate to any admin page. Scroll to the bottom and verify the footer text has been modified to "Exploited by Subscriber".

9. Alternative Approaches

The "Delete Menu" Bypass

The readme.txt mentions a feature to delete menus via a GET parameter. If the AJAX path fails, try this:

  • URL: http://vulnerable-test.local/index.php?wp-custom-admin-interface=delete-menu
  • Method: GET (while logged in as Subscriber)
  • Verification: Check if the option wp_custom_admin_interface_admin_menu_settings is deleted:
    wp option get wp_custom_admin_interface_admin_menu_settings
    
    (Expected: "Error: Could not find 'wp_custom_admin_interface_admin_menu_settings' option.")
Research Findings
Static analysis — not yet PoC-verified

Summary

The WP Custom Admin Interface plugin for WordPress is vulnerable to unauthorized access because it fails to perform capability checks on administrative functions registered via AJAX. This allows authenticated users with Subscriber-level access to perform unauthorized actions such as clearing transients or potentially modifying plugin settings.

Vulnerable Code

// wp-custom-admin-interface.php line 2476
function wp_custom_admin_interface_delete_dismiss_transients() {
	global $wpdb; 
    $sql = "DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_an_dismiss_%'";
    $wpdb->query($sql);
    echo "success";    
    die();    
}
add_action( 'wp_ajax_delete_dismiss_transients', 'wp_custom_admin_interface_delete_dismiss_transients');

Security Fix

--- /home/deploy/wp-safety.org/data/plugin-versions/wp-custom-admin-interface/7.41/wp-custom-admin-interface.php	2026-01-06 23:32:10.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/wp-custom-admin-interface/7.42/wp-custom-admin-interface.php	2026-01-19 21:25:46.000000000 +0000
@@ -2474,11 +2474,16 @@
 *	Function to clear transients related to the admin notice
 */
 function wp_custom_admin_interface_delete_dismiss_transients() {
-	global $wpdb; 
-    $sql = "DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_an_dismiss_%'";
-    $wpdb->query($sql);
-    echo "success";    
+
+    if ( current_user_can( 'administrator' ) ) {
+
+        global $wpdb; 
+        $sql = "DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_an_dismiss_%'";
+        $wpdb->query($sql);
+        echo "success";   
+    } 
     die();    
+
 }
 add_action( 'wp_ajax_delete_dismiss_transients', 'wp_custom_admin_interface_delete_dismiss_transients');

Exploit Outline

The exploit targets missing authorization checks in the plugin's AJAX handlers. 1. Authentication: The attacker authenticates as a Subscriber-level user. 2. Nonce Retrieval: The attacker navigates to the WordPress dashboard (/wp-admin/) and extracts the 'wp_custom_admin_interface_nonce' or the 'security' parameter from localized scripts (like window.wp_custom_admin_interface_settings). 3. Unauthorized Action: The attacker sends a POST request to /wp-admin/admin-ajax.php with the 'action' parameter set to 'delete_dismiss_transients' or 'wp_custom_admin_interface_save_settings', including the captured nonce. 4. Impact: Because the backend function only checks the nonce and not the user's capabilities, the administrative action (such as deleting transients or updating plugin options) is executed on behalf of the Subscriber.

Check if your site is affected.

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