[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fUrdLPhSvGRJ97fXdy5VDScFVdbB_Gn8RD3hWzT_lfAE":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-32460","ultra-addons-for-contact-form-7-authenticated-contributor-stored-cross-site-scripting","Ultra Addons for Contact Form 7 \u003C= 3.5.36 - Authenticated (Contributor+) Stored Cross-Site Scripting","The Ultra Addons for Contact Form 7 plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 3.5.36 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with contributor-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.","ultimate-addons-for-contact-form-7",null,"\u003C=3.5.36","3.5.37","medium",6.4,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:C\u002FC:L\u002FI:L\u002FA:N","Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')","2026-03-14 00:00:00","2026-03-19 15:11:08",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F2be06087-4616-47bb-8a33-3bba97c47cb2?source=api-prod",6,[22,23,24],"admin\u002Ftf-options\u002FTF_Options.php","readme.txt","ultimate-addons-for-contact-form-7.php","researched",false,3,"# Research Plan: Ultra Addons for Contact Form 7 Stored XSS (CVE-2026-32460)\n\n## 1. Vulnerability Summary\nThe **Ultra Addons for Contact Form 7** plugin (up to 3.5.36) contains a stored cross-site scripting (XSS) vulnerability in its option import functionality. The vulnerability exists because the AJAX handler `uacf7_option_import_callback` fails to properly validate the user's capabilities (due to an incorrect use of `is_admin()`) and subsequently stores unsanitized JSON data into post meta. This data is then rendered on the frontend or backend without sufficient escaping.\n\n## 2. Attack Vector Analysis\n*   **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Action:** `uacf7_option_import` (hooked via `wp_ajax_uacf7_option_import`)\n*   **Vulnerable Parameter:** `tf_import_option` (JSON string)\n*   **Required Authentication:** Contributor or higher.\n*   **Privilege Escalation Mechanism:** The plugin attempts to restrict the action to administrators but uses the following check:\n    ```php\n    if ( $current_user_role !== 'administrator' && ! is_admin() ) {\n        wp_die( 'You do not have sufficient permissions to access this page.' );\n    }\n    ```\n    In the context of an AJAX request (`admin-ajax.php`), `is_admin()` always returns `true`. Therefore, the condition `$current_user_role !== 'administrator' && false` always evaluates to `false`, allowing any authenticated user with access to the admin dashboard (like a Contributor) to bypass the check.\n\n## 3. Code Flow\n1.  **Entry Point:** `UACF7_Options::__construct()` registers the AJAX action:\n    `add_action( 'wp_ajax_uacf7_option_import', array( $this, 'uacf7_option_import_callback' ) );`\n2.  **Nonce Verification:** `uacf7_option_import_callback()` verifies the nonce `tf_options_nonce`.\n3.  **Authorization Bypass:** The function performs the flawed role check described above.\n4.  **Data Processing:**\n    *   `$imported_data` is created by `json_decode( wp_unslash( trim( $_POST['tf_import_option'] ) ), true );`.\n    *   `$form_id` is retrieved from `$_POST['form_id']`.\n5.  **Sink:** The unsanitized array is saved to the database:\n    `update_post_meta( $form_id, 'uacf7_form_opt', $imported_data );`\n6.  **Rendering:** When the contact form (ID: `$form_id`) is rendered, the plugin retrieves `uacf7_form_opt` and outputs values (likely in a style block or wrapper div) without proper escaping.\n\n## 4. Nonce Acquisition Strategy\nThe nonce `tf_options_nonce` is localized into the JavaScript variable `tf_options_params`. This occurs in `admin\u002Ftf-options\u002FTF_Options.php` within the `tf_options_admin_enqueue_scripts` method.\n\n**Strategy:**\n1.  Log in as a Contributor.\n2.  The script is enqueued on several admin screens, including the Contact Form 7 list page (`toplevel_page_wpcf7`).\n3.  Navigate to `\u002Fwp-admin\u002Fadmin.php?page=wpcf7`.\n4.  Execute `browser_eval` to extract the nonce:\n    `browser_eval(\"window.tf_options_params?.tf_options_nonce\")`\n\n## 5. Exploitation Strategy\n1.  **Preparation:** Identify an existing Contact Form 7 form ID (e.g., `123`). If none exist, create one.\n2.  **Payload Crafting:** Create a JSON object where values contain XSS payloads. Since this meta is for \"Form Options\" (styling), common fields likely include font families or custom CSS.\n    *   `payload = {\"uacf7_custom_css\": \"\u003C\u002Fstyle>\u003Cscript>alert(document.domain)\u003C\u002Fscript>\"}`\n3.  **Request:** Send a POST request to `admin-ajax.php`.\n    *   **Action:** `uacf7_option_import`\n    *   **ajax_nonce:** [Extracted Nonce]\n    *   **form_id:** 123\n    *   **tf_import_option:** `{\"any_key\": \"\u003Cimg src=x onerror=alert(1)>\"}`\n4.  **Verification:** View the page where Contact Form 123 is embedded.\n\n## 6. Test Data Setup\n1.  **Install Plugins:** Contact Form 7 and Ultra Addons for Contact Form 7 (v3.5.36).\n2.  **Create User:** A user with the `contributor` role.\n3.  **Create Form:** A Contact Form 7 form. Note its ID (e.g., `wp-post-create` or check the UI).\n4.  **Create Page:** A public page containing the shortcode: `[contact-form-7 id=\"123\" title=\"Test Form\"]`.\n\n## 7. Expected Results\n*   The AJAX request should return a JSON success message: `{\"success\":true,\"data\":{\"status\":\"success\",\"message\":\"Options imported successfully!\"}}`.\n*   The database should show the payload stored in the `wp_postmeta` table for the specified `post_id` under the key `uacf7_form_opt`.\n*   When visiting the public page, an alert box should trigger.\n\n## 8. Verification Steps (WP-CLI)\nCheck if the meta was successfully injected:\n```bash\nwp post meta get [FORM_ID] uacf7_form_opt --format=json\n```\nThis should return the JSON object containing the `\u003Cscript>` or `\u003Cimg>` tag.\n\n## 9. Alternative Approaches\nIf the `tf_options_nonce` is not localized on the main Contact Form 7 page for Contributors, try navigating to:\n*   `\u002Fwp-admin\u002Fadmin.php?page=uacf7_settings`\n*   `\u002Fwp-admin\u002Fadmin.php?page=uacf7_setup-wizard`\n\nIf a specific key is required in the JSON for it to be rendered, analyze `admin\u002Ftf-options\u002Fmetaboxes\u002F` or `options\u002F` files to find valid option keys used by the plugin (e.g., `form-title-color`, `form-background-color`). A reliable fallback is to inject into every key:\n`{\"key1\": \"\u003Cscript>alert(1)\u003C\u002Fscript>\", \"key2\": \"\u003Cscript>alert(1)\u003C\u002Fscript>\" ...}`","The Ultra Addons for Contact Form 7 plugin is vulnerable to Stored Cross-Site Scripting via the 'uacf7_option_import' AJAX action due to a flawed capability check and lack of output escaping. Authenticated attackers with Contributor-level access can bypass the intended administrator-only restriction and inject malicious scripts into contact form metadata, which then executes when the form is viewed.","\u002F\u002F admin\u002Ftf-options\u002FTF_Options.php:64\n\t\tpublic function uacf7_option_import_callback() {\n\n\t\t\tif ( ! isset( $_POST['ajax_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['ajax_nonce'] ) ), 'tf_options_nonce' ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t\u002F\u002F  Checked Currenct can save option\n\t\t\t$current_user = wp_get_current_user();\n\t\t\t$current_user_role = $current_user->roles[0];\n\n\t\t\tif ( $current_user_role !== 'administrator' && ! is_admin() ) {\n\t\t\t\twp_die( 'You do not have sufficient permissions to access this page.' );\n\t\t\t}\n\n\t\t\t$imported_data = json_decode( wp_unslash( trim( $_POST['tf_import_option'] ) ), true );\n\t\t\t$form_id = stripslashes( $_POST['form_id'] );\n\n\t\t\t$response = [ \n\t\t\t\t'status' => 'error',\n\t\t\t\t'message' => __( 'Something went wrong!', 'ultimate-addons-cf7' ),\n\t\t\t];\n\n\t\t\tif ( ! empty( $imported_data ) && is_array( $imported_data ) ) {\n\t\t\t\tif ( $form_id != 0 ) {\n\n\t\t\t\t\tupdate_post_meta( $form_id, 'uacf7_form_opt', $imported_data );\n\n\t\t\t\t}","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fultimate-addons-for-contact-form-7\u002F3.5.36\u002Fadmin\u002Ftf-options\u002FTF_Options.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fultimate-addons-for-contact-form-7\u002F3.5.37\u002Fadmin\u002Ftf-options\u002FTF_Options.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fultimate-addons-for-contact-form-7\u002F3.5.36\u002Fadmin\u002Ftf-options\u002FTF_Options.php\t2026-02-03 18:51:00.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fultimate-addons-for-contact-form-7\u002F3.5.37\u002Fadmin\u002Ftf-options\u002FTF_Options.php\t2026-02-26 15:44:42.000000000 +0000\n@@ -64,12 +64,10 @@\n \t\t\t\treturn;\n \t\t\t}\n \n-\t\t\t\u002F\u002F  Checked Currenct can save option\n-\t\t\t$current_user = wp_get_current_user();\n-\t\t\t$current_user_role = $current_user->roles[0];\n-\n-\t\t\tif ( $current_user_role !== 'administrator' && ! is_admin() ) {\n-\t\t\t\twp_die( 'You do not have sufficient permissions to access this page.' );\n+\t\t\tif ( ! current_user_can( 'manage_options' ) ) {\n+\t\t\t\twp_send_json_error(\n+\t\t\t\t\t[ 'message' => __( 'You do not have sufficient permissions to access this page.', 'ultimate-addons-cf7' ) ]\n+\t\t\t\t);\n \t\t\t}\n \n \t\t\t$imported_data = json_decode( wp_unslash( trim( $_POST['tf_import_option'] ) ), true );","The exploit targets the 'uacf7_option_import' AJAX action. An authenticated user (Contributor+) can bypass the permission check because it incorrectly uses is_admin() within an AJAX context, where it always returns true. The attacker extracts the 'tf_options_nonce' from the WordPress admin dashboard scripts and sends a POST request to admin-ajax.php. This request includes a 'tf_import_option' JSON payload containing a malicious script and a target 'form_id'. The plugin saves this unsanitized JSON data into the 'uacf7_form_opt' post meta, which triggers the XSS payload whenever the associated contact form is rendered on the site.","gemini-3-flash-preview","2026-04-18 03:44:56","2026-04-18 03:45:19",{"type":37,"vulnerable_version":38,"fixed_version":11,"vulnerable_browse":39,"vulnerable_zip":40,"fixed_browse":41,"fixed_zip":42,"all_tags":43},"plugin","3.5.36","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fultimate-addons-for-contact-form-7\u002Ftags\u002F3.5.36","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fultimate-addons-for-contact-form-7.3.5.36.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fultimate-addons-for-contact-form-7\u002Ftags\u002F3.5.37","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fultimate-addons-for-contact-form-7.3.5.37.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fultimate-addons-for-contact-form-7\u002Ftags"]