Custom Admin Interface <= 7.40 - Missing Authorization
Description
The Custom Admin Interface plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 7.40. 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:NTechnical Details
<=7.40What Changed in the Fix
Changes introduced in v7.41
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2025-63038 ## 1. Vulnerability Summary The **WP Custom Admin Interface** plugin (<= 7.40) contains a missing authorization vulnerability. While the plugin provides extensive customization of the WordPress admin dashboard (menus, toolbars, CSS, etc.), certain admin…
Show full research plan
Exploitation Research Plan - CVE-2025-63038
1. Vulnerability Summary
The WP Custom Admin Interface plugin (<= 7.40) contains a missing authorization vulnerability. While the plugin provides extensive customization of the WordPress admin dashboard (menus, toolbars, CSS, etc.), certain administrative functions — specifically those triggered via init or admin_init hooks — fail to verify that the requesting user has the manage_options capability. This allows an authenticated user with Subscriber-level permissions to perform unauthorized actions, such as resetting or deleting plugin configurations.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php(which triggersadmin_init) or any frontend page (which triggersinit). - Vulnerable Action: The emergency configuration reset feature (
wp-custom-admin-interface=delete-menu) and potentially the settings import/save functionality. - Authentication: Subscriber-level (authenticated) access is required.
- Preconditions: The plugin must be active. For a visible impact, custom menu or toolbar settings should be configured.
3. Code Flow
- Entry Point: A Subscriber user sends a request to the site.
- Hook Registration: The plugin registers
wp_custom_admin_interface_check_for_delete_menu(inferred name) on theinithook, or handles settings inwp_custom_admin_interface_settings_initregistered onadmin_init. - Vulnerable Function: The handler checks for the presence of a specific GET or POST parameter (e.g.,
$_GET['wp-custom-admin-interface'] == 'delete-menu'). - Authorization Failure: The code likely uses
is_user_logged_in()or no check at all, rather thancurrent_user_can('manage_options'). - Sink: The function calls
delete_option('wp_custom_admin_interface_menu')or overwrites options viaupdate_option().
4. Nonce Acquisition Strategy
Based on the plugin's FAQ and standard "emergency reset" patterns, the delete-menu action may not require a nonce to allow administrators to recover a broken site. However, if other settings actions are targeted:
- Identify Script Localization: The plugin likely enqueues scripts for its admin pages. Use
grep -r "wp_localize_script" .to find the localization variable. - Shortcode Creation: If nonces are only loaded on specific pages, find a shortcode (e.g.,
[wp_custom_admin_interface_...]) usinggrep "add_shortcode" .. - Page Setup:
wp post create --post_type=page --post_status=publish --post_title="Nonce Page" --post_content='[shortcode_found]' - Extraction: Navigate to the page as the Subscriber and use
browser_evalto extract the nonce:- Example:
browser_eval("window.wp_custom_admin_interface_data?.nonce")(inferred variable name).
- Example:
5. Exploitation Strategy
The primary goal is to demonstrate unauthorized configuration deletion.
Step 1: Configuration Reset (Highest Probability)
- Action: Perform a GET request to the homepage with the reset parameter.
- Request:
GET /?wp-custom-admin-interface=delete-menu HTTP/1.1 Host: localhost:8080 Cookie: [Subscriber Cookies] - Expected Response: A redirect (302) to the admin dashboard, and the deletion of the
wp_custom_admin_interface_menuoption.
Step 2: Unauthorized Settings Modification (AJAX)
If the above fails, target the AJAX settings handler.
- Action: Search for
wp_ajax_handlers in the source. - Target Function:
wp_ajax_wp_custom_admin_interface_save_settings(inferred). - Payload: Attempt to change the
wp_custom_admin_interface_general_settings(inferred) to modify the footer text. - Request:
POST /wp-admin/admin-ajax.php HTTP/1.1 Content-Type: application/x-www-form-urlencoded Cookie: [Subscriber Cookies] action=wp_custom_admin_interface_save_settings&footer_text=Hacked+by+Subscriber
6. Test Data Setup
- Install & Activate: Ensure version 7.40 is installed.
- Configure Admin Interface:
# Create a dummy menu configuration to be deleted wp option update wp_custom_admin_interface_menu '{"test_menu": "modified"}' - Create User:
wp user create attacker attacker@example.com --role=subscriber --user_pass=password
7. Expected Results
- Success (Reset): The
wp_custom_admin_interface_menuoption is deleted or returned to default values in the database. - Success (Modification): The plugin settings are updated despite the user lacking administrative privileges.
- Response: The server returns a success code (200) or a redirect (302) instead of a forbidden (403).
8. Verification Steps
- Check Option Deletion:
wp option get wp_custom_admin_interface_menu # If the exploit worked, this will return 'false' or the default value. - Check Settings Modification:
wp option get wp_custom_admin_interface_general_settings # Verify if the injected footer_text or other parameter is present.
9. Alternative Approaches
If the delete-menu parameter is not processed via init, check for a direct POST handler in wp_custom_admin_interface_settings_init which is hooked to admin_init. Subscribers can trigger admin_init by visiting /wp-admin/admin-ajax.php. Send a POST request to that endpoint with parameters like wp_custom_admin_interface_export or wp_custom_admin_interface_import to test for other authorization gaps.
Summary
The WP Custom Admin Interface plugin for WordPress is vulnerable to unauthorized access in versions up to 7.40 due to missing capability checks on administrative functions. Authenticated attackers, including those with subscriber-level permissions, can dismiss admin notices for other users via an AJAX action or potentially trigger an emergency configuration reset that deletes custom menu settings.
Vulnerable Code
// wp-custom-admin-interface.php line 2450 if( wp_verify_nonce( $_POST['nonce'], 'wp_custom_admin_interface_notice' ) ){ //get user input $userId = intval($_POST['userId']); //create transient name - an stands for admin notice $transientName = 'an_dismiss_'.$userId; //create actual transient set_transient($transientName,true,0); }
Security Fix
@@ -2450,13 +2450,18 @@ if( wp_verify_nonce( $_POST['nonce'], 'wp_custom_admin_interface_notice' ) ){ //get user input - $userId = intval($_POST['userId']); + $userId = intval($_POST['userId']); - //create transient name - an stands for admin notice - $transientName = 'an_dismiss_'.$userId; + $current_user_id = intval(get_current_user_id()); + + if($userId == $current_user_id){ + //create transient name - an stands for admin notice + $transientName = 'an_dismiss_'.$userId; + + //create actual transient + set_transient($transientName,true,0); + } - //create actual transient - set_transient($transientName,true,0); }
Exploit Outline
1. Authenticate as a Subscriber-level user. 2. Obtain a valid nonce for the 'wp_custom_admin_interface_notice' action by inspecting the localized script data or HTML source of the WordPress admin profile page. 3. Send a POST request to `/wp-admin/admin-ajax.php` with the action (likely `wp_custom_admin_interface_dismiss_notice`), the stolen nonce, and a target `userId` (e.g., an Administrator's ID). This will dismiss admin notices for the target user. 4. Alternatively, attempt to reset the plugin's configuration by sending a GET request to the site root with the parameter `/?wp-custom-admin-interface=delete-menu`. This exploit works if the plugin fails to verify the `manage_options` capability before deleting the `wp_custom_admin_interface_menu` option.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.