Super Custom Login <= 1.1 - Missing Authorization
Description
The Super Custom Login 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. 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:NTechnical Details
<=1.1This research plan targets CVE-2026-39605, a Missing Authorization vulnerability in the **Super Custom Login** plugin (<= 1.1). The vulnerability allows unauthenticated attackers to perform unauthorized actions, typically modifying plugin settings due to the lack of capability checks in administrati…
Show full research plan
This research plan targets CVE-2026-39605, a Missing Authorization vulnerability in the Super Custom Login plugin (<= 1.1). The vulnerability allows unauthenticated attackers to perform unauthorized actions, typically modifying plugin settings due to the lack of capability checks in administrative hooks.
1. Vulnerability Summary
The Super Custom Login plugin fails to implement proper authorization checks (e.g., current_user_can()) on a function responsible for saving plugin configurations. This function is likely hooked to admin_init or registered as an AJAX action via wp_ajax_nopriv_*. Because admin_init is triggered even when accessing admin-ajax.php or admin-post.php (even by unauthenticated users), any logic inside an admin_init hook that lacks a capability check is accessible to any visitor.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.phpor/wp-admin/admin-post.php(alternatively, any admin-context URL if the hook isadmin_init). - Action:
scl_save_settingsorsuper_custom_login_save(inferred - needs verification in source). - Payload Parameter: Likely a POST request containing settings such as
scl_logo_url,scl_login_bg_color, orscl_custom_css. - Authentication: None (Unauthenticated).
- Preconditions: The plugin must be active.
3. Code Flow (Inferred)
- Entry Point: An unauthenticated user sends a POST request to
/wp-admin/admin-ajax.php. - Hook Execution: WordPress initializes the admin environment, firing the
admin_inithook. - Vulnerable Function: The plugin has registered a function (e.g.,
scl_save_options_callback) to theadmin_inithook. - Authorization Failure: The function checks if specific POST parameters are set (e.g.,
if ( isset( $_POST['scl_submit'] ) )) but fails to verifycurrent_user_can( 'manage_options' ). - Sink: The function calls
update_option( 'scl_settings', ... )with user-supplied data from$_POST.
4. Nonce Acquisition Strategy
If the plugin uses check_admin_referer() or wp_verify_nonce(), we must find where the nonce is leaked.
- Identify Shortcodes: Search for
add_shortcodein the plugin files to see if any frontend elements exist. - Search for Localized Scripts: Look for
wp_localize_scriptin the codebase.- Search command:
grep -r "wp_localize_script" .
- Search command:
- Execution:
- If a nonce is leaked in a JS variable (e.g.,
scl_vars.nonce):- Navigate to the site homepage or login page using
browser_navigate. - Execute
browser_eval("window.scl_vars?.nonce")to retrieve it.
- Navigate to the site homepage or login page using
- If a nonce is leaked in a JS variable (e.g.,
- Bypass Check: Check if the code uses
check_admin_referer( '...', '...', false ). If the third parameter isfalseand the return value isn't checked, the nonce is bypassed.
5. Exploitation Strategy
We will attempt to modify the plugin's settings to change the login page's appearance or inject custom CSS, confirming unauthorized write access.
Step 1: Identify the Action and Parameters
- Search the plugin for
update_option. - Search command:
grep -r "update_option" . - Identify the POST key that triggers the update (e.g.,
scl_updateorsubmit).
- Search the plugin for
Step 2: Construct the Payload
- Method: POST
- URL:
http://localhost:8080/wp-admin/admin-ajax.php(oradmin-post.php) - Body (URL-encoded):
action=[INFERRED_ACTION]&scl_logo_url=http://attacker.com/malicious.png&scl_custom_css=body{display:none !important;}&[TRIGGER_PARAM]=1 - Headers:
Content-Type: application/x-www-form-urlencoded
Step 3: Execute Request
- Use the
http_requesttool to send the payload.
- Use the
6. Test Data Setup
- Install and activate the
super-custom-loginplugin. - (Optional) If the plugin requires a specific page to be visited for nonce leakage, create it:
wp post create --post_type=page --post_status=publish --post_content='[super_custom_login_placeholder]'
7. Expected Results
- The HTTP response should ideally be a
302 redirector a200 OK(if AJAX). - The option in the WordPress database associated with the plugin settings will be updated with the attacker's values.
8. Verification Steps
After the exploit, verify the changes using WP-CLI:
- Check Option Value:
wp option get scl_settings(Verifyscl_logo_urlorscl_custom_cssmatches the payload).
- Visual Confirmation:
- Navigate to the WordPress login page (
/wp-login.php) and check if the custom CSS or logo has been applied.
- Navigate to the WordPress login page (
9. Alternative Approaches
- If
admin_initis not the hook: Check forwp_ajax_nopriv_handlers. If the plugin uses an AJAX handler for settings but registered it withnopriv, any user can call it. - XSS Injection: If the plugin allows saving "Custom JavaScript" or "Footer Text" without sanitization/authorization, escalate the "Missing Authorization" to Stored XSS by injecting
<script>alert(document.domain)</script>. - Settings Reset: Check if there is a "Reset Settings" action that also lacks authorization, which could be used for an Unauthorized Deletion/Denial of Service attack on the plugin's configuration.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.