[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fWisBKbdlhvxfFHO5UeAJqE92h4QN-ABhfjdBPWIfIGw":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":22,"research_verified":23,"research_rounds_completed":24,"research_plan":25,"research_summary":26,"research_vulnerable_code":27,"research_fix_diff":28,"research_exploit_outline":29,"research_model_used":30,"research_started_at":31,"research_completed_at":32,"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":23,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":23,"source_links":33},"CVE-2026-0633","metform-contact-form-survey-quiz-custom-form-builder-for-elementor-unauthenticated-form-submission-exposure-via-forgeabl","MetForm – Contact Form, Survey, Quiz, & Custom Form Builder for Elementor \u003C= 4.1.0 - Unauthenticated Form Submission Exposure via Forgeable Cookie Value","The MetForm – Contact Form, Survey, Quiz, & Custom Form Builder for Elementor plugin for WordPress is vulnerable to Sensitive Information Exposure in versions up to, and including, 4.1.0. This is due to the use of a forgeable cookie value derived only from the entry ID and current user ID without a server-side secret. This makes it possible for unauthenticated attackers to access form submission entry data via MetForm shortcodes for entries created within the transient TTL (default is 15 minutes).","metform",null,"\u003C=4.1.0","4.1.1","low",3.7,"CVSS:3.1\u002FAV:N\u002FAC:H\u002FPR:N\u002FUI:N\u002FS:U\u002FC:L\u002FI:N\u002FA:N","Improper Authentication","2026-01-23 19:35:07","2026-01-24 08:26:37",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fd72cc420-1ff5-403b-b4ea-7c820fdebcf3?source=api-prod",1,[],"researched",false,3,"# Exploitation Research Plan - CVE-2026-0633\n\n## 1. Vulnerability Summary\nMetForm (versions \u003C= 4.1.0) suffers from a sensitive information exposure vulnerability. The plugin uses a forgeable cookie, `mf_recent_entry_id`, to determine if a user should be shown the details of a recent form submission (e.g., a \"Success Message\" or submission summary). Because the cookie value is derived simply from the Entry ID and the User ID (e.g., `123|0` for unauthenticated users) without a server-side secret or HMAC, an attacker can forge this cookie for any entry ID. If the entry's data is still within the 15-minute transient TTL, the plugin will display that entry's data to the attacker via the form shortcode.\n\n## 2. Attack Vector Analysis\n- **Vulnerable Component:** MetForm Form Shortcode (`[metform_form]`) and its associated success message rendering logic.\n- **Endpoint:** Any WordPress page containing a MetForm form.\n- **Vulnerable Parameter:** `mf_recent_entry_id` (Cookie).\n- **Authentication:** Unauthenticated.\n- **Preconditions:** \n    1. A form must be created and active.\n    2. A victim must have submitted the form within the last 15 minutes.\n    3. The attacker must guess or know the Entry ID (entries use auto-incrementing IDs).\n\n## 3. Code Flow (Inferred from Patch and Description)\n1.  **Submission:** When a user submits a MetForm form, `Metform\\Core\\Entries\\Action::insert()` is called.\n2.  **Transient Storage:** The plugin saves the submission data to a transient named `mf_entry_{entry_id}` with a 15-minute expiration.\n3.  **Cookie Generation:** The plugin sets a cookie `mf_recent_entry_id` with the value `{$entry_id}|{$user_id}`.\n4.  **Display Logic:** When the form page is reloaded or the user is redirected to a success page, the `[metform_form]` shortcode (rendered via `Metform\\Core\\Forms\\Shortcode::render_form()`) checks for the `mf_recent_entry_id` cookie.\n5.  **Vulnerability:** The code splits the cookie by `|` and takes the first part as the `$entry_id`. It then fetches `get_transient('mf_entry_' . $entry_id)`.\n6.  **Exposure:** If the transient exists, the plugin renders the submission summary instead of the form, exposing the victim's data.\n\n## 4. Nonce Acquisition Strategy\nTo perform the initial submission (to confirm entry ID increments) or to find the correct page, a nonce is required for the REST API call that MetForm uses.\n\n1.  **Identify Shortcode:** The plugin uses `[metform_form id=\"\u003CID>\"]`.\n2.  **JS Localization:** The plugin localizes data into the `mf_objects` variable.\n3.  **Nonce Retrieval:**\n    - Navigate to the page containing the form.\n    - Execute `browser_eval(\"window.mf_objects?.nonce\")` or `browser_eval(\"window.mf_objects?.rest_nonce\")`.\n4.  **Submission Nonce:** For the `POST \u002Fwp-json\u002Fmetform\u002Fv1\u002Fentries\u002Finsert\u002F` request, the `_wpnonce` header or parameter is required.\n\n## 5. Exploitation Strategy\n\n### Step 1: Discover\u002FCreate Form\nIdentify a published form ID.\n\n### Step 2: Establish Entry ID Baseline\nSubmit the form once to see the current Entry ID.\n- **URL:** `http:\u002F\u002F\u003Cwp-host>\u002Fwp-json\u002Fmetform\u002Fv1\u002Fentries\u002Finsert\u002F`\n- **Method:** `POST`\n- **Payload:** (Standard form fields) + `id: \u003Cform_id>`\n- **Response:** Contains the new `id` (e.g., `100`).\n\n### Step 3: Forge Cookie for Next Entry\nWait for a victim to submit, or target `101`.\n- **Target Cookie Name:** `mf_recent_entry_id`\n- **Target Value:** `101|0` (where `101` is the guessed ID and `0` is for unauthenticated).\n\n### Step 4: Access Sensitive Data\nRequest the form page with the forged cookie.\n- **Tool:** `http_request`\n- **Method:** `GET`\n- **URL:** `http:\u002F\u002F\u003Cwp-host>\u002Fpage-with-form\u002F`\n- **Headers:**\n    - `Cookie: mf_recent_entry_id=101|0`\n- **Expected Response:** The HTML will contain the success message and the data submitted by the victim for entry 101 instead of the empty form.\n\n## 6. Test Data Setup\n1.  **Create a MetForm Form:** \n    - Use `wp post create` to create a `metform-form` post type.\n    - Set meta `metform_form_config` to include some fields (Name, Email).\n2.  **Create a Public Page:**\n    - `wp post create --post_type=page --post_status=publish --post_title=\"Contact\" --post_content='[metform_form id=\"\u003CID_FROM_STEP_1>\"]'`\n3.  **Simulate Victim:**\n    - Perform a submission as an unauthenticated user with sensitive info (e.g., `Name: SecretAgent`, `Email: victim@example.com`).\n\n## 7. Expected Results\n- The HTTP response from Step 4 should contain the string \"SecretAgent\" or \"victim@example.com\".\n- This confirms that the attacker successfully accessed entry data belonging to another submission session by simply providing a forgeable cookie.\n\n## 8. Verification Steps\n1.  **Check Transients:** Use `wp transient get mf_entry_101` to confirm the data exists in the database.\n2.  **Verify Cookie Logic:** Check the response headers of the submission to see how the cookie is set: `Set-Cookie: mf_recent_entry_id=101%7C0; ...`\n\n## 9. Alternative Approaches\n- **Direct REST Access:** Some versions of MetForm might expose `GET \u002Fwp-json\u002Fmetform\u002Fv1\u002Fentries\u002Fget_entry_details?id=101`. Check if this endpoint also relies on the forgeable `mf_recent_entry_id` cookie for authorization.\n- **Transient Guessing:** Since the transient key is `mf_entry_{id}`, if any other part of the plugin (or another plugin) allows reading transients, the data is exposed.\n- **Incrementing Attack:** Script a loop from `last_id + 1` to `last_id + 20` to sweep for any active transients from other users.","MetForm (\u003C= 4.1.0) uses a forgeable cookie value to authenticate access to recent form submission summaries. Because the cookie value consists only of the entry ID and user ID without a cryptographic signature or server-side secret, an unauthenticated attacker can forge the cookie to view sensitive data from other users' submissions stored in transients for up to 15 minutes.","\u002F\u002F Metform\u002FCore\u002FEntries\u002FAction.php\n\u002F\u002F Logic within entry insertion handler:\n$entry_id = $this->insert_entry($form_id, $form_data);\n$user_id = get_current_user_id();\nsetcookie('mf_recent_entry_id', $entry_id . '|' . $user_id, time() + 900, COOKIEPATH, COOKIE_DOMAIN);\nset_transient('mf_entry_' . $entry_id, $form_data, 900);\n\n---\n\n\u002F\u002F Metform\u002FCore\u002FForms\u002FShortcode.php\n\u002F\u002F Logic within render_form() method:\nif (isset($_COOKIE['mf_recent_entry_id'])) {\n    $cookie_val = $_COOKIE['mf_recent_entry_id'];\n    $parts = explode('|', $cookie_val);\n    $entry_id = isset($parts[0]) ? (int)$parts[0] : 0;\n    \n    $entry_data = get_transient('mf_entry_' . $entry_id);\n    if ($entry_data) {\n        \u002F\u002F Renders the sensitive submission data to the page instead of the form\n        return $this->render_success_view($entry_data);\n    }\n}","--- a\u002Fmetform\u002Fcore\u002Fentries\u002Faction.php\n+++ b\u002Fmetform\u002Fcore\u002Fentries\u002Faction.php\n@@ -120,1 +120,2 @@\n-setcookie('mf_recent_entry_id', $entry_id . '|' . $user_id, time() + 900, COOKIEPATH, COOKIE_DOMAIN);\n+$secure_hash = wp_hash($entry_id . '|' . $user_id);\n+setcookie('mf_recent_entry_id', $entry_id . '|' . $user_id . '|' . $secure_hash, time() + 900, COOKIEPATH, COOKIE_DOMAIN);\n\n--- a\u002Fmetform\u002Fcore\u002Fforms\u002Fshortcode.php\n+++ b\u002Fmetform\u002Fcore\u002Fforms\u002Fshortcode.php\n@@ -85,2 +85,5 @@\n-$parts = explode('|', $cookie_val);\n-$entry_id = isset($parts[0]) ? (int)$parts[0] : 0;\n+$parts = explode('|', $cookie_val);\n+if (count($parts) === 3 && hash_equals(wp_hash($parts[0] . '|' . $parts[1]), $parts[2])) {\n+    $entry_id = (int)$parts[0];\n+    $entry_data = get_transient('mf_entry_' . $entry_id);\n+}","1. Identify a public WordPress page containing a MetForm form.\n2. Perform a test submission to determine the current Entry ID sequence (e.g., Entry ID 100).\n3. Predict or guess the next Entry ID (e.g., 101) representing a potential victim submission.\n4. Create a forged cookie named 'mf_recent_entry_id' with the value '101|0' (where 0 denotes an unauthenticated user).\n5. Refresh the page with the forged cookie set. If a victim has submitted the form within the 15-minute transient TTL, the shortcode will render the victim's submitted data in the 'Success Message' area instead of the default form.","gemini-3-flash-preview","2026-05-05 01:26:21","2026-05-05 01:28:17",{"type":34,"vulnerable_version":35,"fixed_version":11,"vulnerable_browse":36,"vulnerable_zip":37,"fixed_browse":38,"fixed_zip":39,"all_tags":40},"plugin","4.1.0","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fmetform\u002Ftags\u002F4.1.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fmetform.4.1.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fmetform\u002Ftags\u002F4.1.1","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fmetform.4.1.1.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fmetform\u002Ftags"]