[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$ffSD00Jp56KUkJf4FHR22mSxht9CEoKZ4g01abm9Izm0":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":29,"research_verified":30,"research_rounds_completed":31,"research_plan":32,"research_summary":9,"research_vulnerable_code":9,"research_fix_diff":9,"research_exploit_outline":9,"research_model_used":33,"research_started_at":34,"research_completed_at":35,"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":30,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":30,"source_links":36},"CVE-2026-25417","profilegrid-user-profiles-groups-and-communities-authenticated-subscriber-stored-cross-site-scripting","ProfileGrid – User Profiles, Groups and Communities \u003C= 5.9.8.1 - Authenticated (Subscriber+) Stored Cross-Site Scripting","The ProfileGrid – User Profiles, Groups and Communities plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 5.9.8.1 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with subscriber-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.","profilegrid-user-profiles-groups-and-communities",null,"\u003C=5.9.8.1","5.9.8.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-03-23 00:00:00","2026-03-26 20:41:24",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Ff6d3c88d-d0a1-4f27-8a9c-df35235b34dc?source=api-prod",4,[22,23,24,25,26,27,28],"admin\u002Fclass-profile-magic-access-options.php","admin\u002Fpartials\u002Fadd-group-tabview.php","includes\u002Fclass-profile-magic-html-generator.php","profile-magic.php","public\u002Fclass-profile-magic-public.php","public\u002Fjs\u002Fpg-messaging.js","readme.txt","researched",false,3,"# Exploitation Research Plan: CVE-2026-25417 (ProfileGrid Stored XSS)\n\n## 1. Vulnerability Summary\nThe **ProfileGrid** plugin for WordPress is vulnerable to **Stored Cross-Site Scripting (XSS)** in versions up to and including 5.9.8.1. The vulnerability stems from two primary issues:\n1.  **Broken Security Logic:** In `admin\u002Fclass-profile-magic-access-options.php`, the function `profile_magic_save_access_meta` contains a logical error in its nonce verification. It uses `if ( sanitize_text_field( $post['pg_meta_box_nonce'] ) || wp_verify_nonce(...) )`, where the `OR` condition ensures that any non-empty string provided for `pg_meta_box_nonce` will satisfy the check, effectively bypassing CSRF and authorization controls for meta updates.\n2.  **Unescaped Output:** In the same file, the function `profile_magic_check_content_access` retrieves the post meta `pm_admin_note_content` and prepends\u002Fappends it to the post content without any sanitization or escaping (e.g., `esc_html` or `wp_kses`).\n\nAuthenticated attackers with **Subscriber-level** permissions can exploit this to inject scripts into \"Blogs\" (the `profilegrid_blogs` custom post type) they own, which will execute for any user viewing the post.\n\n## 2. Attack Vector Analysis\n-   **Endpoint:** WordPress `save_post` hook (triggered via post creation or update).\n-   **Vulnerable Post Type:** `profilegrid_blogs` (User Blogs).\n-   **Vulnerable Parameter:** `pm_admin_note_content` (Post Meta).\n-   **Bypass Parameter:** `pg_meta_box_nonce` (set to any non-empty string).\n-   **Authentication:** Subscriber or above (users who can create blogs).\n-   **Preconditions:** The \"User Blogs\" feature must be enabled, or the attacker must be able to create a `profilegrid_blogs` post.\n\n## 3. Code Flow\n1.  **Entry Point:** An authenticated user submits a request to create or update a `profilegrid_blogs` post. This can occur via the standard WordPress admin or the ProfileGrid frontend blog submission form (usually via shortcode `[pg_user_blog]`).\n2.  **Hook Trigger:** WordPress triggers the `save_post` action.\n3.  **Vulnerable Function:** `Profile_Magic_access_options::profile_magic_save_access_meta( $post_id )` is called.\n4.  **Bypass:** The code checks `if ( sanitize_text_field( $post['pg_meta_box_nonce'] ) || ... )`. Since `sanitize_text_field` returns a string, and a non-empty string evaluates to `true`, the meta-saving logic proceeds.\n5.  **Storage:** The function updates the `pm_admin_note_content` meta key with the raw value from `$_POST['pm_admin_note_content']` (this logic was likely in the truncated portion of the provided source, but is confirmed by the sink).\n6.  **Sink:** When a user views the post, `Profile_Magic_access_options::profile_magic_check_content_access( $content )` is called (hooked to `the_content`).\n7.  **Execution:** The function retrieves the meta: `$admin_note = get_post_meta( $id, 'pm_admin_note_content', true );`. It then constructs a div: `$note = '\u003Cdiv class=\"pg-admin-note\">' . $admin_note . '\u003C\u002Fdiv>';` and modifies `$content` with it. The payload executes in the viewer's browser.\n\n## 4. Nonce Acquisition Strategy\nThe vulnerability effectively **bypasses the nonce check**. In `profile_magic_save_access_meta`, the check is:\n```php\nif ( sanitize_text_field( $post['pg_meta_box_nonce'] ) || wp_verify_nonce(...) )\n```\nBecause of the `||` (OR) operator, if `pg_meta_box_nonce` is present in the request and is not an empty string, `sanitize_text_field` returns a truthy value, and `wp_verify_nonce` is never even evaluated or its failure is ignored.\n\n**Strategy:**\n- No valid nonce is required. Simply include `pg_meta_box_nonce=anything` in the POST request.\n\n## 5. Exploitation Strategy\n\n### Step 1: Create a Blog Post as a Subscriber\nAs a Subscriber, create a `profilegrid_blogs` post to obtain a `post_id`. This can be done via the frontend dashboard provided by ProfileGrid or via WP-CLI for testing.\n\n### Step 2: Inject the Malicious Meta\nSend an authenticated POST request to the WordPress `save_post` entry point (or the ProfileGrid AJAX handler if specific) containing the XSS payload.\n\n**Request Details:**\n-   **URL:** `https:\u002F\u002F\u003Ctarget>\u002Fwp-admin\u002Fpost.php` (if the subscriber can access the dashboard) OR the ProfileGrid frontend submission URL.\n-   **Method:** `POST`\n-   **Headers:** `Content-Type: application\u002Fx-www-form-urlencoded`\n-   **Body Parameters:**\n    -   `action`: `editpost`\n    -   `post_ID`: `\u003CTARGET_POST_ID>`\n    -   `pg_meta_box_nonce`: `bypass_check` (any string)\n    -   `pm_admin_note_content`: `\u003Cscript>alert(document.domain)\u003C\u002Fscript>`\n    -   `pm_admin_note_position`: `top`\n\n### Step 3: Trigger the XSS\nNavigate to the permalink of the `profilegrid_blogs` post.\n\n## 6. Test Data Setup\n1.  **Enable User Blogs:** Ensure ProfileGrid is configured to allow users to submit blogs.\n2.  **Create Subscriber:** Create a user with the `subscriber` role.\n3.  **Create Blog Post:**\n    ```bash\n    # As an admin, create a blog post for the subscriber\n    wp post create --post_type=profilegrid_blogs --post_status=publish --post_title=\"XSS Test Post\" --post_author=\u003CSUBSCRIBER_ID>\n    ```\n4.  **Identify Post ID:** Use `wp post list --post_type=profilegrid_blogs` to find the ID.\n\n## 7. Expected Results\n-   The server should process the update request and return a 200 or 302 (redirect).\n-   When viewing the post, the HTML source should contain:\n    `\u003Cdiv class=\"pg-admin-note\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>\u003C\u002Fdiv>`\n-   The browser should trigger the `alert` box.\n\n## 8. Verification Steps\nAfter the exploit attempt, verify the database state using WP-CLI:\n```bash\n# Check if the malicious meta was stored\nwp post meta get \u003CPOST_ID> pm_admin_note_content\n```\n\n## 9. Alternative Approaches\nIf the Subscriber cannot reach `wp-admin\u002Fpost.php`, the ProfileGrid frontend submission logic must be used.\n-   **Shortcode for Nonce (if the bypass is patched in some parts):** If a valid nonce is needed for the frontend form, use `browser_navigate` to a page with `[pg_user_blog]` and extract `pm_ajax_object.nonce`.\n-   **AJAX Handler:** Check for AJAX actions registered in `Profile_Magic_Public`. The localized object `pm_ajax_object` in `public\u002Fclass-profile-magic-public.php` suggests AJAX-heavy interaction.\n-   **Parameter variations:** Try `pm_content_access` or `pm_content_access_group` if `pm_admin_note_content` is filtered, although the source shows the admin note is the most likely unescaped sink.","gemini-3-flash-preview","2026-04-17 23:41:09","2026-04-17 23:41:35",{"type":37,"vulnerable_version":38,"fixed_version":11,"vulnerable_browse":39,"vulnerable_zip":40,"fixed_browse":41,"fixed_zip":42,"all_tags":43},"plugin","5.9.8.1","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fprofilegrid-user-profiles-groups-and-communities\u002Ftags\u002F5.9.8.1","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fprofilegrid-user-profiles-groups-and-communities.5.9.8.1.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fprofilegrid-user-profiles-groups-and-communities\u002Ftags\u002F5.9.8.2","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fprofilegrid-user-profiles-groups-and-communities.5.9.8.2.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fprofilegrid-user-profiles-groups-and-communities\u002Ftags"]